考虑这个程序:
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 是否正在崩溃?如果是这样,为什么常量被忽略了?
让我们看看如果我们尝试实例化 Foo
类模板会发生什么:
template<typename T>
struct Foo {
void foo(T const&) {}
void foo(T&) {}
};
带有模板参数double&
。将 T 替换为 double&
并根据引用折叠规则,您将得到:
struct Foo {
void foo(double& const) {}
void foo(double&) {}
};
由于引用本质上是常量 double& const
等同于 double&
。因此,您将获得以下实例:
struct Foo {
void foo(double&) {}
void foo(double&) {}
};
编译器大喊“伙计,你不能用相同的签名重载 foo
”。
CLANG给出了一个更简洁的错误:
error: multiple overloads of 'foo' instantiate to the same signature
'void (double &&)' void foo(T&) { }
Live Demo