2011-12-07 52 views
8

Possible Duplicate:
std::endl is of unknown type when overloading operator<<
Operator overloadingC++操作<<性病的链接::法院像使用

我目前编程记录器类,但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; 
}; 

它包含在我的main.cpp和作品perfecly当我输出一个字符串:

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'

回答

11

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

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

一个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>&)); 
//... 
}; 

所以当使用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; 
} 

也可以在class Loggeroperator<<一个新的重载让编译器推断的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

+2

“此外,还可以使用 '\ n' 而不是'endl'。”如果OP想要确保输出缓冲区被刷新,请不要,因为我[最近了解到](http://stackoverflow.com/q/8311058/440558)。 –

+0

对,我将它添加到我的答案中。 – fefe

+0

谢谢,它的作品:) – Tuxer