The std::exchange
was proposed in N3511 without default template argument, and later N3608 with a default template argument. Note that in N3608 the following reasoning was provided:
Giving the second template argument a default value fixes the
following two cases:
DefaultConstructible x = ...;
if (exchange(x, {})) { ... }
int (*fp)(int);
int f(int);
double f(double);
/*...*/ exchange(fp, &f) /*...*/
The first example's usefullness is of course that an untyped temporary {}
will be deduced to T
. The second example is more involved:
14.8.2 Template argument deduction [temp.deduct]
5 The resulting substituted and adjusted function type is used as the
type of the function template for template argument deduction. If a
template argument has not been deduced and its corresponding template
parameter has a default argument, the template argument is determined
by substituting the template arguments determined for preceding
template parameters into the default argument. If the substitution
results in an invalid type, as described above, type deduction fails.
14.8.2.5 Deducing template arguments from a type [temp.deduct.type]
4 In most cases, the types, templates, and non-type values that are
used to compose P participate in template argument deduction. That is,
they may be used to determine the value of a template argument, and
the value so determined must be consistent with the values determined
elsewhere. In certain contexts, however, the value does not
participate in type deduction, but instead uses the values of template
arguments that were either deduced elsewhere or explicitly specified.
If a template parameter is used only in non-deduced contexts and is
not explicitly specified, template argument deduction fails.
5 The non-deduced contexts are:
(5.5) — A function parameter for which argument deduction cannot be
done because the associated function argument is a function, or a set
of overloaded functions (13.4), and one or more of the following
apply:
(5.5.1) — more than one function matches the function parameter
type (resulting in an ambiguous deduction)
In the second example, the template parameter U
is only used in a non-deduced context because the two overloads f(int)
and f(double)
both can be matched to U
. Hence, argument deduction does not take place, and U
becomes the supplied default value of T
(int (*)(int)
in this case, so f(int)
is selected).
In addition, as explained by @VladfromMoscow, having a defaulted parameter allows for shorter code when passing std::exchange<T>
(to a standard algorithm e.g.).