Reputation: 1279
I've seen there are already questions about ambiguous error in C++, but this is some kind of different.
Let's say we have code like following:
#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;
}
This will produce compiling error like:
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.
The error will just be gone if:
void Foo(const T &key) const{
)or 2. Add a const at the end of void Foo(const AClass<T> &other)
too
or 3. Change the Constructor into AClass() {}
(also the relative Initialization of a1 and a2 in main function)
or some other ways.
How do these 3 or more rectification wrok, what's the problem of the original?
Upvotes: 0
Views: 1816
Reputation: 137330
This constructor defines an implicit conversion from T
to AClass<T>
:
AClass(T a) {}
Given a1.Foo(1)
:
void Foo(const AClass<T> &other)
is a better match on the implicit object parameter and a worse match on other
(since it requires a user-defined conversion)void Foo(const T& key) const
is a better match on key
(because it's an exact match) and a worse match for the implicit object parameter because of the adding of const
.Because neither function is unambiguously better than the other (each is better on one parameter and worse on the other), the call is ambiguous.
Your first two fixes make the two functions equally good w/r/t the implicit object parameter, so the T
version unambiguously wins. Your third fix makes the AClass<T>
function no longer viable because the implicit conversion doesn't exist anymore.
Upvotes: 1