c++castinglanguage-lawyergrammarbraced-init-list

Is (multi-word type name){expression-list} legal?


Consider:

(long long){1};

It’s not a C-style cast expression per [expr.cast]/1:

The result of the expression (T) cast-expression is of type T. The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type; otherwise the result is a prvalue.

cast-expression:

  • unary-expression
  • ( type-id ) cast-expression

{1} shouldn't be a cast-expression.

It's also not a functional-style cast expression per [expr.type.conv]/1:

A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer. If the type is a placeholder for a deduced class type, it is replaced by the return type of the function selected by overload resolution for class template deduction for the remainder of this subclause. Otherwise, if the type contains a placeholder type, it is replaced by the type determined by placeholder type deduction ([dcl.type.auto.deduct]).

simple-type-specifier:

  • nested-name-specifier opt type-name
  • nested-name-specifier template simple-template-id
  • decltype-specifier
  • placeholder-type-specifier
  • nested-name-specifier opt template-name
  • char
  • char8_­t
  • char16_­t
  • char32_­t
  • wchar_­t
  • bool
  • short
  • int
  • long
  • signed
  • unsigned
  • float
  • double
  • void

(long long) shouldn't be a simple-type-specifier.

It doesn't seem legal, but it should be, why?


Solution

  • It is not valid syntax in ISO standard C++.

    In C it is the syntax for a compound literal. Compilers by default often support that also in C++ mode as an extension. When enabling strict(er) standard conformance they should reject it or at least provide a warning (e.g. with -pedantic, -pedantic-errors)

    Whether there are multiple words doesn't matter by the way. (long){1} has the same problem. (/*..*/){/*..*/} can't be syntax for an expression as can be seen from the standard quotes you gave.

    Also, in C such a compound literal is an lvalue like string literals. That would be confusing in C++, where an analogues cast expression, i.e. T{1} with using T=long long;, produces a prvalue. The lifetime of the resulting object is also very different. Therefore supporting them in C++ would either have a different meaning as in C or mean a confusing difference between (T){e}and T{e}.

    Here is a closed proposal from 2020-2022 to introduce compound literals in C++. As you can see from the voting results there wasn't a consensus whether to add them at all or what behavior they should have.