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
Pcan 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_listor reference to possibly cv-qualifiedstd::initializer_listtype.
... 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?
- If so, is there an associated defect report(1)?
- If not, what passages of the C++14 standard covers that
#1above is well-formed?
(1) I've tried to find one myself without any success.