C++重载<<操作符以实现类似于std::cout的链式调用

26 浏览
0 Comments

C++重载<<操作符以实现类似于std::cout的链式调用

这个问题已经有答案了:

可能是重复问题:

当重载operator<<时,std::endl是未知类型

运算符重载

我正在编写一个日志记录器类,但是operator<<方法导致编译错误。下面是一个简化版的类,位于文件“logger.h”中:

#include 
class Logger {
public:
    Logger() : m_file(std::cout) {}
    template 
    Logger &operator<<(const T &a) {
        m_file<<a;
        return *this;
    }
protected:
    std::ostream& m_file;
};

当我输出一个字符串字面值时,它被包含在我的main.cpp中,可以工作得很好:

log << "hi"; 

但是以下内容无法编译。

#include "logger.h"
int main() {
    Logger log;
    log << std::endl;
}

g++编译器报告:

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

admin 更改状态以发布 2023年5月22日
0
0 Comments

错误原因是std::endl是一个函数。请参考:

重载operator<<时,std::endl是未知类型

0
0 Comments

你的问题不是关于 << 链式操作符的问题,单独使用 log << endl 也会导致问题出现。这是因为 std::endl 是一个模板函数:

template 
basic_ostream& endl(basic_ostream& os);

basic_ostream 中 operator<< 的重载之一是:

template  >
class basic_ostream : virtual public basic_ios {
public:
    basic_ostream& operator<<(
    basic_ostream& (*pf)(basic_ostream&));
//...
};

所以当使用 std::cout << std::endl 时,模板参数可以被推导。但是,当左侧是 class Logger 时,编译器无法推导出 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< >;
    log<<"hi"<<" stackoverflow"< >;
    return 0;
}

或者你可以添加一个 class Logger 中 operator<< 的重载,让编译器推导出 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<

另外,如果你不需要立即刷新输出,可以使用 '\n' 替代 endl。

0