2011-12-07 6 views
8

Possible Duplicate:
std::endl is of unknown type when overloading operator<<
Operator overloadingC++ encadenamiento del operador << para std :: cout como el uso

Actualmente estoy programando una clase de logger, pero el método operator<< provoca un error de compilación. Aquí hay una versión minimizada de la clase, en el archivo "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; 
}; 

Se incluye en mi main.cpp y trabaja perfecly cuando la salida una cadena literal:

log << "hi"; 

Sin embargo, lo siguiente no compilará.

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

    log << std::endl; 
} 

g ++ informes del compilador:

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

Respuesta

11

Su problema no es sobre la cadena de <<, una sola log << endl también podría causar el problema. Es porque std::endl es una función de plantilla:

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

Uno de la sobrecarga de operator<< en basic_ostream es:

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

Así que los parámetros de plantilla se puede deducir cuando se utiliza std::cout<<std::endl. Sin embargo, cuando el lado izquierdo es el class Logger, la compilación no puede deducir los parámetros de plantilla de endl. Explícitamente dar los parámetros de plantilla pueden dejar el programa compila y trabajo:

#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; 
} 

O puede agregar una nueva sobrecarga de operator<< en class Logger dejar compilador de deducir los parámetros de plantilla de 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; 
} 

Además, si no necesita que la salida se descargue inmediatamente, puede usar '\ n' en lugar de endl.

+2

"Además, se puede usar '\ n' en lugar de' endl'." No si el PO quiere asegurarse de que los buffers de salida se vacían, como yo [aprendido recientemente] (http://stackoverflow.com/q/8311058/440558). –

+0

Correcto, lo agregaré a mi respuesta. – fefe

+0

Gracias, funciona :) – Tuxer

0

El error es causado por std::endl que es una función. Consulte:

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

+0

'std :: cout' es una función? – jalf

+3

Creo que Eric quería decir que 'std :: endl' es una función. –

+0

Supongo que quiere decir "' std :: endl' es una plantilla de función "? –

Cuestiones relacionadas