如果您取消注释第一个运算符定义,它将编译并运行:
#include <iostream>
struct logger
{
std::ostream &loggingStream;
logger(std::ostream &ls) : loggingStream(ls) {}
};
/*
logger &operator<<(logger &l, std::ostream & (*manip)(std::ostream &)) {
manip(l.loggingStream);
return l;
}
*/
template<typename T>
logger &operator<<(logger &l, const T &t) {
l.loggingStream << t;
return l;
}
int main() {
logger l(std::cout);
l << "Hello" << std::endl;
return 0;
}
注释到位
error: no match for ‘operator<<’ (operand types are ‘logger’ and ‘<unresolved overloaded function type>’)
为什么我需要提供非模板重载来处理endl
?
答案 0 :(得分:1)
因为std::endl
作为函数模板,是关于模板自变量推导的重载集;和模板参数推论不适用于重载集(除非它当然只包含一个函数)。
为说明,请考虑:
template<class Function>
void functor(Function f)
{ f(0); }
void g(float) {}
void g(double) {}
functor(g);
没有理由偏爱g
的一个版本,除非您明确地专门化functor
(functor<void(float)>(f)
很好),否则模板参数推导必须失败。
如果g
是模板,则也是如此:http://coliru.stacked-crooked.com/a/8e27a45bbeedd979
答案 1 :(得分:1)
std::endl
本身就是模板。当您遇到第一个重载时,可以通过与函数指针匹配来推导其参数。为此就是发生TAD的一种情况。
使用 just operator<<
模板,可以从中推论出什么?这两个模板都需要推论其参数。