C++ chaining of the operator << for std::cout like usage

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 .


The error is caused by std::endl which is a function. Refer to:

std::endl is of unknown type when overloading operator<<

链接地址: http://www.djcxy.com/p/12698.html

上一篇: 在C ++中重载提取操作符>>

下一篇: 用于std :: cout的运算符<< C ++链接