为什么我的模板不接受初始化列表

时间:2011-01-21 10:19:08

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

我创建了一个模板如下

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

我希望这可以通过容器调用,也可以通过初始化列表调用。我认为这将是initializer_list<int>,如下调用。

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)

任何人都可以解释如何在没有警告的情况下完成这项工作吗?谢谢!

3 个答案:

答案 0 :(得分:26)

像{1,2,3}这样的“东西”不符合表达式的条件。它没有类型。因此,不进行任何类型推断。但是C ++ 0x为'auto'做了一个显式异常,所以

auto x = {1,2,3};

实际上有效,而decltype(x)将为initializer_list<int>。但这是一个特殊规则,仅适用于auto。我猜他们想要制作像这样的循环

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

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

至于解决问题,您可以添加initializer_list<T>重载作为“包装器”:

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

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

答案 1 :(得分:3)

好吧,the documentation

  

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

此信息可能仅仅过时(根据2008年最新更新的来源)。据我所知,扣除额已纳入海湾合作委员会,但期望该标准的后期草案将删除该规则,或至少限制该规则。

答案 2 :(得分:1)

  

任何人都可以解释如何在没有警告的情况下完成这项工作吗?

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

来避免它
f<initializer_list<int>>({1, 2, 3});

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

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