In his "C++ and Beyond 2012: Universal References" presentation, Scott repeatedly stresses the point, that universal references handle/bind to everything and thus overloading a function that already takes a universal reference parameter does not make sense.
I had no reason to doubt that until I mingled them with std::initializer_list
.
Here is a short example:
#include <iostream>
#include <initializer_list>
using namespace std;
template <typename T>
void foo(T&&) { cout << "universal reference" << endl; }
template <typename T>
void foo(initializer_list<T>) { cout << "initializer list" << endl; }
template <typename T>
void goo(T&&) { cout << "universal reference" << endl; }
template <typename T>
void goo(initializer_list<T> const&) { cout << "initializer list" << endl; }
int main(){
auto il = {4,5,6};
foo( {1,2,3} );
foo( il );
goo( {1,2,3} );
goo( il );
return 0;
}
Oddly enough, VC11 Nov 2012 CTP complains about ambiguity (error C2668: 'foo' : ambiguous call to overloaded function
). Yet even more suprising is, that gcc-4.7.2, gcc-4.9.0 and clang-3.4 agree on the following output:
initializer list
initializer list
initializer list
universal reference
So apparently it is possible (with gcc and clang) to overload functions taking universal references with initializer_list
s but when using the auto + { expr } => initializer_list
-idiom it does even matter whether one takes the initializer_list
by value or by const&
.
At least to me that behavior was totally surprising.
Which behavior conforms to the standard? Does anyone know the logic behind that?