Initializer list expressions are really convenient for initializing C++ containers:
std::vector<int>({1, 2, 3})
...but it seems that a brace-enclosed initializer list expression, like {1,2,3}
will only bind to a function that takes a std::initializer_list<int>
- it doesn't seem to bind to a universal (forwarding) reference:
template <class T>
void foo(T&& v)
{
std::vector<int>(std::forward<T>(v));
}
int main()
{
foo({1, 2, 3})
}
This outputs:
test2.cpp:11:6: note: template<class U> void foo(U&&)
test2.cpp:11:6: note: template argument deduction/substitution failed:
test2.cpp:33:13: note: couldn't deduce template parameter ‘U’
(This was the result with GCC 4.7.2.)
This unfortunately means we can't forward an initializer list expression. Since it would be very convenient to do that, I'd like to ask why is it that this doesn't work? Why can't a brace enclosed initializer list expression bind to a forwarding reference? Or is this allowed, and perhaps my compiler is just too old?
It's not that it can't bind to the parameter of your function; it's just that the compiler is unable to detect the type of your template. This compiles:
#include <vector>
template <class T>
void foo(T&& v)
{
std::vector<int>(std::forward<T>(v));
}
int main()
{
foo(std::initializer_list<int>{1, 2, 3});
}
The initializer list cannot be deduced in this case. This is actually covered explicitly by the standard in [temp.deduct.call]:
Template argument deduction is done by comparing each function template parameter type (call it
P
) with the type of the corresponding argument of the call (call itA
) as described below. IfP
is a dependent type, [...]. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context (14.8.2.5). [ Example:template<class T> void f(std::initializer_list<T>); f({1,2,3}); // T deduced to int f({1,"asdf"}); // error: T deduced to both int and const char* template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T
The example here for g
is exactly your case - T
is not a dependent type, so this is considered to be a non-deduced context. The compiler is correct to reject your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With