RustyX RustyX - 1 month ago 9
C++ Question

Template function argument deduction with an implicit conversion

I understand that template function argument deduction does not take implicit conversions into account.

So this code doesn't compile:

#include <iostream>

template<class T>
struct A {};
struct B : public A<int> {};
struct C {
operator B() { return {}; }
};

template<class X>
void test(A<X> arg1, A<X> arg2) {
std::cout << "ok1";
}

int main() {
B b;
C c;
test(b, c); // error: no matching function for call to 'test'
}


What I don't understand is how adding an extra level of indirection with an identity
typedef
somehow makes it work:

#include <iostream>

template<class T>
struct A {};
struct B : public A<int> {};
struct C {
operator B() { return {}; }
};

template<typename U> struct magic { typedef U type; };

template<class T> using magic_t = typename magic<T>::type;

template<class X>
void test(A<X> arg1, A<X> arg2) {
std::cout << "ok1";
}

template<class X>
void test(A<X> arg3, magic_t<A<X>> arg4) {
std::cout << "ok2";
}

int main() {
B b;
C c;
test(b, c); // prints "ok2"
}


Live demo on Godbolt

How does
magic_t<A<X>>
end up matching
C
?

Answer Source

The second parameter becomes non-deduced context and doesn't participate in template argument deduction. X is then successfully deduced from the first argument.