gnz*_*lbg 11 c++ initializer-list uniform-initialization c++11
统一初始化是一个重要且有用的C++ 11特性.但是,您不能{}随处使用,因为:
std::vector<int> a(10, 0); // 10 elements of value zero
std::vector<int> b({10, 0}); // 2 elements of value 10 and 0 respectively
std::vector<int> c{10, 0}; // 2 elements of value 10 and 0 respectively
std::vector<int> d = {10, 0}; // 2 elements of value 10 and 0 respectively
auto e(0); // deduced type is int
auto f = 0; // deduced type is int
auto g{0}; // deduced type is std::initializer_list<int>
auto h = {0}; // deduced type is std::initializer_list<int>
Run Code Online (Sandbox Code Playgroud)
注意到例如需要使用聚合初始化,在我看来,通过要求调用构造函数来避免选择向量构造函数的整个问题可以避免:std::arrays{{}}{{}}std::initializer_list
std::vector<int> i{10, 0}; // 10 elements of value zero
std::vector<int> j{{10, 0}}; // 2 elements of value 10 and 0 respectively
std::vector<int> k = {10, 0}; // 2 elements of value 10 and 0 respectively
auto l{0}; // deduced type is int
auto m{{0}}; // deduced type is std::initializer_list<int>
auto n = {0}; // deduced type is std::initializer_list<int>
Run Code Online (Sandbox Code Playgroud)
我确定已经讨论了这个问题,那么反对这个的原因是什么?标准提案的引用/链接首选作为答案.
更新.- N2532中有一点说:
(3)可能令人讨厌的歧义情况仅发生在短初始化列表中[...]
(5)语言规则为什么要强制程序员想要简洁和模糊控制(出于完美的理由)写更多的东西来取悦那些喜欢(出于完美的理由)更明确的程序员 - 并且可以?
[...]
假设程序员期望调用f(X).af(Y)如何"劫持"一个电话?
(4)假设X没有初始化列表构造函数,但Y没有.在这种情况下,赋予初始化列表构造函数的优先级有利于劫持者(记住我们假设程序员某种程度上期望调用f(X)).这类似于某人期望f(y)使用用户定义的转换来调用f(X),并且有人带有完全匹配的f(Y).我认为使用{...}的人会记住初始化列表构造函数的可能性是公平的.[强调我的]
我猜关键在于可以,这意味着你不必使用统一初始化.{}正确使用很难,因为:
你不仅要检查你想打电话,但也为构造的任何构造服用initializer_list可能赢得(可能会)在其上;
如果您使用代码编写代码,{}并且将来会添加一个std::initializer_list构造函数,您的代码可能会破坏并默默地执行此操作.
即使你有一类A与构造函数A(int, bool)和 A(std::initializer_list<double>),后者将在前者的选择A a{0, false};(这IMO是坚果),所以我觉得真的很难在具有或类使用统一的初始化可能有(需要水晶球超级大国)initializer_list构造函数.
你的代码可以默默地破解我的事实让我很担心.
Jon*_*ely 11
这是Stroustrup在这个问题上所说的:
统一和普遍并不仅仅是第四种选择.它的目的是要在初始化语法和不幸[不]可行的所有遗留代码使用,尤其是
vector.如果我vector今天设计的话,你就不得不说出类似的事情vector<int> {Count{9}};.
并回答问题"是问题向量还是{} -init语法?"
这是矢量设计:如果我
vector今天设计的话,你就不得不说出一些vector<int> {Count{9}};想要计算的东西.更普遍的问题是,具有相同类型的几个语义上不同的参数最终会导致混淆,特别是如果它们可以出现.例如:
Run Code Online (Sandbox Code Playgroud)vector<int> v(7,2); // 7 (a count) element with the value 2
(这并不是真正的答案,只是对我在这个问题上的想法的讨论。)
我认为我希望编译器在存在歧义的情况下发出警告,建议开发人员使用({ })(如果他们确实希望使用initializer_list)或( )不使用。如果MostVexingParse有风险,请额外警告!-也许建议(( ))避免这种情况?
(以下“故事”可能不是基于正确的功能开发历史顺序,而是我了解编译器中的当前规则的方式。)
一开始我们有构造函数:
type t (...);
Run Code Online (Sandbox Code Playgroud)
然后,我们想到了允许{提供一个字面量集合供构造函数使用的想法(以及其他地方)。
type t ( {...} );
Run Code Online (Sandbox Code Playgroud)
...以及initializer_list构造函数中的新类型以匹配此类型。
然后,我们被允许更换( )同{ }以避免最令人头痛的解析:
type t { ... };
type t { {...} };
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很好。语言的纯扩展。
最后,“有争议”的补充是,当编译器看到{ ... }(作为构造函数)时,它将首先尝试将其重写为({ ... })(如果存在,则调用initializer_list),然后再回退( ... )。我想如果两个选项都被认为是同样好的,并且如果两者都可能出现,那么我会更愿意发出警告或错误。
| 归档时间: |
|
| 查看次数: |
4203 次 |
| 最近记录: |