How is it parsed: constructing unnamed temporary with braced init list
Asked Answered
C

1

13

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 type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e); is well-formed, for some invented temporary variable t (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?

Claybourne answered 24/6, 2014 at 11:26 Comment(7)
This is not legal C++. The following is the correct way: Alias<T[N]>{...}.Hagberry
@Hagberry What is Alias supposed to do?Thitherto
template<class T> using Alias = T;, a simply using-alias to make the code parseable.Hagberry
I think it's conventional to use the name identity for that.Mho
@Xeo: thanks, apparently you're right (about it not being valid). The C++ code failed to compile with Visual C++ 12.0 and with g++ 4.8.2 when -pedantic was specified. Without -pedantic g++ accepted the code, presumably as a C99 compound literal used as a C++ extension.Claybourne
@Xeo: if you write up your comment as answer with proper mention of simple-template-id (C++11 §14.2) I'll accept it, then this question will have an SO answer. :)Claybourne
@BenVoigt: I don't know, but I've always used Type, to my mind self-descriptive. For earlier versions of Visual C++ I used Type_T_, which was template< class Type_ > struct Type_T_{ typedef Type_ T; };, with ditto more verbose usage.Claybourne
E
6

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 };
Epicure answered 24/6, 2014 at 15:26 Comment(2)
Why rvalue? It's not a temporary and can take its address in C just fine. In fact, p5 of the same paragraph says In either case, the result is an lvalue.Habitancy
@Habitancy You are of course correct, I was expecting decltype((const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }) to be const int(&)[10] to indicate an lvalue, when in fact it is simply const int[10] just like a literal of any other type.Epicure

© 2022 - 2024 — McMap. All rights reserved.