Kno*_*abe 18 c++ templates c++11 list-initialization template-argument-deduction
我理解,给定一个支撑的初始化程序,auto将推导出一种类型std::initializer_list,而模板类型推导将失败:
auto var = { 1, 2, 3 }; // type deduced as std::initializer_list<int>
template<class T> void f(T parameter);
f({ 1, 2, 3 }); // doesn't compile; type deduction fails
Run Code Online (Sandbox Code Playgroud)
我甚至知道在C++ 11标准中指定的位置:14.8.2.5/5 bullet 5:
[如果程序有,则这是一个非推导的上下文]一个函数参数,其关联参数是初始化列表(8.5.4),但参数没有std :: initializer_list或者可能是cv-qualified std :: initializer_list的引用类型.[ 例如:
模板void g(T);
克({1,2,3}); //错误:没有推断T的参数
- 结束例子 ]
我不知道或不理解的是为什么存在这种类型演绎行为的差异.C++ 14 CD中的规范与C++ 11中的规范相同,因此标准化委员会可能不会将C++ 11行为视为缺陷.
有人知道为什么auto推导出支撑初始值设定项的类型,但是不允许使用模板吗?虽然对"这可能是原因"形式的推测性解释很有意思,但我对那些知道为什么标准是按原样编写的人的解释特别感兴趣.
Joh*_*itb 13
模板不做任何演绎有两个重要原因(我在与负责人的讨论中记得两个)
对未来语言扩展的担忧(你可以发明多种含义 - 如果我们想为引入的init列表函数参数引入完美转发呢?)
大括号有时可以有效地初始化依赖的函数参数
Run Code Online (Sandbox Code Playgroud)template<typename T> void assign(T &d, const T& s);
int main() {
vector<int> v;
assign(v, { 1, 2, 3 });
}
Run Code Online (Sandbox Code Playgroud)
如果T在右侧推导initializer_list<int>但在左侧推断,vector<int>由于矛盾的论证推论,这将无法奏效.
对于演绎auto到initializer_list<T>是有争议的.存在一个C++的提议 - 在14之后删除它(并禁止使用{ }or 进行初始化{a, b},并{a}推导出类型的推断a).
首先,正如您所说,它是“对‘这可能是原因’形式的推测性解释”。
\n\n{1,2,3}不仅std::initializer_list<int>还允许在没有构造函数的情况下初始化类型。例如:
#include <initializer_list>\n\nstruct x{\n int a,b,c;\n};\n\nvoid f(x){\n\n}\nint main() {\n f({1,2,3});\n}\nRun Code Online (Sandbox Code Playgroud)\n\n是正确的代码。为了证明它不是,initializer_list让我们看看下面的代码:
#include <initializer_list>\n\nstruct x{int a,b,c;};\n\nvoid f(x){\n\n}\nint main() {\n auto il = {1, 2, 3};\n f(il);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n错误是:
\n\nprog.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99:\nprog.cpp:10:9: error: could not convert \xe2\x80\x98il\xe2\x80\x99 from \xe2\x80\x98std::initializer_list<int>\xe2\x80\x99 to \xe2\x80\x98x\xe2\x80\x99\nRun Code Online (Sandbox Code Playgroud)\n\n现在问题是“有什么区别?”
\n\n在auto x = {1, 2, 3};代码中可以确定类型,因为编码器明确表示“它是什么类型并不重要”auto
而在函数模板的情况下,他可以确定他使用的是不同的类型。而且它可以很好地防止在模棱两可的情况下出现错误(它看起来不像 C++ 风格)。
\n\n尤其糟糕的是,如果有 1 个函数f(x),然后将其更改为模板 1,情况会更糟糕。程序员编写了将其用作x,并且在为其他类型添加新函数后,它稍作更改以调用完全不同的函数。