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
,但是当使用 auto + { expr } => initializer_list
这种语法时,无论是按值传递还是按const&
传递initializer_list
都没有区别。
至少对我来说,这种行为完全出乎意料。
哪种行为符合标准?有人知道背后的逻辑吗?
重载 + URef 几乎总是错误的。没有意义:URefs 可以处理所有东西。 [...]
- user2523017template <class T> void f(initializer_list<T>)
比template <class T> void f(T&&)
更加专业化。使用GCC进行简单测试也证实了这一点(不一定要使用initializer_list
作为容器)。 - jogojapan