It comes as no surprise that the following program
// #1
template<typename T, std::size_t N>
void f(T (&&)[N]) {}
int main() { f({1,2,3}); }
is seemingly well-formed in C++14 (well, at least all compilers that I've tried seems to accepts it).
However, it seems as if this is not supported by the C++14 standard, particularly that T
and N
can be deduced from an initializer list argument?
A given type
P
can be composed from a number of other types, templates, and non-type values:
- [...]
- /3.4 An array type includes the array element type and the value of the array bound.
explains why deduction succeeds for the following example:
template<typename T, std::size_t N>
void f(T (&)[N]) {}
int main() {
int arr[] = {1, 2, 3}; // #2
f(arr);
}
where particularly [dcl.init.aggr]/4 governs that #2
declares and array of size 3
(even though omitted from the type in the declaration).
However, in the context of a function call, as per [temp.deduct.type]/5.6
A function parameter for which the associated argument is an initializer list ([dcl.init.list]) but the parameter does not have
std::initializer_list
or reference to possibly cv-qualifiedstd::initializer_list
type.
... this is a non-deduced context.
From the C++17 standard and onwards [temp.deduct.call]/1 has been updated to express that an array type argument can be deduced from a (non-empty) initializer list, but this was not present in the C++14 standard, and [temp.deduct.type]/5.6, regarding non-deduced contexts, explicitly refers to [temp.deduct.call]/1 for exceptions to the rule.
Was this a defect/underspecification of the C++14 standard?
#1
above is well-formed?(1) I've tried to find one myself without any success.
This is DR 1591.
It would seem reasonable ... to allow an array bound to be deduced from the number of elements in the initializer list, e.g.,
template<int N> void g(int const (&)[N]); void f() { g( { 1, 2, 3, 4 } ); }
Being a DR, it applies retroactively to C++14.
NB: It seems Language Lawyer beat me to it, but I found it independently through git blame of templates.tex
:)