Explicitly choose which template overload should be

Can I choose which template overload function should be used in this case?

struct X { };

struct A { A(X){} };
struct B { B(X){} };

template<class T>
void fun(T, A) { }

template<class T>
void fun(T, B) { }

int main() {
    /* explicitly choose overload */ fun(1, X());
}

      

Mistake:

error: call of overloaded 'fun(int, X)' is ambiguous
     /* explicitly choose overload */ fun(1, X());
                                                ^
    candidate: void fun(T, A) [with T = int]
 void fun(T, A) { }
      ^~~
    candidate: void fun(T, B) [with T = int]
 void fun(T, B) { }
      ^~~

      

For a normal function, it looks like this:

void fun(A){}
void fun(B){}

int main() {
    ((void(*)(A))(fun))(X());
}

      

Is it possible?

+3


source to share


3 answers


If you don't want to explicitly specify the first parameter type, but want to specify the second, you can go along with a lambda designed for the casting purpose (C ++ 14 solution):

struct X { };

struct A { A(X){} };
struct B { B(X){} };

template<class T>
void fun(T, A) { }

template<class T>
void fun(T, B) { }

int main() {
    [](auto v, auto x){ static_cast<void(*)(decltype(v), A)>(fun)(v, x); }(1, X());
}

      



[live demo]

+2


source


Improving your example, you can try



 ((void(*)(int, A))(fun))(1, X());

      

+3


source


A low-tech solution to this problem is to add one extra layer of indirection. Add a type function funA

whose sole purpose is to explicitly name the first version fun

:

struct X { };

struct A { A(X){} };
struct B { B(X){} };

template<class T>
void fun(T, A) { }

template<class T>
void fun(T, B) { }

template <class T>
void funA(T t, A a) { fun(t, a); }

int main() {
    /* explicitly choose overload */ funA(1, X());
}

      

However, I wonder why you can't just change the argument to A(X())

. You still have to change the calling code, so what's the problem?

+1


source







All Articles