Possible Duplicate:
std::endl is of unknown type when overloading operator<<
Operator overloading
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 <iostream>
class Logger {
public:
Logger() : m_file(std::cout) {}
template <typename T>
Logger &operator<<(const T &a) {
m_file<<a;
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'
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 <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);
One of the overload of operator<<
in basic_ostream
is:
template <class charT, class traits = char_traits<charT> >
class basic_ostream : virtual public basic_ios<charT,traits> {
public:
basic_ostream<charT,traits>& operator<<(
basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
//...
};
So the template parameters can be deduced when std::cout<<std::endl
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 <iostream>
class Logger
{
public:
std::ostream &m_file;
Logger(std::ostream &o = std::cout):m_file(o){};
template <typename T>
Logger &operator<<(const T &a) {
m_file<<a;
return *this;
}
};
int main()
{
Logger log;
log<<std::endl<char, std::char_traits<char> >;
log<<"hi"<<" stackoverflow"<<std::endl<char, std::char_traits<char> >;
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 <iostream>
class Logger
{
public:
std::ostream &m_file;
Logger(std::ostream &o = std::cout):m_file(o){};
template <typename T>
Logger &operator<<(const T &a) {
m_file<<a;
return *this;
}
Logger &operator<<(std::ostream& (*pf) (std::ostream&)){
m_file<<pf;
return *this;
}
};
int main()
{
Logger log;
log<<std::endl;
log<<"hi"<<" stackoverflow"<<std::endl;
return 0;
}
Also, if you don't need the output to be flushed immediately, you can use '\n' instead of endl
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With