为什么在C++ 11/C++ 14中有自动和支撑初始化器的特殊类型推导规则?

Phi*_*ßen 6 c++ initializer-list auto c++11 c++14

在他的CppCon 2014 talke "Type Deduction和Why You Care"中,Scott Meyers提出了一个问题,即为什么auto在C++ 11/C++ 14标准中有一个关于和支持初始化器的特殊规则(他的问题从36m05开始).

auto的语义与braced-init-list的组合在§7.1.6.4/ 6中定义.


我想到了它,也无法想出一个用例.到目前为止,我所看到的最接近的是Bjarne Stroustrup使用它的一个例子.

2014年的Cpp演讲中"简单易懂任务!" ,他曾经auto用来捕获初始化器(但仅作为解决方法).

这是代码(幻灯片30的一部分,37m10s):

    // auto ss1 = collect({ 1, 2, 3, 4, 5, 6 }, odd); // error: Bummer!
    auto lst = { 1, 2, 3, 4, 5, 6 };
    auto ss2 = collect(lst, odd);    // {1,3,5}
Run Code Online (Sandbox Code Playgroud)

但请注意,这只是一种解决方法.他提到它不应该是必要的.相反,他更愿意直接将参数传递给函数.因此,它不能真正作为auto初始化列表的良好动机.


我对C++的理解并不足以判断Bjarne的例子中允许初始化列表的缺点,正如他所提出的那样.无论如何,它将避免auto在这种情况下的需要.

那么,auto和初始化器列表只是一个可以更好地解决的问题的解决方法吗?或者是否有很好的例子,§7.1.6.4/ 6中的额外自动扣除规则是否有用?

T.C*_*.C. 8

理由是在N2640中,它希望禁止从支持的初始化列表中删除普通类型参数:

template<class T>
void inc(T, int); // (1)

template<class T>
void inc(std::initializer_list<T>, long); // (2)

inc({1, 2, 3}, 3); // Calls (2). (If deduction had succeeded
                   // for (1), (1) would have been called — a
                   // surprise.)
Run Code Online (Sandbox Code Playgroud)

但是特别例外auto:

在另一方面,能够推导出一个initializer_list<X>T是有吸引力的,允许:

auto x = { 1, 1, 2, 3, 5 };
f(x);
g(x);
Run Code Online (Sandbox Code Playgroud)

从EWG关于初始化列表的讨论开始以来,这被认为是理想的行为.T我们现在更倾向于使用"auto"变量的特殊情况来处理这个问题,而不是为与{} -list匹配的参数类型提出一个聪明的演绎规则(我们在本文的早期草图和草稿中讨论了这个选项).初始化器为{} -list时的推论.即,对于使用"auto"类型说明符和{} -list初始化程序声明的变量的特定情况,推导出"auto" f(initializer_list<T>)而不是函数 而不是函数f(T).