Consider the following function template calls:
#include <optional>
template <class T = int>
void f(std::optional<T>);
int main() {
f(1); // (1)
f({}); // (2)
}
The first call (1) doesn't compile: type-deduction should occur before any type-conversion of the arguments can take place, but T
cannot be deduced in this context.
However, (2) does compile, and the default template argument is used. Why?
During template argument deduction from a function call, braced-init-list arguments are treated specially: in particular, type deduction is never attempted from an empty initializer list argument. For the call to be well-formed, arguments for template parameters in the type of the corresponding function parameter must be obtained elsewhere (for example, by deduction from other function arguments, or, as in this case, from default template arguments). This is called a non-deduced context; see [temp.deduct.type] for details.
A plain int
argument, on the other hand, gets no such treatment: in the call f(1)
, deduction is attempted as usual for the int
/std:optional<T>
argument/parameter pair, and fails (since there is no T
that makes the types match) before reaching the step where default template arguments are considered, making the call ill-formed.