Question

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!

Was it helpful?

Solution

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.

OTHER TIPS

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top