Why doesn't my template accept an initializer list

爱⌒轻易说出口 提交于 2019-12-17 05:07:34

问题


I have created a template as follows

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

I wanted for this to be callable by containers but also by initializer lists. I thought it would be initializer_list<int>, when called as follows.

f({1, 2, 3});

But GCC behaves as if it's not Standards compliant

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)

Can anyone explain how I can make this work without warnings? Thanks!


回答1:


A "thing" like {1,2,3} does not qualify as an expression. It has no type. Therefore, no type deduction is done. But C++0x makes an explicit exception for 'auto', so

auto x = {1,2,3};

actually works and decltype(x) will be initializer_list<int>. But this is a special rule that only applies to auto. I guess they wanted to make loops like these

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

work since this kind of loop exploits the special rule.

As for solving the problem, you could add an initializer_list<T> overload as a "wrapper":

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

I didn't test this but my current understanding is that it should work.




回答2:


Well, the documentation says that

This option is present because this deduction is an extension to the current specification in the C++0x working draft, and there was some concern about potential overload resolution problems.

This information may simply be outdated (according to the source it was last updated in 2008). As far as I understand this, the deduction was included into GCC but with the expectation that a later draft of the standard would remove the rule, or at least limit it.




回答3:


Can anyone explain how I can make this work without warnings?

I don't know if this refers to the exact code you quoted, or if you just want to know how you can instantiate the function template with an initializer list without triggering warnings, but if it's the latter and if the problem is merely deducing the correct type, you could possibly avoid it by just calling

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

It's not pretty, but it might avoid the warning without fiddling with the compiler command line arguments.

I'd probably put a comment nearby which explains that you don't rely on the compiler deducing the correct type due to weaknesses in certain GCC versions.



来源:https://stackoverflow.com/questions/4757614/why-doesnt-my-template-accept-an-initializer-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!