std :: ignore with structured bindings?

jot*_*tik 61 c++ language-lawyer c++17

序幕:

std::tuple<int, int, int> f();
std::tuple<int, int, float, int> g();
Run Code Online (Sandbox Code Playgroud)

C++ 1z将引入结构化绑定的语法,这样可以编写代替

int a, b, c;
std::tie(a, b, c) = f();
Run Code Online (Sandbox Code Playgroud)

就像是

auto [a, b, c] = f();
Run Code Online (Sandbox Code Playgroud)

但是,std::tie也允许指定std::ignore忽略某些组件,例如:

std::tie(a, b, std::ignore, c) = g();
Run Code Online (Sandbox Code Playgroud)

是否可以使用新的结构化绑定语法执行类似的操作?它会如何工作?

met*_*fox 46

结构化绑定提案包含一个回答您问题的专用部分(P0144R2):

3.8是否应该有明确忽略组件的方法?

动机是使编译器关于未使用名称的警告静音.我们认为答案应该是"还没有."这不是出于用例的原因(沉默编译器警告是一种动机,但它本身并不是一个用例),最好留待我们在上下文中重新考虑这一点.一个更一般的模式匹配提案,这应该作为一个特例.

对称与std::tie建议使用类似的东西std::ignore:

tuple<T1,T2,T3> f();

auto [x, std::ignore, z] = f(); // NOT proposed: ignore second element
Run Code Online (Sandbox Code Playgroud)

然而,这感觉很尴尬.

预期语言中的模式匹配可能会建议使用_或者通配符*,但由于我们还没有模式匹配,因此选择我们知道将兼容的语法为时过早.这是一个纯粹的扩展,可以等待模式匹配.

但请注意,标准的工作草案目前正在由相关的国家机构(NB)进行修订,并且有一条NB评论要求此功能(P0488R0,US100):

分解声明应该提供语法来丢弃一些返回的值,就像std::tie使用一样std::ignore.

  • @DanielH,他们必须在拥有众多功能来完成同一件事(臃肿、难以教授、更容易出错)之间取得平衡,或者等待人们有一些额外的变量未使用的惩罚。正如他们所说,当他们引入通用模式匹配时,忽略结构化绑定的部分是可行的(已经提出了“inspect”,并且也有“is”和“as”关键字)。他们不会支持“std::ignore”与稍后添加的内容相结合,而是只拥有稍后添加的内容。这是复杂语言中的简化祝福。 (4认同)
  • 现在为时已晚,但我要指出的是,一个使用起来很尴尬并且将来可能会被替换的功能比*根本没有能力使用该功能*要好,而且这似乎不像这种事情会使标准委员会希望成为一台时光机,因为在结构化绑定中没有其他对std :: ignore的合理解释。 (3认同)

dav*_*igh 10

C++26 将引入一个没有名称的漂亮占位符 (P2169R0)。借助这一新的语言功能,人们最终可以用作_忽略结构化绑定表达式中的变量的一种方法。有关设计的详细信息,请参阅链接文档。


Nic*_*las 7

使用新的结构化绑定语法是否可以做类似的事情?

不。您只需要组成一个变量名,以后将不再提及。

  • 它将生成未使用的变量警告`-Wunused-variable`,您可以使用:`[[maybe_unused]] auto [a,b,dummy] = std :: tuple(1,“ 2”,3f);`但这意味着它们中的任何一个都可能未被使用,您将不知道哪个。目前没有针对这种情况的好的解决方案。希望它将在c ++ 20中得到改善。取自此处:/sf/ask/2898280101/?noredirect=1&amp;lq=1 (20认同)
  • @andreee:用完一个语句只是为了消除警告不是我所说的“好的解决方案”。 (6认同)
  • “用完一份声明只是为了平息警告……”我们的声明用完了吗? (5认同)
  • @AndyJost:不,但我们已经耗尽了屏幕上的视觉空间。花费它,特别是宝贵的垂直空间来消除警告是没有用的。 (3认同)
  • @jotik:那总是会发生的。“变量”不是一个独特的对象;而是一个独立的对象。它是其他对象的子对象。该“其他对象”只有在离开范围时才会被销毁。你不能随意破坏物体的一部分。 (3认同)
  • @serine:如果某些但不是全部结构化绑定未使用([dcl.attr.unused]/4),编译器不应该发出警告。 (3认同)
  • _“目前没有针对这种情况的好的解决方案” _:并非完全正确:[您可以简单地使用`(void)dummy;`来消除未使用的变量警告](https://stackoverflow.com/问题1486904 /如何在不影响其他变量的情况下保持最佳警戒状态)。 (2认同)

foo*_*foo 7

我通常使用_C++ 中的有效标识符,但看起来与 Kotlin 的下划线运算符相同,它会丢弃 lambda 参数。你最终会得到一个像这样的漂亮代码

map([&](auto it) {
    auto [_, deviceServiceXAddr] = it;
    return deviceServiceXAddr;
});
Run Code Online (Sandbox Code Playgroud)

  • 更不用说如果您想忽略多个变量,这将不起作用。 (17认同)
  • @somebody4 • `_______________` 是一个保留标识符,以这种方式使用它是**未定义的行为**。 (15认同)
  • @303 • 标识符中任何位置带有双下划线的所有标识符都被保留(特别是供编译器使用)。将它们用于您自己的代码就是 UB。 (10认同)
  • 我想这种方法的缺点仍然是“_”的生命周期将在语句之后继续,而“_”只会在离开作用域时被销毁。 (2认同)