24

我创建了一个模板如下

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)

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

4

3 回答 3

28

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

auto x = {1,2,3};

实际上有效并且 decltype(x) 将是initializer_list<int>. 但这是一条仅适用于汽车的特殊规则。我猜他们想制作这样的循环

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

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

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

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

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

于 2011-01-21T20:32:50.800 回答
3

好吧,文档

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

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

于 2011-01-21T10:23:30.177 回答
1

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

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

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

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

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

于 2011-01-21T12:40:53.140 回答