C++ 重载 operator<< 时 std::endl 是未知类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1134388/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
std::endl is of unknown type when overloading operator<<
提问by Kazoom
I overloaded operator <<
我重载了运算符 <<
template <Typename T>
UIStream& operator<<(const T);
UIStream my_stream;
my_stream << 10 << " heads";
Works but:
有效但:
my_stream << endl;
Gives compilation error:
给出编译错误:
error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'UIStream' (or there is no acceptable conversion)
错误 C2678:二进制“<<”:未找到采用“UIStream”类型的左侧操作数的运算符(或没有可接受的转换)
What is the work around for making my_stream << endl
work?
工作的解决方法是my_stream << endl
什么?
回答by GManNickG
std::endl
is a function and std::cout
utilizes it by implementing operator<<
to take a function pointer with the same signature as std::endl
.
std::endl
是一个函数,std::cout
并通过实现operator<<
采用与 具有相同签名的函数指针来利用它std::endl
。
In there, it calls the function, and forwards the return value.
在那里,它调用函数,并转发返回值。
Here is a code example:
这是一个代码示例:
#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;
}
Hopefully this gives you a better idea of how these things work.
希望这能让你更好地了解这些东西是如何工作的。
回答by AProgrammer
The problem is that std::endl
is a function template, as your operator <<
is. So when you write:
问题在于它std::endl
是一个函数模板,就像您的操作员一样<<
。所以当你写:
my_stream << endl;
you'll like the compiler to deduce the template parameters for the operator
as well as for endl
. This isn't possible.
您会喜欢编译器为运算符和 for 推导出模板参数endl
。这是不可能的。
So you have to write additional, non template, overloads of operator <<
to
work with manipulators. Their prototype will look like:
所以你必须编写额外的、非模板的、运算符的重载<<
来与操纵器一起工作。他们的原型将如下所示:
UIStream& operator<<(UIStream& os, std::ostream& (*pf)(std::ostream&));
(there are two others, replacing std::ostream
by std::basic_ios<char>
and
std::ios_base
, which you have also to provide if you want to allow all
manipulators) and their implementation will be very similar to the one of
your templates. In fact, so similar that you can use your template for
implementation like this:
(还有另外两个,std::ostream
由std::basic_ios<char>
and
替换,std::ios_base
如果您想允许所有操纵器,您还必须提供它们)并且它们的实现将与您的模板之一非常相似。事实上,非常相似,您可以使用您的模板来实现这样的:
typedef std::ostream& (*ostream_manipulator)(std::ostream&);
UIStream& operator<<(UIStream& os, ostream_manipulator pf)
{
return operator<< <ostream_manipulator> (os, pf);
}
A final note, often writing a custom streambuf
is often a better way to
achieve what one try to achieve applying to technique you are using.
最后一点,通常编写自定义streambuf
通常是实现人们尝试实现的应用到您正在使用的技术的更好方法。
回答by Lucas Casagrande
I did this to solve my problem, here is part of my code:
我这样做是为了解决我的问题,这是我的代码的一部分:
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;
...
}
I got the reference in here http://www.cplusplus.com/forum/general/49590/
我在这里得到了参考http://www.cplusplus.com/forum/general/49590/
Hope this can help someone.
希望这可以帮助某人。
回答by EFraim
See herefor better ways of extending IOStreams. (A bit outdated, and tailored for VC 6, so you will have to take it with a grain of salt)
有关扩展 IOStreams 的更好方法,请参见此处。(有点过时了,是为 VC 6 量身定做的,所以你必须小心翼翼地接受它)
The point is that to make functors work (and endl, which both outputs "\n" and flushes is a functor) you need to implement the full ostream interface.
关键是要使函子工作(和 endl,输出 "\n" 和刷新都是函子),您需要实现完整的 ostream 接口。
回答by Troubadour
The std
streams are not designed to be subclassed as they have no virtual methods so I don't think you'll get too far with that. You can try aggregating a std::ostream to do the work though.
该std
流不设计,因为他们没有虚方法被子类,所以我不认为你会得到与该太远。不过,您可以尝试聚合 std::ostream 来完成这项工作。
To make endl
work you need to implement a version of operator<<
that takes a pointer-to-function as that is how the manipulators such as endl
are handled i.e.
为了endl
工作,你需要实现一个版本,operator<<
它需要一个指向函数的指针,因为这就是操纵器endl
的处理方式,即
UStream& operator<<( UStream&, UStream& (*f)( UStream& ) );
or
或者
UStream& UStream::operator<<( UStream& (*f)( UStream& ) );
Now std::endl
is a function that takes and returns a reference to a std::basic_ostream so that won't work directly with your stream so you'll need to make your own version which calls through to the std::endl
version in your aggregated std::iostream
.
现在std::endl
是一个函数,它接受并返回对 std::basic_ostream 的引用,因此它不能直接与您的流一起使用,因此您需要制作自己的版本,该std::endl
版本调用您的聚合std::iostream
.
Edit: Looks likes GMan's answer is better. He gets std::endl
working too!
编辑:看起来 GMan 的答案更好。他也开始std::endl
工作了!
回答by AlwaysLearning
In addition to the accepted answer, with C++11 it is possible to overload operator<<
for the type:
除了接受的答案之外,使用 C++11 还可以重载operator<<
该类型:
decltype(std::endl<char, std::char_traits<char>>)