Summary
The template call max(4, 4.2) does not return a float because template argument deduction requires both parameters to have the same deduced type, and no single type can be deduced from int and double simultaneously. This prevents the template from being instantiated at all.
Root Cause
- Template argument deduction must deduce one unique type
Tfor all template parameters. - Passing
4(anint) and4.2(adouble) forces the compiler to deduceTas bothintanddouble, which is impossible. - Because deduction fails, the function template is not viable, and overload resolution will not select it.
Why This Happens in Real Systems
- Templates do not perform implicit type promotion during deduction; they only match exact types.
- Mixed-type calls require either overloads or additional template parameters, not a single-type template.
- Returning a reference requires both arguments to be lvalues of the same type, which is not true for mixed literals.
Real-World Impact
- Developers may assume templates behave like macros and “figure out” the best type, but:
- Compilation errors occur when mixed types are passed.
- Unexpected overload selection may happen if other overloads exist.
- Reference return types become invalid when temporaries are involved.
Example or Code (if necessary and relevant)
A corrected version using two template parameters:
template
auto max2(A const& a, B const& b) {
return a < b ? b : a;
}
This returns by value, avoiding references to temporaries.
How Senior Engineers Fix It
- Use two-type templates (
<A, B>) and return by value. - Use
std::common_typeto compute a safe return type. - Avoid returning references when arguments may be temporaries.
- Provide overloads or concepts to constrain valid calls.
Why Juniors Miss It
- They assume templates behave like dynamic polymorphism and “adapt” automatically.
- They overlook that template deduction is strict, not heuristic.
- They misunderstand that references cannot bind safely to temporaries in mixed-type expressions.
Would you like an expanded version showing how std::common_type solves this pattern?