Why is implicit conversion not applied to templated function parameter?

item<int> i;
template <typename T> void butNotWhenTemplated (const item<const T> &) { }
butNotWhenTemplated(i); 

According to template argument substitution rules, no T could be found for item<const T> to match item<int>. This fails with an hard error way before any conversion (builtin or user-defined) could be considered.

Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later. However, if deduction succeeds for all parameters that participate in template argument deduction, and all template arguments that aren't deduced are explicitly specified or defaulted, then the remaining function parameters are compared with the corresponding function arguments.


Try this overload:

template <typename T>
void butNotWhenTemplated(const item<const T>&) { }

template <typename T>
void butNotWhenTemplated(const item<T>& x) {
    butNotWhenTemplated<const T>(x);
}

Addendum:

You're trying to pass by reference to const, but implicit conversion creates a copy of your object, even in the non-template case. You might want to rethink your design here.