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

时间:2014-10-12 22:07:48

标签: c++ c++11 auto c++14 initializer-list

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

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


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

在他的Cpp 2014 talk "Make Simple Tasks Simple!"中,他曾使用auto来捕获初始值设定项(但仅作为解决方法)。

以下是代码(幻灯片30的一部分,at 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}

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


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

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

2 个答案:

答案 0 :(得分: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.)

但为auto划出了一个特殊例外:

  

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

auto x = { 1, 1, 2, 3, 5 };
f(x);
g(x);
     

从一开始就被认为是理想的行为   EWG关于初始化列表的讨论。而不是想出一个   与{} -list匹配的参数类型T的聪明扣除规则   (我们在本文的早期草图和草稿中追求的选项),   我们现在更喜欢用“auto”变量的特殊情况来处理这个问题   初始化器为{} -list时的推论。即,具体而言   使用“auto”类型说明符声明的变量的大小写   {} -list初始化程序,对于函数推导出“auto”   f(initializer_list<T>)代替函数f(T)

答案 1 :(得分:2)

Scott Meyers在博文中提到了这个话题:Why auto deduces std::initializer_list for a braced initializer

与T.C。的答案一样,它也指N2640。添加了特殊扣除规则以允许这样的代码起作用:

 auto x = { 1, 1, 2, 3, 5 };
 f(x);
 g(x);

在博客文章中,Scott引用了James Hopkin的以下解释:

  

简短的故事是N2640提出了一个特殊情况,即auto应该将支持的初始化器推断为initializer_lists,而没有意识到这样做会破坏统一初始化(例如,它使得int x{7};auto x{7};非常不同)。 N3922修正了(当然!)引入另一个特例:单个参数支撑的初始化器有自己的规则。

     

稍微详细一点:N2640尝试简化模板参数推导,但尝试通过将支持的初始化程序分配给auto来将其传递给两个或多个函数。这在N2672中变成了措辞。请注意,Stroustrup在N2532中的先前设计允许扣除无约束模板参数和auto的initializer_lists,这更加一致,但也会破坏统一初始化。

     

这些都没有解释为什么N3922没有删除auto的特殊情况。这不会导致对代码含义的无声改变,并且会简化语言。