Template argument deduction/substitution fails for implicit conversion [duplicate]

21 hours ago 1
ARTICLE AD BOX

Template argument deduction does not consider any potential type conversions - mainly because deduction happens before any such conversions can happen.

Basically, when the compiler sees fun(a), it first gathers a set of foo functions that are eligible to service that call. If a foo function template is found, the compiler tries to generate a concrete function from it by substituting the template arguments with the types of arguments passed in the call statement. That's where the template argument deduction happens. No type conversion can happen here because there is no concrete type to convert to. In your example, B<T> is not a type to convert to because T is unknown and it cannot be discovered from an argument of type A<int>. It is also not known whether an arbitrary instance of B<T> will be constructible from A<int> because different specializations of B may have different sets of constructors. Hence the deduction fails in your case.

If the deduction succeeds, the concrete function (with the deduced argument types) is added to the candidate set.

When the set of candidates is gathered, then the best matching candidate is chosen. At this point argument conversions are considered. The conversions are possible since the candidates are no longer templates, and the target types for conversions are known.

What you could do to work around it is to allow the compiler to deduce the template as well and then construct B<T> explicitly:

template<typename... Ts> void fun_impl(B<Ts>...); template<template<typename> class X, typename... Ts> std::enable_if_t<(std::is_constructible_v<B<Ts>, X<Ts>> && ...)> fun(X<Ts>... args) { fun_impl(B<Ts>(args)...); } int main() { A<int> a; fun(B(a)); // works, instantiates fun<B, int> fun(a); // works, instantiates fun<A, int> }
Read Entire Article