C++26 中 _ 下划线变量的规则是什么,什么是与名称无关的声明?

Jan*_*tke 7 c++ local-variables identifier c++26

当我编译以下代码时,我收到警告(https://godbolt.org/z/Tx7v6jWf1):

void foo() {
    int _;
    // warning: name-independent declarations only available with
    //           '-std=c++2c' or '-std=gnu++2c' [-Wc++26-extensions]
    int _;
}
Run Code Online (Sandbox Code Playgroud)

C++26 中的变量到底发生了什么变化_,什么是名称独立声明

Jan*_*tke 10

P2169: C++26 已接受一个没有名称的漂亮占位符_,这在以下上下文中很特殊:

  • 局部变量(例如int _
  • 本地结构化绑定(例如auto [x, _]
  • 初始化捕获(例如[_ = 0] {}
  • 匿名联合体以外的非静态数据成员(例如struct S { int _; }

在这种情况下,_使声明与名称无关

_抑制警告

标准说:

推荐实践:实现不应发出关于使用或未使用名称无关声明的警告。

这与[dcl.attr.unused] p4[[maybe_unused]]中的建议非常相似。通常,您会收到未使用变量的警告(在 GCC 中),但是并抑制此警告。-Wunused_[[maybe_unused]]

从历史上看,开发人员将其用作_未使用事物的“占位符”,因此这只是标准化现有实践。

_可以多次声明

此外,与名称无关的声明不会存在潜在冲突。简而言之,可以_多次声明。但是,名称查找不能有歧义。

void g() {
  int _;
  _ = 0;   // OK, and warning is not recommended
  int _;   // OK, name-independent declaration does not potentially conflict with the first _
  _ = 0;   // error: two non-function declarations in the lookup set
}
Run Code Online (Sandbox Code Playgroud)

此代码取自[basic.scope.scope] 示例 3

请注意,_它还与声明有一些特殊的交互using。有关更多详细信息,请参阅[namespace.udecl] p10 。

从链接器的角度来看,两个_不是同一实体

即使有外部链接,两个_也不被视为同一实体:

// a.cpp
int _ = 0;
Run Code Online (Sandbox Code Playgroud)
// b.cpp
int _ = 0;
Run Code Online (Sandbox Code Playgroud)

链接后,该程序就可以了。对于 以外的任何名称_,这会给您一个“多重定义”链接器错误。另请参阅[basic.link] p8

编译器支持

在撰写本文时,只有 GCC 14 和 Clang 18 支持此功能。有关更多信息,请参阅C++26 编译器支持

如果您需要测试支持,请测试__cpp_placeholder_variables

// b.cpp
int _ = 0;
Run Code Online (Sandbox Code Playgroud)

  • @ABaumstumpf 这种“神秘的语法和不直观的行为”绝不是“神秘的语法和不直观的行为”,并且使用 `std::ignore` 来解决这个问题绝不是“更好”或“更一致”。`ignore = lock_guard{mtx}` 会立即释放锁,这完全不是你想要的。 (2认同)