【问题标题】:Why doesn't my template accept an initializer list为什么我的模板不接受初始化列表
【发布时间】:2011-06-13 01:23:59
【问题描述】:

我创建了一个模板如下

template<typename T>
void f(T const& t) { }

我希望它可以被容器调用,也可以被初始化列表调用。我以为是initializer_list&lt;int&gt;,调用如下。

f({1, 2, 3});

但 GCC 的行为就好像它不符合标准

m.cpp: In function 'int main()':
m.cpp:6:25: warning: deducing 'const T' as 'const std::initializer_list<int>'
m.cpp:4:6: warning:   in call to 'void f(const T&) [with T = std::initializer_list<int>]'
m.cpp:6:25: warning:   (you can disable this with -fno-deduce-init-list)

谁能解释我如何在没有警告的情况下完成这项工作?谢谢!

【问题讨论】:

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


【解决方案1】:

像 {1,2,3} 这样的“事物”不符合表达式的条件。它没有类型。因此,没有进行类型推导。但是 C++0x 为 'auto' 做了一个明确的例外,所以

auto x = {1,2,3};

确实有效,decltype(x) 将是initializer_list&lt;int&gt;。但这是一条仅适用于汽车的特殊规则。我猜他们想制作这样的循环

for (int x : {2,3,5,7,11}) {
   ...
}

工作,因为这种循环利用了特殊规则。

至于解决问题,您可以添加一个initializer_list&lt;T&gt; 重载作为“包装器”:

template<class T>
inline void outer(initializer_list<T> il) {
   inner(il);
}

我没有对此进行测试,但我目前的理解是它应该可以工作。

【讨论】:

  • 提到的特殊规则在 7.1.6.4 `auto' 说明符 [dcl.spec.auto]
  • C++0x makes an explicit exception for 'auto' 是的,在你展示的类似赋值的语法中,还有auto something{a, b, c} 形式。后者一直是后部的不一致疼痛,现在只能用 C++17 修复,其中 auto something{blah} 没有 = 符号意味着 '创建 decltype(blah) 的对象,从 @ 初始化987654331@ - 不是 的当前含义'创建一个名为 somethinginitializer_list,其中一个元素与 blah' 类型相同。最后!但到此为止,这意味着对受影响的代码库进行大量更新。 :C
【解决方案2】:

嗯,the documentation 这么说

之所以存在此选项,是因为此推论是对 C++0x 工作草案中当前规范的扩展,并且对潜在的重载解决问题存在一些担忧。

此信息可能只是过时了(根据来源,它最后一次更新是在 2008 年)。据我了解,该扣除已包含在 GCC 中,但期望该标准的后续草案会删除该规则,或至少对其进行限制。

【讨论】:

    【解决方案3】:

    谁能解释我如何在没有警告的情况下完成这项工作?

    我不知道this 是否指的是您引用的确切代码,或者您是否只想知道如何使用初始化列表实例化函数模板而不触发警告,但如果是后者并且如果问题仅仅是推断正确的类型,你可以通过调用来避免它

    f<initializer_list<int>>({1, 2, 3});
    

    它并不漂亮,但它可以避免警告而无需摆弄编译器命令行参数。

    我可能会在附近发表评论,说明由于某些 GCC 版本的弱点,您不依赖编译器推断正确的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-17
      • 1970-01-01
      • 2012-02-13
      • 1970-01-01
      • 1970-01-01
      • 2015-07-05
      相关资源
      最近更新 更多