This code does compile (the important point is that F()
only accepts A
s, 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.)
Template argument deduction doesn't consider implicit conversion.
Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.
The template parameter T
must be deduced at first (before overload resolution), but given the parameter A<T>
with argument B<int>
, T
can't be deduced from them; then compilation fails.
As the workaround, you can use explicit conversion as you said, or specify the template argument explicitly.
F<int>(B<int>());
As better explained by songyuanyao, the template parameter T
must be deduced before.
You can solve the problem explicating the T
type
F<int>(B<int>());
but I understand that can be annoying.
So, as workaround for your problem, I propose another template function that deduce T
before calling F()
template <template <typename> class C, typename T>
void G (C<T> const & c)
{ F<T>(c); }
so you can call F()
, passing through G()
, without explicating the T
type
G(B<int>{});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.