Sunday, March 31, 2019

C++ chaining of the operator










I'm currently programming a logger class, but the operator<< method causes a compiler error. Here's a minimized version of the class, in file "logger.h":




#include 
class Logger {
public:
Logger() : m_file(std::cout) {}

template
Logger &operator<<(const T &a) {
m_file< return *this;
}


protected:
std::ostream& m_file;
};


It is included in my main.cpp and works perfecly when I output a string literal:



log << "hi"; 



However, the following won't compile.



#include "logger.h"
int main() {
Logger log;

log << std::endl;
}



The g++ compiler reports:




src/main.cpp:5: error: no match for 'operator<<' in 'log << std::endl'



Answer



Your problem is not about the chain of << , a single log << endl would also cause the problem. It is because std::endl is a template function:



template 

basic_ostream& endl(basic_ostream& os);


One of the overload of operator<< in basic_ostream is:



template  >
class basic_ostream : virtual public basic_ios {
public:
basic_ostream& operator<<(
basic_ostream& (*pf)(basic_ostream&));

//...
};


So the template parameters can be deduced when std::cout< is used. However, when the left side is the class Logger, the compile cannot deduce the template parameters of endl. Explicitly give the template parameters can let program compile and work:



#include 
class Logger
{
public:

std::ostream &m_file;
Logger(std::ostream &o = std::cout):m_file(o){};

template
Logger &operator<<(const T &a) {
m_file< return *this;
}
};


int main()
{
Logger log;
log< >;
log<<"hi"<<" stackoverflow"< >;
return 0;
}


Or you can add a new overload of operator<< in class Logger to let compiler deduce the template parameters of std::endl:




#include 
class Logger
{
public:
std::ostream &m_file;
Logger(std::ostream &o = std::cout):m_file(o){};

template
Logger &operator<<(const T &a) {

m_file< return *this;
}

Logger &operator<<(std::ostream& (*pf) (std::ostream&)){
m_file< return *this;
}
};


int main()
{
Logger log;
log< log<<"hi"<<" stackoverflow"< return 0;
}


Also, if you don't need the output to be flushed immediately, you can use '\n' instead of endl.



No comments:

Post a Comment

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...