I recently yet again encountered the notation
( const int[10] ){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }
As I recall it's permitted in both C and C++, but via quite different language mechanisms.
I believed that in C++ the formal view is that it's a construction of an unnamed temporary via an epxlicit type conversion (T)
cast-expression that would reduce to a static_cast
, that constructs an object via C++11 §5.2.9/4:
” an expression
e
can be explicitly converted to a typeT
using astatic_cast
of the formstatic_cast<T>(e)
if the declarationT t(e);
is well-formed, for some invented temporary variablet
(8.5)
However, the cast-expression syntax is defined by C++11 §5.4/2 as being either unary-expression or, recursively, a (
type-id )
cast-expression, where the single base case is reduction to unary-expression.
And as far as I can tell a braced init-list is not an expression?
An alternative view could be that it’s an explicit type conversion via functional notation, C++11 §5.2.3/3,
” a simple-type-specifier or typename-specifier followed by a braced-init-list creates a temporary object of the specified type
but as far as I can tell a simple-type-specifier can’t involve parentheses, and a typename-specifier involves the keyword typename
?
Per C99 (well, actually N1256 which is the prior draft) 6.5.2.5/4:
A postfix expression that consists of a parenthesized type name followed by a brace-enclosed list of initializers is a compound literal. It provides an unnamed object whose value is given by the initializer list.
Some compilers - at least g++ and clang - provide C99 compound literals in C++ as an extension. Semantically, the expression
( const int[10] ){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }
is a literal of type const int[10]
: decltype((const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 })
is in fact const int[10]
. Note well: There's some disagreement among g++ versions about the exact type: g++ versions before 4.9 says that decltype((const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 })
is const int(&)[10]
. See this demonstration program.
You can achieve the same result in standard C++ with explicit type conversion via functional notation, but you must define a type alias for the array type since functional notation requires a simple-type-specifier:
using foo = const int[10];
foo{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
or Xeo's general alias template:
template <typename T>
using foo = T;
foo<const int[10]>{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With