实现简单的记录器
struct DebugOutput {
DebugOutput(std::ostream& out = std::cerr) : m_Out(out) {}
template<typename T>
inline DebugOutput& operator <<(T&& value) {
m_Out << value;
return *this;
}
private:
std::ostream& m_Out;
};
我发现universal reference无法捕获std::endl
。
DebugOutput dbg;
dgb << std::endl;
我发现这个this post解释了你需要在结构中添加一个特别是函数指针签名的重载函数,即:
typedef std::ostream& (*StandardEndLine)(std::ostream&);
inline DebugOutput& operator<<(StandardEndLine manip) {
return *this;
}
为什么通用引用不捕获函数指针?它不是int
或void*
的类型吗?
答案 0 :(得分:12)
函数(指针)可以绑定到通用引用。例如:
void f(int) {}
template <typename T>
void foo(T&&) {}
foo(f); // OK
然而,重载功能不能。也就是说,如果你添加f
的第二个重载,比如说,
void f(double) {}
电话foo(f)
将失败。
把自己放在编译器鞋上。需要将f
传递给foo
,并且有两个名为f
的函数,每个函数都有不同的类型。如果我们通知类型,那么编译器可以明确地选择正确的f
。例如,
foo(static_cast<void (*)(int)>(f));
编译正常并将void f(int)
(在函数到指针转换后)传递给foo
。
但是,我们没有通知该类型。我们宁愿要求编译器推断它。
与f
类似,同一参数适用于std::endl
,因为这是一个函数模板,因此名称std::endl
表示一组函数,所有函数都具有相同的名称,但不同类型。
现在,您可以看到错误的原因是我们提供了一个重载集并要求类型推导。因此,这不是普遍的参考。
std::cout << std::endl
有效,因为basic_ostream::operator <<
不是模板,并且不会尝试推断传递的参数的类型。这是一个函数,它采用一种特定类型的std::endl
。