std :: endl é de tipo desconhecido ao sobrecarregar o operador <<

Sobrecarregei o operador <<

template  UIStream& operator<<(const T); UIStream my_stream; my_stream << 10 << " heads"; 

Funciona, mas:

 my_stream << endl; 

Dá erro de compilation:

erro C2678: binário ‘<<': nenhum operador encontrado que usa um operando à esquerda do tipo 'UIStream' (ou não há conversão aceitável)

Qual é o trabalho para fazer my_stream << endl work?

std::endl é uma function e std::cout utiliza implementando operator< < para pegar um ponteiro de function com a mesma assinatura std::endl .

Lá, ele chama a function e encaminha o valor de retorno.

Aqui está um exemplo de código:

 #include  struct MyStream { template  MyStream& operator< <(const T& x) { std::cout << x; return *this; } // function that takes a custom stream, and returns it typedef MyStream& (*MyStreamManipulator)(MyStream&); // take in a function with the custom signature MyStream& operator<<(MyStreamManipulator manip) { // call the function, and return it's value return manip(*this); } // define the custom endl for this stream. // note how it matches the `MyStreamManipulator` // function signature static MyStream& endl(MyStream& stream) { // print a new line std::cout << std::endl; // do other stuff with the stream // std::cout, for example, will flush the stream stream << "Called MyStream::endl!" << std::endl; return stream; } // this is the type of std::cout typedef std::basic_ostream > CoutType; // this is the function signature of std::endl typedef CoutType& (*StandardEndLine)(CoutType&); // define an operator< < to take in std::endl MyStream& operator<<(StandardEndLine manip) { // call the function, but we cannot return it's value manip(std::cout); return *this; } }; int main(void) { MyStream stream; stream << 10 << " faces."; stream << MyStream::endl; stream << std::endl; return 0; } 

Espero que isso lhe dê uma idéia melhor de como essas coisas funcionam.

O problema é que std::endl é um modelo de function, como seu operador < < é. Então, quando você escreve:

 my_stream < < endl; 

Você vai gostar do compilador para deduzir os parâmetros do modelo para o operador, bem como para endl . Isso não é possível.

Então você tem que escrever sobrecargas adicionais do operador, não modelo, < < para trabalhar com manipuladores. Seu protótipo será parecido com:

 UIStream& operator< <(UIStream& os, std::ostream& (*pf)(std::ostream&)); 

(há dois outros, substituindo std::ostream por std::basic_ios e std::ios_base , que você também deve fornecer se você quiser permitir todos os manipuladores) e sua implementação será muito semelhante à de seus modelos. Na verdade, é tão semelhante que você pode usar seu modelo para implementação assim:

 typedef std::ostream& (*ostream_manipulator)(std::ostream&); UIStream& operator< <(UIStream& os, ostream_manipulator pf) { return operator<<  (os, pf); } 

Uma nota final, muitas vezes escrever um streambuf personalizado é muitas vezes uma maneira melhor de alcançar o que se tenta aplicar à técnica que você está usando.

Eu fiz isso para resolver o meu problema, aqui faz parte do meu código:

  template CFileLogger &operator < <(const T value) { (*this).logFile << value; return *this; } CFileLogger &operator <<(std::ostream& (*os)(std::ostream&)) { (*this).logFile << os; return *this; } 

Main.cpp

 int main(){ CFileLogger log(); log < < "[WARNINGS] " << 10 << std::endl; log << "[ERRORS] " << 2 << std::endl; ... } 

Eu tenho a referência aqui http://www.cplusplus.com/forum/general/49590/

Espero que isso possa ajudar alguém.

Veja aqui as melhores maneiras de estender o IOStreams. (Um pouco desatualizado e adaptado para VC 6, então você terá que levá-lo com um grão de sal)

O ponto é que para fazer funcionar os functores (e endl, que ambas as saídas “\ n” e flushes é um functor) você precisa implementar a interface completa do ostream.

Os streams std não são projetados para serem subclassificados, pois não possuem methods virtuais, então eu não acho que você irá muito longe com isso. Você pode tentar agregar um std :: ostream para fazer o trabalho.

Para fazer o trabalho endl você precisa implementar uma versão do operator< < que leve um ponteiro para function, pois é assim que os manipuladores, como o endl são manipulados.

 UStream& operator< <( UStream&, UStream& (*f)( UStream& ) ); 

ou

 UStream& UStream::operator< <( UStream& (*f)( UStream& ) ); 

Agora o std::endl é uma function que pega e retorna uma referência a um std :: basic_ostream para que não funcione diretamente com o seu stream, então você precisará criar sua própria versão, que std::endl versão std::endl em seu std::iostream agregado.

Edit: Parece que a resposta do GMan é melhor. Ele também std::endl !

Além da resposta aceita, com o C ++ 11 é possível sobrecarregar o operator< < para o tipo:

 decltype(std::endl>)