This code does compile (the important point is that F() only accepts As, and since there is an implicit conversion from B to A, I can easily pass a B to it.)
struct A {};
struct B {
constexpr operator A () const {return {};}
};
void F (A a) {}
int main() {
F(B());
return 0;
}
But the templated version does not compile:
template <typename T>
struct A {};
template <typename T>
struct B {
constexpr operator A<T> () const {return {};}
};
template <typename T>
void F (A<T> a) {}
int main() {
F(B<int>());
return 0;
}
with the following error on GCC (and equivalent on MSVC):
error: no matching function for call to ‘F(B<int>)’
(with additional info that there is an F(A<>) but B does not inherit from A.)
For the record, implementing an implicit conversion operator in A doesn't help either.
Why doesn't the template version compile? Am I missing something? Or there is actually no way to do it with class templates?!
(Note: I know that I can explicitly cast B to A at call site; this is not something I prefer.)