Ambiguity between const match function in the best way and another function

Consider the following example:

#include <type_traits> #if 1 struct X {}; struct O { O(X) { ; } }; #else struct O {}; struct X { operator O () { return {}; } }; #endif static_assert(std::is_convertible< X, O >::value); struct S { void f(X) const { ; } void f(O) { ; } }; #include <cstdlib> int main() { S s; sf(X{}); return EXIT_SUCCESS; } 

Living example

This gives an error:

  error: call to member function 'f' is ambiguous 

When I remove const -qualifier, the error ceases to exist. Likewise, if I add a const -qualifier to the second overload of f . That is, if both overloads are equally const -qualified, then everything is fine.

Why is this so?

My compiler is clang 3.8.

+5
source share
3 answers

Member functions have an implicit this parameter.

Thus, to call one of the functions f compiler must either convert this to type const S * or convert X to O

Not a single change in all respects is better. Therefore, the compiler generates an error message.

+2
source

Why is it so? : The reason here is that the constant of the object s also considered when overload resolution is enabled. Since s not a constant, this requires adding const to the implicit this pointer to call const f . Calling non-const f is an exact match for the this pointer, but requires an implicit conversion from X to O through the O conversion constructor.

+2
source

Mark B and Vlad from Moscow, answer why I just answer, as you can name them.

you must add explicit to avoid implicit compiler conversion

 #include <iostream> struct X {}; struct O { explicit O(X) { ; } O() = default; O(O const &) = default; O(O &&) = default; }; struct S { void f(X) const { ; } void f(O) { ; } }; #include <cstdlib> int main() { S s; sf(X{}); return EXIT_SUCCESS; } 

EDIT

if your type O is in 3party lib you can add a template for this.

 #include <iostream> using namespace std; struct X {}; struct O { O(X) { ; } O() = default; O(O const&) = default; O(O&&) = default; }; struct S { void f(const X) const { cout << "X" << endl; } void f(O) { cout << "O" << endl; } }; #include <cstdlib> template<typename TA, typename TB> void myCall(TA a, TB b) { ((const TA &&)a).f(b); } template<> void myCall(S a, O b) { af(b); } template<> void myCall(S a, X b) { ((const S)a).f(b); } int main() { S s; myCall(s, X()); //sf(X()); return EXIT_SUCCESS; } 
+1
source

Source: https://habr.com/ru/post/1240709/


All Articles