【问题标题】:Why doesn't template operator<< deduce std::endl? [duplicate]为什么模板运算符<< 不推断 std::endl? [复制]
【发布时间】:2019-07-28 11:32:12
【问题描述】:

如果您取消注释第一个运算符定义,这将编译并运行:

#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

【问题讨论】:

标签: c++ templates iostream iomanip


【解决方案1】:

std::endl 本身就是一个模板。当你有第一个重载时,它的参数可以通过匹配函数指针来推断。这是 TAD 发生的一个例子。

只是operator&lt;&lt; 模板,有什么可以推导出来的?两个模板都需要推导出它们的参数。

【讨论】:

    【解决方案2】:

    因为,作为函数模板,std::endl 是关于模板实参推导的重载集;并且模板参数推导不适用于重载集(当然,除非它只包含一个函数)。

    为了说明,考虑:

    template<class Function>
    void functor(Function f)
    { f(0); }
    
    void g(float) {}
    void g(double) {}
    
    functor(g);
    

    没有理由偏爱g 的一个版本而不是另一个版本,除非您明确专门化functorfunctor&lt;void(float)&gt;(f) 很好),否则模板参数推导一定会失败。

    如果g 是一个模板也是如此:http://coliru.stacked-crooked.com/a/8e27a45bbeedd979

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-01
      • 2016-10-30
      • 1970-01-01
      • 2020-07-23
      • 2012-08-09
      • 2020-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多