【问题标题】:What is the difference between std::initializer_list<int>({1,2,3}) and {1,2,3}?std::initializer_list<int>({1,2,3}) 和 {1,2,3} 有什么区别?
【发布时间】:2017-01-13 13:06:35
【问题描述】:

我有以下模板函数:

template<typename T> void foo2(T t) {}

我知道我不能使用:

foo2({1,2,3});

因为初始化列表是模板参数的非推导上下文。我必须使用:

foo2<std::initializer_list<int>>({1,2,3});

但我也可以使用:

foo2(std::initializer_list<int>({1,2,3}));

这让我想知道:{1,2,3}std::initializer_list&lt;int&gt;({1,2,3}) 之间有什么区别?

【问题讨论】:

  • std::initializer_list&lt;int&gt;({1,2,3})std::initializer_list&lt;int&gt; 类型的表达式。 {1,2,3} 不是表达式。大括号列表只能出现在语言定义明确允许的上下文中,而不仅仅是表达式可以出现的任何地方。
  • @M.M 当您知道一个有 0 个答案的问题的答案时,但事实证明它在 cmets 中得到了回答。 ﴾ ͡° ʖ̯ ͡°﴿
  • @luk32 随意写一个答案......我认为一个完整的答案应该涵盖我不太确定的模板的细节

标签: c++ c++11


【解决方案1】:

braced-init list 不是表达式,因此没有类型。当你打电话时

foo2({1,2,3});

编译器不知道{1,2,3}在你的脑海中代表什么类型,所以它不会编译。

foo2<std::initializer_list<int>>({1,2,3});

编译因为这里编译器不必推断类型,你已经指定了它,它是std::initializer_list&lt;int&gt;。所以它可以用{1,2,3}初始化t

第三个调用也会编译,因为编译器可以推断出类型。 std::initializer_list&lt;int&gt;({1,2,3}) 显然是一个std::initializer_list&lt;int&gt;,所以它可以用传递的prvalue初始化t

【讨论】:

  • 请注意,在 C++17 中,“保证省略”规则使您的最后一段不同。从某种意义上说,不再有一个值在那里创建然后被省略到函数参数中;它只是成为初始化函数参数的一种方式。或者我认为,我还没有掌握新规则。 (实际上,在这种情况下几乎没有区别)
猜你喜欢
  • 2021-06-22
  • 2018-06-24
  • 2010-09-05
  • 2014-07-14
  • 1970-01-01
  • 1970-01-01
  • 2021-10-29
  • 2014-07-13
  • 1970-01-01
相关资源
最近更新 更多