为什么使用std :: initializer_list的构造函数不喜欢使用双花括号语法

冈兹堡

统一初始化是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>

注意到集合初始化上如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>

我确定已经讨论过了,那么反对这个的原因是什么?优先选择标准提案中的报价/链接作为答案。

更新。N2532中有一点指出:

(3)可能令人讨厌的歧义情况仅在简短的初始化列表中发生[...]

(5)为什么语言规则会迫使想要简洁和歧义控制的程序员(出于充分的理由)多写些东西,以取悦那些(出于充分的理由)更明确的程序员,并且可以做到?

[...]

假定程序员期望f(X)被调用。af(Y)如何“劫持”电话?

(4)假设X没有初始化器列表构造函数,而Y有。在这种情况下,赋予初始值设定项列表构造函数的优先级优先于劫持者(请记住,我们假设程序员以某种方式希望调用f(X))。这类似于有人期望f(y)使用用户定义的转换来调用f(X),而有人带来了一个完全匹配的f(Y)。我认为可以期望使用{…}的人会记得初始化列表构造函数的可能性。[强调我的]

我猜关键在于can,这意味着您不必使用统一的初始化。{}正确使用很难,因为:

  • 您不仅要检查要调用的构造函数,还要检查任何采用initializer_list可能会胜过(可能会胜过)的的构造函数

  • 如果您使用编写代码,{}并且将来有人添加了std::initializer_list构造函数,则您的代码可能会中断并以静默方式执行

即使您有一个A带有构造函数A(int, bool)的类,也将A(std::initializer_list<double>)在后者上选择后者A a{0, false};(对于IMO来说是螺母),所以我发现在具有或可能具有的类上使用统一初始化确实非常困难(需要水晶球超能力)构造函数。initializer_list

您的代码可以无声破解的事实令我非常担忧。

乔纳森·韦克利

这是Stroustrup在这个问题上说的:

统一和通用并非仅是第四选择。它的目的是要初始化语法和不幸[不]可行的所有遗留代码使用,尤其是vector如果我vector今天设计的话,您可能不得不说点什么vector<int> {Count{9}};才能获得计数。

并回答“问题向量或{} -init语法是?”这个问题。

这是矢量设计:如果我vector今天设计的话,您可能不得不说点什么vector<int> {Count{9}};来获得计数。

更普遍的问题是,具有相同类型的几个语义上不同的参数最终会导致混淆,尤其是当它们可以形容词出现时。例如:

vector<int> v(7,2);    // 7 (a count) element with the value 2

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么使用带括号的初始化程序列表时首选std :: initializer_list构造函数?

来自分类Dev

为什么双空花括号{{}}用一个元素而不是零创建std :: initializer_list <double>?

来自分类Dev

稍后添加initializer_list构造函数时,使用大括号初始化语法会改变构造行为吗?

来自分类Dev

如何防止std :: string使用initializer_list构造函数?

来自分类Dev

为什么这个initializer_list构造函数是可行的重载?

来自分类Dev

为什么我不能在`std :: initializer_list`中使用引用类型

来自分类Dev

如何使用带有std :: initializer_list的构造函数设计类?

来自分类Dev

为什么要使用std :: forward?

来自分类Dev

为什么不总是使用std :: forward?

来自分类Dev

std :: initializer_list作为std :: array构造函数

来自分类Dev

为什么在std :: move中使用std :: remove_reference?

来自分类Dev

std :: initializer_list作为构造函数的模板参数

来自分类Dev

构造函数中的std :: initializer_list转换

来自分类Dev

为什么在括号上使用花括号?

来自分类Dev

使用std :: initializer_list参数的非成员函数(/非构造函数上下文)的重载解析

来自分类Dev

在模板函数中使用initializer_list

来自分类Dev

在模板函数中使用initializer_list

来自分类Dev

为什么必须复制std :: initializer_list的元素?

来自分类Dev

为什么std :: min仅支持initializer_list?

来自分类Dev

为什么Clang无法优化std :: initializer_list?

来自分类Dev

如何不使用std :: initializer_list定义初始值设定项列表构造函数?

来自分类Dev

为什么在返回此函数时使用std :: move

来自分类Dev

为什么传递给模板函数的std :: string对象不喜欢std :: string重载?

来自分类Dev

为什么要使用 list() 构造函数?

来自分类Dev

为什么C ++ 11中的std :: initializer_list重载了std :: begin()和std :: end()?

来自分类Dev

为什么在访问元素之前在容器上使用std :: forward?

来自分类Dev

为什么在`std :: is_member_function_pointer`中使用&符号?

来自分类Dev

为什么不推荐使用std :: function :: argument_type?

来自分类Dev

为什么Microsoft std :: vector :: insert使用Rotate()?

Related 相关文章

  1. 1

    为什么使用带括号的初始化程序列表时首选std :: initializer_list构造函数?

  2. 2

    为什么双空花括号{{}}用一个元素而不是零创建std :: initializer_list <double>?

  3. 3

    稍后添加initializer_list构造函数时,使用大括号初始化语法会改变构造行为吗?

  4. 4

    如何防止std :: string使用initializer_list构造函数?

  5. 5

    为什么这个initializer_list构造函数是可行的重载?

  6. 6

    为什么我不能在`std :: initializer_list`中使用引用类型

  7. 7

    如何使用带有std :: initializer_list的构造函数设计类?

  8. 8

    为什么要使用std :: forward?

  9. 9

    为什么不总是使用std :: forward?

  10. 10

    std :: initializer_list作为std :: array构造函数

  11. 11

    为什么在std :: move中使用std :: remove_reference?

  12. 12

    std :: initializer_list作为构造函数的模板参数

  13. 13

    构造函数中的std :: initializer_list转换

  14. 14

    为什么在括号上使用花括号?

  15. 15

    使用std :: initializer_list参数的非成员函数(/非构造函数上下文)的重载解析

  16. 16

    在模板函数中使用initializer_list

  17. 17

    在模板函数中使用initializer_list

  18. 18

    为什么必须复制std :: initializer_list的元素?

  19. 19

    为什么std :: min仅支持initializer_list?

  20. 20

    为什么Clang无法优化std :: initializer_list?

  21. 21

    如何不使用std :: initializer_list定义初始值设定项列表构造函数?

  22. 22

    为什么在返回此函数时使用std :: move

  23. 23

    为什么传递给模板函数的std :: string对象不喜欢std :: string重载?

  24. 24

    为什么要使用 list() 构造函数?

  25. 25

    为什么C ++ 11中的std :: initializer_list重载了std :: begin()和std :: end()?

  26. 26

    为什么在访问元素之前在容器上使用std :: forward?

  27. 27

    为什么在`std :: is_member_function_pointer`中使用&符号?

  28. 28

    为什么不推荐使用std :: function :: argument_type?

  29. 29

    为什么Microsoft std :: vector :: insert使用Rotate()?

热门标签

归档