c++11 - msvc++ doesn't see overloaded operator<< -
i'm porting piece of code written linux , compiled gcc v4.8.2 (using -std=c++11) windows. part of overloaded operator<<
msvc++ 2013 doesn't agree with. condensed example below.
we've defined custom stream class supports standard stream manipulator functions. reason we've overloaded operator<<
accepts function pointer second argument.
if define templated overload of operator<< . msvc++ complains:
error c2676: binary '<<' : 'foobar' not define operator or conversion type acceptable predefined operator
but if specify type of second argument std::ostream
instead of templated std::basis_ostream<..,..>
code works expected.
at first thought had messed template arguments. however, if define arbitrary template function instead of overload of operator<<
code compiles fine. what's going on here?
example
#include "stdafx.h" #include <iostream> #include <sstream> #include <string> struct foobar { std::stringstream s_; }; /* causes compiler error c2676 template <typename chart = char, typename traits = std::char_traits<chart> > foobar& operator<<(foobar& foo, std::basic_ostream<chart, traits>& (*manip)(std::basic_ostream<chart, traits>&)) { foo.s_ << manip; return foo; } */ /* works intendend */ foobar& operator<<(foobar& foo, std::ostream& (*manip)(std::ostream&)) { foo.s_ << manip; return foo; } /* works */ template <typename chart = char, typename traits = std::char_traits<chart> > foobar& qux(foobar& foo, std::basic_ostream<chart, traits>& (*manip)(std::basic_ostream<chart, traits>&)) { foo.s_ << manip; return foo; } int _tmain(int argc, _tchar* argv[]) { foobar foo; foo << std::endl; qux(foo, std::endl); return 0; }
there appears kind of bug default arguments, overloaded operators, , template function parameter overload resolution.
these complex, sort of understandable.
the news shouldn't taking just any iomanip there -- should taking specific one.
you can either hard code it, or deduce so:
// nth type template instance: template<class...>struct types{using type=types;}; template<class t, size_t n> struct nth{}; template<class t, size_t n> using nth_t=typename nth<t,n>::type; template<template<class...>class z, class t0, class...ts, size_t n> struct nth<z<t0,ts...>,n>:nth<types<ts...>,n-1>{}; template<template<class...>class z, class t0, class...ts> struct nth<z<t0,ts...>,0>{using type=t0;}; // string type, produce compatible basic_stream type: template<class string> using compat_stream = std::basic_ostream<nth_t<string,0>, nth_t<string,1>>; // type t, produce signature of function pointer // pass-through manipulates it: template<class t> using manip_f = t&(*)(t&); // string type, produce compatible io-manipulator: template<class string> using io_manip_f = manip_f< compat_stream<string> >; // return of foobar: struct foobar { std::stringstream s_; // type of manipulators compatible s_: using manip_f = io_manip_f<std::stringstream> manip; // koenig operator<<: friend foobar& operator<<( foobar& self, manip_f manip ) { self.s_ << manip; return self; } };
Comments
Post a Comment