【问题标题】:std::endl and variadic template [duplicate]std::endl 和可变参数模板
【发布时间】:2014-01-19 16:53:44
【问题描述】:

代码:

#include <iostream>

void out()
{
}

template<typename T, typename... Args>
void out(T value, Args... args)
{
    std::cout << value;
    out(args...);
}

int main()
{
    out("12345", "  ", 5, "\n"); // OK
    out(std::endl);              // compilation error
    return 0;
}

构建错误:

g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++11 -pthread -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.cpp"
../main.cpp: In function ‘int main()’:
../main.cpp:17:15: error: no matching function for call to ‘out(<unresolved overloaded function type>)’
../main.cpp:17:15: note: candidates are:
../main.cpp:3:6: note: void out()
../main.cpp:3:6: note:   candidate expects 0 arguments, 1 provided
../main.cpp:8:6: note: template<class T, class ... Args> void out(T, Args ...)
../main.cpp:8:6: note:   template argument deduction/substitution failed:
../main.cpp:17:15: note:   couldn't deduce template parameter ‘T’

所以,除了std::endl,一切都很好。我该如何解决这个问题(使用“\n”除外)?

【问题讨论】:

  • out(&amp;std::endl&lt;char, std::char_traits&lt;char&gt;&gt;);

标签: c++ c++11 variadic-templates


【解决方案1】:

std::endl 是一个重载函数,(在许多 STL 实现中,一个模板)并且编译器没有关于选择什么的信息。

只需将其转换为static_cast&lt;std::ostream&amp;(*)(std::ostream&amp;)&gt;(std::endl)

【讨论】:

  • 重点其实是模板,而不是重载。
  • @jogojapan:从技术上讲,模板是“重载生成器”:std::endl 与流类一样多。无论是通过声明其中的一些(例如对于 ostream 和 wostream)还是通过模板(在ostream&lt;T,Traits&gt;)来获得,都是一个实现细节,不会改变关于如何选择重载的子实体。
  • 就解决方案的有效性而言,这并没有什么区别,但模板实例化和重载解析是两种截然不同的机制。将模板称为重载生成器具有误导性。
  • 按照您描述的方式,模板生成一组函数,然后应用重载决议来选择一个。这是不正确的,原因有两个: a) 在简单重载决议的情况下,可供选择的函数集是预定义的,隐式类型转换是编译器可以用来在给定参数和它选择的函数,而在模板实例化的情况下,可以生成函数的新实例以完全适合给定的参数。这在模棱两可的情况下具有广泛的意义。 b) 在的情况下
  • 如果 std::endl 是一组重载,则库实现存在错误,因为它无法用于自定义字符特征(或自定义字符类型)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-23
  • 2012-04-18
  • 2019-04-30
  • 2022-01-05
  • 2015-12-09
  • 1970-01-01
  • 2019-01-18
相关资源
最近更新 更多