C++链接运算符<< for std :: cout like usage

Tux*_*xer 11 c++ operators chaining

可能重复:
当重载operator << Operator重载时,std :: endl的类型未知

我目前正在编写一个记录器类,但该operator<<方法会导致编译器错误.这是类的最小化版本,在文件"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;
};
Run Code Online (Sandbox Code Playgroud)

它包含在我的main.cpp中,并在输出字符串文字时完美地工作:

log << "hi"; 
Run Code Online (Sandbox Code Playgroud)

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

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

    log << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

g ++编译器报告:

src/main.cpp:5:错误:'log << std :: endl'中'operator <<'不匹配

fef*_*efe 13

你的问题不在于链条<<,单一log << endl也会导致问题.这是因为std::endl是模板功能:

template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);
Run Code Online (Sandbox Code Playgroud)

其中一个过载operator<<basic_ostream是:

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>&));
//...
};
Run Code Online (Sandbox Code Playgroud)

因此,可以在std::cout<<std::endl使用时推导出模板参数.但是,当左侧是class Logger,编译时无法推断出模板参数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;
    }
};

int main()
{
    Logger log;
    log<<std::endl<char, std::char_traits<char> >;
    log<<"hi"<<" stackoverflow"<<std::endl<char, std::char_traits<char> >;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

或者你可以添加一个新的重载operator<<in class Logger让编译器推导出模板参数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;
}
Run Code Online (Sandbox Code Playgroud)

此外,如果您不需要立即刷新输出,则可以使用'\n'代替endl.

  • "另外,你可以使用'\n'代替`endl`." 如果OP想要确保刷新输出缓冲区,就不像我[最近学到的](http://stackoverflow.com/q/8311058/440558). (2认同)