问题描述
我正在尝试编写自己的日志记录类并将其用作流:
I'm trying to write my own logging class and use it as a stream:
logger L;
L << "whatever" << std::endl;
这是我开始的代码:
#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" << '
' ; // This works
L << "bye" << "alo" << endl; // This doesn't work
return 0;
}
但是我在尝试编译时遇到一个错误,说没有对 operator<<< 的定义.(使用 std::endl 时):
But I was getting an error when trying to compile, saying that there was no definition for operator<< (when using 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’
所以,我一直在尝试重载 operator<<接受这种流,但这让我发疯.我不知道该怎么做.例如,我一直在关注 ostream 头文件中 std::endl 的定义,并用这个头文件编写了一个函数:
So, I've been trying to overload operator<< to accept this kind of streams, but it's driving me mad. I don't know how to do it. I've been loking at, for instance, the definition of std::endl at the ostream header file and written a function with this header:
logger& operator <<(logger& log, const basic_ostream<char,char_traits<char> >& (*s)(basic_ostream<char,char_traits<char> >&))
但没有运气.我已经尝试过使用模板而不是直接使用 char 来做同样的事情,也尝试过简单地使用const ostream& os",但什么也没有.
But no luck. I've tried the same using templates instead of directly using char, and also tried simply using "const ostream& os", and nothing.
另一件让我烦恼的事情是,在错误输出中,operator<< 的第一个参数.变化,有时是对指针的引用,有时看起来像双重引用...
Another thing that bugs me is that, in the error output, the first argument for operator<< changes, sometimes it's a reference to a pointer, sometimes looks like a double reference...
推荐答案
endl
是个奇怪的野兽.它不是一个常数值.它实际上是所有事物中的一个函数.你需要一个特殊的覆盖来处理 endl
的应用:
endl
is a strange beast. It isn't a constant value. It's actually, of all things, a function. You need a special override to handle the application of endl
:
logger& operator<< (logger& log, ostream& (*pf) (ostream&))
{
cout << pf;
return log;
}
这接受一个函数的插入,该函数接受一个 ostream
引用并返回一个 ostream
引用.这就是 endl
是什么.
This accepts insertion of a function that takes an ostream
reference and returns an ostream
reference. That's what endl
is.
回应 FranticPedantic 的有趣问题为什么编译器不能自动推断出这一点?".原因是,如果你再深入研究,endl
实际上本身就是一个 模板 函数.定义为:
In response to FranticPedantic's interesting question of "why can't the compiler deduce this automatically?". The reason is that if you delve yet deeper, endl
is actually itself a template function. It's defined as:
template <class charT, class traits>
basic_ostream<charT,traits>& endl ( basic_ostream<charT,traits>& os );
也就是说,它可以接受任何类型的ostream
作为它的输入和输出.所以问题不在于编译器无法推断 T const &
可能是一个函数指针,而是它无法确定 哪个 endl
您打算传入.问题中提供的 operator<<
模板化版本将接受指向任何函数的指针作为其第二个参数,但同时,endl
模板表示一个无限潜在函数集,因此编译器在那里不能做任何有意义的事情.
That is, it can take any sort of ostream
as its input and output. So the problem isn't that the compiler can't deduce that T const &
could be a function pointer, but that it can't figure out which endl
you meant to pass in. The templated version of operator<<
presented in the question would accept a pointer to any function as its second argument, but at the same time, the endl
template represents an infinite set of potential functions, so the compiler can't do anything meaningful there.
提供 operator<<
的特殊重载,其第二个参数与 endl
模板的特定实例相匹配,允许调用解析.
Providing the special overload of the operator<<
whose second argument matches a specific instantiation of the endl
template allows the call to resolve.
这篇关于C++流作为重载operator<<时的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!