C++ 为什么在C+;中有一个特殊的自动和带括号的初始值设定项类型推断规则+;11/C++;14?
Scott Meyers在其2014年CppCon演讲中提出了一个问题:为什么在C++11/C++14标准中有一条关于C++ 为什么在C+;中有一个特殊的自动和带括号的初始值设定项类型推断规则+;11/C++;14?,c++,c++11,auto,c++14,initializer-list,C++,C++11,Auto,C++14,Initializer List,Scott Meyers在其2014年CppCon演讲中提出了一个问题:为什么在C++11/C++14标准中有一条关于auto和带括号的初始值设定项的特殊规则(他的问题开始了) 自动与大括号初始列表组合的语义定义见§7.1.6.4/6 我想了想,也没能想出一个用例。到目前为止,我所看到的最接近的一件事是比亚恩·斯特罗斯特普使用它的一个例子 在his中,他曾使用auto捕获初始化者(但仅作为一种解决方法) 以下是代码(幻灯片30的一部分): 但请注意,这只是一种变通方法。他提到这不必要。相反,他
auto
和带括号的初始值设定项的特殊规则(他的问题开始了)
自动与大括号初始列表组合的语义定义见§7.1.6.4/6
我想了想,也没能想出一个用例。到目前为止,我所看到的最接近的一件事是比亚恩·斯特罗斯特普使用它的一个例子 在his中,他曾使用
auto
捕获初始化者(但仅作为一种解决方法)
以下是代码(幻灯片30的一部分):
但请注意,这只是一种变通方法。他提到这不必要。相反,他更愿意直接将参数传递给函数。因此,它不能真正成为auto
和初始值设定项列表的良好动机
我对C++的理解不够深入,无法判断BjARNE的示例中允许初始化列表的缺点。无论如何,在这种情况下,它将避免使用
auto
那么,auto
和初始值设定项列表是否仅仅是一个解决问题的方法?还是有好的例子,其中§7.1.6.4/6中的额外自动扣除规则是有用的?基本原理是,一般来说,它想要禁止从括号内的初始值设定项列表中扣除普通类型参数:
从一开始就被认为是可取的行为
EWG关于初始值设定项列表的讨论。而不是想出一个
与{}列表匹配的参数类型T
的智能推断规则
(我们在本文的早期草图和草稿中采用了这一选项),
我们现在更喜欢用“auto”变量的特例来处理这个问题
当初始值设定项是{}-列表时的推断。即,对于特定的
使用“自动”类型说明符和
{}-列表初始值设定项,将“auto”推断为函数
f(初始值设定项列表)
而不是函数的asf(T)
Scott Meyers在一篇博客文章中谈到了这个话题: 就像T.C.的回答一样,它也提到了。已添加特殊扣除规则,以允许这样的代码工作:
auto x = { 1, 1, 2, 3, 5 };
f(x);
g(x);
斯科特在博客中引用了詹姆斯·霍普金的以下解释:
简短的故事是,提出了一个特例,即auto应该将括号内的初始值设定项推断为初始值设定项列表,而没有意识到这样做破坏了统一的初始化(例如,它使intx{7};
和autox{7};
非常不同)。通过(当然!)引入另一种特殊情况修复了这一问题:带括号的单参数初始值设定项有自己的规则
更详细一点:尝试保持模板参数推导简单,但尝试通过将括号内的初始值设定项分配给自动函数,将其传递给两个或多个函数。这句话后来变成了书面语。请注意,Stroustrup以前在中的设计允许为无约束模板参数和auto推导初始值设定项列表,这更为一致,但也破坏了统一的初始化
所有这些都不能解释为什么我们不删除汽车的特殊情况。这不会导致对代码含义的无声更改,也不会简化语言
我很确定有一个C++1z建议,使
autoX={expr}代码>使用expr
类型(减号允许使用非括号逗号运算符)。不过,我不确定完整的列表还应该使用哪种类型。@christ我想你是指N3922。斯科特·梅耶斯也提到了这一点。VisualStudio已经实现了它,尽管它不是C++14的一部分。这是链接:啊,就是这个。虽然由于这个用法,我不得不有点不同意一般的说法。我真的希望格式不正确,并且初始化列表能够在没有额外行的情况下传递到函数中。
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 x = { 1, 1, 2, 3, 5 };
f(x);
g(x);
auto x = { 1, 1, 2, 3, 5 };
f(x);
g(x);