【问题标题】:C++ chaining of the operator << for std::cout like usage [duplicate]运算符 << 的 C++ 链接用于 std::cout 类似用法 [重复]
【发布时间】:2012-01-14 23:57:27
【问题描述】:

可能重复:
std::endl is of unknown type when overloading operator<<
Operator overloading

我目前正在编写一个记录器类,但operator&lt;&lt; 方法会导致编译器错误。这是该类的最小化版本,在文件“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;
};

它包含在我的 main.cpp 中,并且在我输出字符串文字时完美运行:

log << "hi"; 

但是,以下内容不会编译。

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

    log << std::endl;
}

g++ 编译器报告:

src/main.cpp:5: 错误: 'log

【问题讨论】:

    标签: c++ operators chaining


    【解决方案1】:

    您的问题与 &lt;&lt; 的链无关,单个 log &lt;&lt; endl 也会导致问题。这是因为std::endl是一个模板函数:

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

    operator&lt;&lt;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>&));
    //...
    };
    

    所以使用std::cout&lt;&lt;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;
    }
    

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

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

    【讨论】:

    • "另外,您可以使用 '\n' 代替 endl。"如果 OP 想要确保刷新输出缓冲区,则不是,因为我 recently learned
    • 好的,我会把它添加到我的答案中。
    【解决方案2】:

    错误是由std::endl 引起的,它是一个函数。参考:

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

    【讨论】:

    • 我认为 Eric 想说std::endl 是一个函数。
    • 我猜你的意思是“std::endl 是一个函数模板”?
    • @Mike,好吧,std::endl 本身并不是模板。它接受并返回一个模板类,是的,但它只是一个成员函数。它的声明看起来像template&lt;class charT, class traits&gt; basic_ostream&lt;charT, traits&gt;&amp; endl(basic_ostream&lt;charT, traits&gt;&amp; os);
    • @jalf,纠正措辞,我的意思是“std::endl”;)
    • @FrédéricHamidi:在我看来,这很像函数模板。它不是任何事物的成员。
    猜你喜欢
    • 2020-01-25
    • 2011-09-30
    • 1970-01-01
    • 2022-01-20
    • 2019-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多