考虑这个程序:
template<typename T>
struct Foo
{
void foo(const T&) {}
void foo(T&) {}
};
int main()
{
Foo<double&> f;
double d = 3.14;
f.foo(d); //complains that foo() is ambigous
}
在上面,如果Foo被实例化为Foo<double>
,那么事情很好,但如果它被实例化为Foo<double&>
,则对foo
的调用变得模糊不清。在推导foo
的参数类型时,ref是否正在崩溃?如果是这样,为什么常量被忽略?
答案 0 :(得分:3)
让我们看看如果我们尝试实例化Foo
类模板会发生什么:
template<typename T>
struct Foo {
void foo(T const&) {}
void foo(T&) {}
};
使用模板参数double&
。用double&
代替T并根据参考折叠规则得到:
struct Foo {
void foo(double& const) {}
void foo(double&) {}
};
由于引用本质上是常数double& const
等同于double&
。因此,您将获得以下实例:
struct Foo {
void foo(double&) {}
void foo(double&) {}
};
编译器大喊“你不能用相同的签名重载foo
”。
CLANG给出了一个更简洁的错误:
错误:'foo'的多次重载实例化到同一个签名 'void(double&amp;&amp;)'void foo(T&amp;){}