当重载operator <<时,std :: endl是未知的types

我重载了operator <<

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

作品,但是:

 my_stream << endl; 

给汇编错误:

错误C2678:二进制'<<':找不到操作符findtypes为'UIStream'的左手操作数(或没有可接受的转换)

什么是使my_stream << endl工作的工作?

std::endl是一个函数, std::cout通过实现operator<<来使用与std::endl具有相同签名的函数指针。

在那里,它调用函数,并转发返回值。

这是一个代码示例:

 #include <iostream> struct MyStream { template <typename T> 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<char, std::char_traits<char> > 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; } 

希望这可以让你更好地了解这些东西是如何工作的。

问题是std::endl是一个函数模板,因为你的operator <<是。 所以当你写:

 my_stream << endl; 

你会喜欢编译器推导运算符以及endl的模板参数。 这是不可能的。

所以你必须编写额外的,非模板的operator <<重载操作符。 他们的原型将如下所示:

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

(还有另外两个,用std::ostream std::basic_ios<char>std::ios_basereplacestd::ostream ,如果你想允许所有的操纵器,你也可以提供它们),它们的实现将非常类似于你的模板。 事实上,如此类似,你可以使用你的模板来实现这样的事情:

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

最后一点,经常写一个自定义的streambuf往往是一个更好的方法来实现你正在使用的技术,试图实现。

看到这里更好的方式来扩展IOStreams。 (有点过时了,为VC 6量身打造,所以你必须拿一粒盐)

关键是要使函子工作(和endl,这两个输出“\ n”和冲洗是一个仿函数),你需要实现完整的ostream接口。

stdstream不是被devise为subclassed的,因为他们没有虚拟方法,所以我不认为你会得到太多的。 你可以尝试聚合一个std :: ostream来完成这项工作。

为了使endl能够工作,你需要实现一个operator<<operator<< ,这个operator<<指向的函数就像endl这样的operator<<是如何处理的

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

要么

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

现在, std::endl是一个函数,它接受并返回一个std :: basic_ostream的引用,这样就不会直接与你的stream进行工作,所以你需要创build自己的版本来调用std::endl版本在你的聚合std::iostream

编辑:看起来像GMan的答案是更好的。 他得到std::endl工作!

我这样做是为了解决我的问题,这里是我的代码的一部分:

  template<typename T> 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; ... } 

我在这里得到了参考http://www.cplusplus.com/forum/general/49590/

希望这可以帮助别人。

除了被接受的答案之外,在C ++ 11中,还可以重载operator<<

 decltype(std::endl<char, std::char_traits<char>>)