C ++ template statement compilation error

I am trying to create a C ++ class similar to std::ostream that will take its input and write the two std::ostream specified in the constructor. Here it is, along with the corresponding operator<< template:

 struct SplitStream { SplitStream(std::ostream & a_, std::ostream & b_) : a(a_), b(b_) {} std::ostream & a, & b; }; template<class T> const SplitStream & operator << (const SplitStream & sp, const T & x) { sp.a << x; sp.b << x; return sp; } 

A few lines below this code, I am trying to use this class:

 void foo(SplitStream & out) { double some_double = 1.23; out << "bar" << some_double << std::endl; } 

And I get this rather cryptic error:

 ... error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'const SplitStream' (or there is no acceptable conversion) ... 

What am I doing wrong? I tried to define operator<< without consts, and it also did not compile.

+4
source share
2 answers

The immediate problem is that std::endl not an object, and the function template declares something like this:

 template <typename cT, typename Traits> std::basic_ostream<cT, Traits>& endl(std::basic_ostream<cT, Traits>&); 

To use a pointer to a function like this, you must output the template arguments. To this end, the class std::basic_ostream<cT, Traits> declared suitable overloads for operator<<() :

 template <typename cT, typename Traits> std::basic_ostream<cT, Traits>& std::baisic_ostream<cT, Traits>::operator<< ( std::basic_ostream<cT, Traits>& (*manip)(std::basic_ostream<cT, Traits>&)); 

In this way, the compiler can infer the correct instance when the std::endl function is std::endl .

However, everything that is completely inappropriate, because what you are trying to do is better to do in a completely different way! You must create a suitable stream buffer and use the built std::ostream with this custom stream buffer. Below is a complete example of how to do this correctly (I published it earlier, but only a couple of dozen times ...):

 #include <streambuf> struct teebuf : std::streambuf { std::streambuf* sb1_; std::streambuf* sb2_; teebuf(std::streambuf* sb1, std::streambuf* sb2) : sb1_(sb1), sb2_(sb2) { } int overflow(int c) { typedef std::streambuf::traits_type traits; bool rc(true); if (!traits::eq_int_type(traits::eof(), c)) { traits::eq_int_type(this->sb1_->sputc(c), traits::eof()) && (rc = false); traits::eq_int_type(this->sb2_->sputc(c), traits::eof()) && (rc = false); } return rc? traits::not_eof(c): traits::eof(); } int sync() { bool rc(true); this->sb1_->pubsync() != -1 || (rc = false); this->sb2_->pubsync() != -1 || (rc = false); return rc? 0: -1; } }; #include <fstream> #include <iostream> int main() { std::ofstream fout("tee.txt"); teebuf sbuf(fout.rdbuf(), std::cout.rdbuf()); std::ostream out(&sbuf); out << "hello, world!\n"; } 
+5
source

Another answer is better, but for completeness:

The references to SplitStream in your <statement should not be const, since they modify the streams that the structure contains.

 template<class T> SplitStream & operator << (SplitStream & sp, const T & x) { sp.a << x; sp.b << x; return sp; } 
0
source

All Articles