Jos*_*ino 10 c++ operator-overloading stream endl
我正在尝试编写自己的日志记录类并将其用作流:
logger L;
L << "whatever" << std::endl;
Run Code Online (Sandbox Code Playgroud)
这是我开始使用的代码:
#include <iostream>
using namespace std;
class logger{
public:
template <typename T>
friend logger& operator <<(logger& log, const T& value);
};
template <typename T>
logger& operator <<(logger& log, T const & value) {
// Here I'd output the values to a file and stdout, etc.
cout << value;
return log;
}
int main(int argc, char *argv[])
{
logger L;
L << "hello" << '\n' ; // This works
L << "bye" << "alo" << endl; // This doesn't work
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是我在尝试编译时遇到错误,说没有operator <<的定义(当使用std :: endl时):
pruebaLog.cpp:31: error: no match for ‘operator<<’ in ‘operator<< [with T = char [4]](((logger&)((logger*)operator<< [with T = char [4]](((logger&)(& L)), ((const char (&)[4])"bye")))), ((const char (&)[4])"alo")) << std::endl’
Run Code Online (Sandbox Code Playgroud)
所以,我一直在尝试重载operator <<来接受这种流,但这让我很生气.我不知道怎么做.例如,我一直在ostream头文件中定义std :: endl,并用这个头写了一个函数:
logger& operator <<(logger& log, const basic_ostream<char,char_traits<char> >& (*s)(basic_ostream<char,char_traits<char> >&))
Run Code Online (Sandbox Code Playgroud)
但没有运气.我尝试使用模板而不是直接使用char,并尝试使用"const ostream&os",并没有尝试.
让我烦恼的另一件事是,在错误输出中,operator <<的第一个参数发生了变化,有时候它是对指针的引用,有时看起来像是双引用...
endl
是一个奇怪的野兽.它不是一个恒定的值.事实上,在所有事情上,它都是一种功能.您需要一个特殊的覆盖来处理以下应用程序endl
:
logger& operator<< (logger& log, ostream& (*pf) (ostream&))
{
cout << pf;
return log;
}
Run Code Online (Sandbox Code Playgroud)
这接受插入一个带ostream
引用并返回ostream
引用的函数.那是什么endl
.
编辑:回应FranticPedantic有趣的问题"为什么编译器不能自动推断出这个?".原因是,如果你深入研究,endl
实际上它本身就是一个模板函数.它被定义为:
template <class charT, class traits>
basic_ostream<charT,traits>& endl ( basic_ostream<charT,traits>& os );
Run Code Online (Sandbox Code Playgroud)
也就是说,它可以ostream
作为其输入和输出.所以,问题不在于编译器不能推断,T const &
可能是一个函数指针,但它无法找出哪个 endl
你的意思是传递作者的模板版本operator<<
的问题,提出将接受一个指向任何功能作为它的第二个参数,但同时,endl
模板代表了一组无限的潜在函数,因此编译器无法在那里做任何有意义的事情.
提供operator<<
其第二个参数的特殊重载与模板的特定实例化匹配endl
允许调用解析.
endl
是一个IO操纵器,它是一个仿函数,通过引用接受流,对它执行一些操作,并通过引用返回该流.cout << endl
相当于cout << '\n' << flush
,哪里flush
是一个刷新输出缓冲区的操纵器.
在您的课程中,您只需要为此运算符编写重载:
logger& operator<<(logger&(*function)(logger&)) {
return function(*this);
}
Run Code Online (Sandbox Code Playgroud)
logger&(*)(logger&)
函数的类型在哪里接受并logger
通过引用返回.要编写自己的操纵器,只需编写一个与该签名匹配的函数,并让它在流上执行一些操作:
logger& newline(logger& L) {
return L << '\n';
}
Run Code Online (Sandbox Code Playgroud)