我已经看到C 中的歧义错误已经存在问题,但这是某种不同的问题。
假设我们的代码如下:
#include <iostream>
#define LDBG(msg)
std::cout << "[" << __FUNCTION__ << " " << __LINE__ << "] " << msg << std::endl;
template<typename T>
struct AClass{
AClass(T a) {}
void Foo(const AClass<T> &other){
LDBG("")
}
void Foo(const T &key) const{
LDBG("")
}
};
int main(){
AClass<int> a1{1};
AClass<int> a2{2};
a1.Foo(1);
a1.Foo(a2);
LDBG("")
return 0;
}
这将产生汇编错误,例如:
error: call to member function 'Foo' is ambiguous
a1.Foo(1);
~~~^~~
note: candidate function
void Foo(const AClass<T> &other){
^
note: candidate function
void Foo(const T &key) const{
^
1 error generated.
如果以下情况,错误将消失:
- 在第14行(
void Foo(const T &key) const{
)处删除const
或2。在void Foo(const AClass<T> &other)
的末尾加一个const
或3。将构造函数更改为AClass() {}
(也是主函数中A1和A2的相对初始化)
或其他一些方法。
这三个或多个纠正如何,原始的问题是什么?
此构造函数定义了从 T
到 AClass<T>
的隐式转换:
AClass(T a) {}
给定a1.Foo(1)
:
-
void Foo(const AClass<T> &other)
是隐式对象参数的更好匹配,并且在other
上匹配更差(因为它需要用户定义的转换) -
void Foo(const T& key) const
是key
上更好的匹配(因为它是确切的匹配),并且由于添加了const
。
因为这两个功能都不比另一个功能好(每个函数在一个参数上更好,而另一个参数都更好),所以呼叫是模棱两可的。
您的前两个修复程序使这两个函数同样好,w/r/t是隐式对象参数,因此T
版本明确获胜。您的第三个修复程序使AClass<T>
功能不再可行,因为隐式转换不再存在。