在他的“C++ and Beyond 2012:Universal References”演讲中,Scott 反复强调了这一点,即通用引用处理/绑定到所有内容,因此重载已经采用通用引用参数的函数是没有意义的。我没有理由怀疑这一点,直到我将它们与std::initializer_list
.
这是一个简短的例子:
#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;
}
奇怪的是,VC11 Nov 2012 CTP 抱怨歧义(error C2668: 'foo' : ambiguous call to overloaded function
)。更令人惊讶的是,gcc-4.7.2、gcc-4.9.0 和 clang-3.4 同意以下输出:
initializer list
initializer list
initializer list
universal reference
因此,显然可以(使用 gcc 和 clang)重载使用initializer_list
s 进行通用引用的函数,但是在使用-idiom 时,使用by value 还是 byauto + { expr } => initializer_list
甚至都无关紧要。至少对我来说,这种行为完全令人惊讶。哪种行为符合标准?有谁知道这背后的逻辑?initializer_list
const&