Search code examples
c++language-lawyerc++23

Is `auto(expr)` treated as cast at the beginning of the expression statement?


I have a simple code snippet shown below (https://godbolt.org/z/cPT3PhYdj):

int main() {
  int x = 1;
  auto(1); // ok in GCC, error in Clang
  auto{1}; // ok in GCC, error in Clang
  static_cast<void>(auto(x)); // ok
  auto{x}; // ok in GCC, error in Clang
  auto(x); // both error in GCC an Clang
}

Where both GCC and Clang emit an error showing:

// by GCC Trunk [-std=c++23]
<source>: In function 'int main()':
<source>:7:3: error: declaration of 'auto x' has no initializer
    7 |   auto(x); // why
      |   ^~~~
Compiler returned: 1

// by Clang Trunk [-std=c++2b]
<source>:3:8: error: expected unqualified-id
  auto(1); // why
       ^
<source>:3:8: error: expected ')'
<source>:3:7: note: to match this '('
  auto(1); // why
      ^
<source>:4:7: error: expected unqualified-id
  auto{1}; // why
      ^
<source>:6:7: error: expected unqualified-id
  auto{x}; // why
      ^
<source>:7:8: error: redefinition of 'x'
  auto(x); // why
       ^
<source>:2:7: note: previous definition is here
  int x = 1;
      ^
<source>:7:8: error: declaration of variable 'x' with deduced type 'auto' requires an initializer
  auto(x); // why
       ^
6 errors generated.
Compiler returned: 1
  • If C++23 is experimental, and will they be able to fix the ambiguity or change the disambiguation since another auto(expr) is introduced, or just leave it be?

  • Are these expressions supposed to be parsed as explicit type decay conversion auto(expr) or auto{expr} in expression statements or parsed as a declaration?

  • If there is no ambiguity, then which priority comes first:

    • auto(identifier) as auto identifier?, or
    • auto(identifier) as cast expression?

Solution

  • From Explicit cast conversion:

    auto ( expression )   (8)     (since C++23)
    
    auto { expression }   (9)     (since C++23)
    

    8,9) The auto specifier is replaced with the deduced type of the invented variable x declared with auto x(expression); (which is never interpreted as a function declaration) or auto x{expression}; respectively. The result is always a prvalue of an object type.

    So your usage seems to be allowed(in accordance with ) by the above quoted statement.

    Here is a working demo of your code. Note in the linked demo, only the usage auto(x) produces an error, all other cases work fine.


    Also note that from PR105516:

    auto(x); is interpreted as auto x;. Use +auto(x); if you want that to be an expression.


    If there is no ambiguity, then which priority comes first:

    This is one of the examples showing how C++ is a context sensitive language. A construct cannot always be understood without knowing its wider contexts. Consider the following example:

    int main()
    {
        int x = 0   ;
        int k       ;
    //------vvvvvvv----->here auto(x) is behaves as an expression as it is used as an expression 
        k = auto(x) ;
    
        auto(p)     ;  //this a declaration and not an explicit case unlike the above
    }