xinaiz
xinaiz

Reputation: 7788

Explicitly choose which template overload should be used

Can we chose which function template overload 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());
}

Error:

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 normal function it looks like this:

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

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

Is it possible?

Upvotes: 3

Views: 144

Answers (3)

W.F.
W.F.

Reputation: 13988

If you choose not to explicitly specify the first parameter type but still want to specify the second you could go along with lambda dedicated for 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]

Upvotes: 2

Christian Hackl
Christian Hackl

Reputation: 27518

A low-tech solution to this problem would be to add one extra level of indirection. Add a function like funA, whose sole purpose is to give an explicit name to the first version of 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 cannot just change the argument to A(X()). You will have to change the calling code anyway, so what's the problem?

Upvotes: 1

max66
max66

Reputation: 66190

Improving your example, you can try with

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

Upvotes: 3

Related Questions