问题
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