Braced-init-lists and function template type deduction order
我有一个关于函数模板参数类型推导程序的问题。
举个例子:
1
2 3 4 5 6 7 8 9 10 11 12 |
#include <vector>
#include <sstream> #include <string> #include <iterator> #include <fstream> int main() |
如果我理解正确,第二个参数被推断为 std::istream_iterator 类型,其中调用了默认构造函数。
适当的 std::vector 构造函数声明为:
1
2 3 |
template <class InputIterator>
vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); |
由于第一个参数类型被推导出为 std::istream_iterator<int>,第二个参数也被推导出为 std::istream_iterator<int>,因此可以应用统一的初始化语义。我不知道的是类型推导发生的顺序。我真的很感激有关这方面的一些信息。
提前致谢!
- 它有效吗?如果是这样,必须先扣除第一个。
让我们用一个更简单的例子:
1
2 3 4 |
template<class T>
void foo(T, T); foo(42, {}); |
函数调用有两个参数:
- int 类型的纯右值表达式(整数文字)
- 一个花括号初始化列表 {}
后者,{},可以是表达式列表的一部分,但它本身不是表达式。表达式列表被定义为初始化列表。大括号初始化列表没有类型。
对每个函数参数单独进行模板类型扣除[temp.deduct.type]/2。 [temp.deduct.call]/1 说明函数参数 P:
的类型推导
If removing references and cv-qualifiers from P gives
std::initializer_list<P’> for some P’ and the argument is an
initializer list, then deduction is performed instead for each element
of the initializer list, taking P’ as a function template parameter
type and the initializer element as its argument. Otherwise, an
initializer list argument causes the parameter to be considered a
non-deduced context. [emphasis mine]
所以在调用 foo(42, {}); 中,不会从第二个参数 {} 推导出 T。然而,T 可以从第一个参数推导出来。
一般来说,我们可以从多个函数参数中推导出T。在这种情况下,推导的类型必须完全匹配 [temp.deduct.type]/2。如果类型仅从一个函数参数推导出但在其他地方使用(在另一个函数参数中,在非推导上下文中,在返回类型等中),则没有问题。类型扣除可能会失败,例如当模板参数不能从任何函数参数中推导出来且没有显式设置时。
推演后,T 将被 int 替代,产生类似于:
的函数签名
1
|
void foo<int>(int, int);
|
可以使用两个参数42 和{} 调用此函数。后者将执行复制列表初始化,导致第二个参数的值初始化。
- 这或多或少是我直观地看到的。谢谢你把事情弄清楚。
来源:https://www.codenong.com/24059738/