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<
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