运算符的C ++<< std::cout

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

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
std::endl is of unknown type when overloading operator<< Operator overloading

我目前正在编程一个logger类,但是operator<<方法会导致编译器错误。这是类的最小化版本,在文件"logger.h"中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#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;
};

它包含在main.cpp中,并在输出字符串文字时执行:

1
log <<"hi";

但是,以下内容无法编译。

1
2
3
4
5
6
#include"logger.h"
int main() {
    Logger log;

    log << std::endl;
}

G++编译器报告:

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


你的问题不在于<<的链,单个log << endl也会引起问题。这是因为std::endl是一个模板函数:

1
2
template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);

basic_ostreamoperator<<的过载之一是:

1
2
3
4
5
6
7
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>&));
//...
};

因此,在使用std::cout<时,可以推导出模板参数。但是,当左边是class Logger时,编译程序无法推导endl的模板参数。显式给出模板参数可以让程序编译和工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#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;
}

或者可以在class Logger中添加新的operator<<重载,让编译器推断std::endl的模板参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#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;
}

另外,如果不需要立即刷新输出,可以使用''而不是endl


错误是由函数std::endl引起的。参考:

当重载运算符时,std::endl是未知类型<<