`auto(expr)` 在表达式语句的开头是否被视为强制转换?

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

我有一个简单的代码片段如下所示 (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
}

GCC 和 Clang 都发出错误显示:

// 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

来自 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.

所以你的用法似乎被上面引用的声明所允许(根据 )。

Here 是您的代码的工作演示。请注意,在链接的演示中,只有使用 auto(x) 会产生错误,所有其他情况都可以正常工作。


另请注意,来自 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:

这是展示 C++ 如何成为一种上下文敏感语言 的示例之一。如果不了解其更广泛的上下文,就不能总是理解一个结构。考虑以下示例:

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
}

据我所知 the paper 除了允许 auto 作为 functional-style 显式转换中的类型说明符外,引入此功能并没有做任何进一步的相关更改。

所以凭直觉 auto 这里的行为应该与任何其他类型说明符的行为相同。

例如,将 auto 替换为 int,预计所有这些情况都有效并且是 functional-style 显式转换,除了

int(x); // auto(x);

根据语法,这也可以是名为 xint 类型(或占位符类型)变量的声明,声明符周围有括号且没有初始值设定项。

像往常一样,通过更喜欢将解释作为声明来消除语法歧义(参见 [stmt.ambig]/1). At least, I don't think that it should be different for auto. A declaration with auto placeholder type requires an initializer, which is not present in this interpretation, but according to [stmt.ambig]/3 消除歧义应该很早就完成并且纯粹是语法,即使它以 ill-formed 声明结束.我不完全确定,但我想这应该意味着 auto(x); 仍然应该作为声明来消除歧义。

我不知道为什么 Clang 会为许多其他行提供错误。我想该功能要么只实现了部分,要么这些是实现错误(这是未完成的标准修订版中的一个非常新的功能)。

我认为 auto(x)(其中 x 实际上是一个标识符)在不同的上下文中仍然可以有不同的含义,因此在 C++23 中受制于 [dcl.ambig.res]

不幸的是,歧义不太可能得到修复。在以下程序中(well-formed 自 C++11 起),auto(x) = Bar{}; 被解释为声明。如果 auto(x) 是“固定的”,auto(x) = Bar{}; 将成为一个表达式语句,这将改变现有的行为。

#include <cstdio>
struct Bar {
    Bar()
    {
        std::puts("initialization");
    }
};

struct Foo {
    void operator=(Bar)
    {
        std::puts("assignment");
    }
};

int main()
{
    Foo x{};
    {
        auto(x) = Bar{}; // only prints "initialization"
    }
}