【问题标题】:std::ignore with structured bindings?std::ignore 与结构化绑定?
【发布时间】:2017-04-02 01:38:36
【问题描述】:

前奏:

std::tuple<int, int, int> f();
std::tuple<int, int, float, int> g();

C++1z 将引入结构化绑定的语法,这将使编写而不是

成为可能
int a, b, c;
std::tie(a, b, c) = f();

类似

auto [a, b, c] = f();

不过,std::tie 也允许指定 std::ignore 以忽略某些组件,例如:

std::tie(a, b, std::ignore, c) = g();

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

【问题讨论】:

  • 随便放一个名字就行了。
  • @n.m.任意名称不会创建副本吗?
  • @Piotr 我认为不会比std::ignore 多。由于我们保证了复制省略,因此初始化了虚拟变量;使用std::tie,在分配给std::ignore 的右侧的临时值被初始化。
  • 可能会有一个宏 auto[IGNORE] 生成一个唯一的名称(例如:使用编译器特定的 COUNTERLINE)。它具有足够的可读性,并且在实践中的功能类似于 std::ignore for std::tie
  • @PiotrSkotnicki 不,decomp 声明所做的唯一副本是被分解的东西。被声明的事物要么是该事物的成员/元素的别名,要么是绑定到 get 返回的引用。

标签: c++ language-lawyer c++17


【解决方案1】:

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

map([&](auto it) {
    auto [_, deviceServiceXAddr] = it;
    return deviceServiceXAddr;
});

【讨论】:

  • 我猜这种方法的缺点仍然是_ 的生命周期将在语句之后继续,而_ 只会在离开作用域时被销毁。
  • 更不用说,如果您希望忽略多个变量,这将不起作用。
  • jotik> 正如有人在另一条评论中指出的那样,您绑定的变量容器的生命周期在语句之后继续,所以它的所有内容也是如此。即使您无法绑定某些片段,它们仍然会存活到容器生命周期结束。
  • 自动 [,,,______________,foo] = bar; =]
  • @somebody4 • _______________ 是一个保留标识符,以这种方式使用它是未定义的行为
【解决方案2】:

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

3.8 是否有办法显式忽略组件?

动机是使编译器对未使用名称的警告保持沉默。 我们认为答案应该是“还没有”。这不是由用例引起的(消除编译器警告是一种动机,但它本身不是用例),最好留到我们可以在更通用的模式匹配提议的上下文中重新审视这一点之前,这应该失败作为特例。

std::tie 的对称性建议使用std::ignore 之类的东西:

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

auto [x, std::ignore, z] = f(); // NOT proposed: ignore second element

但是,这感觉很尴尬。

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

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

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

【讨论】:

  • 现在为时已晚,但我要指出,使用起来感觉很尴尬并且将来可能会被替换的功能总比完全无法使用该功能要好,这似乎不会让标准委员会希望有一台时间机器,因为在结构化绑定中没有其他合理的 std::ignore 解释。
【解决方案3】:

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

没有。你只需要编一个后面不会提到的变量名。

【讨论】:

  • 这将产生未使用的变量警告-Wunused-variable ,您可以使用:[[maybe_unused]] auto [ a, b, dummy ] = std::tuple(1,"2",3f); 但这意味着它们中的任何一个都可能未使用,您将不知道是哪一个。目前没有很好的解决方案。希望它会在 c++20 中得到改进。取自这里:stackoverflow.com/questions/41404001/…
  • “目前这种情况没有好的解决方案”:这并不完全正确:You can simply use (void)dummy; to get rid of the unused variable warning 不会影响其他变量。
  • @andreee:使用声明来消除警告并不是我所说的“好解决方案”。
  • @AndyJost:不,但是我们的屏幕上的可视空间已经用完了。把它,特别是宝贵的垂直空间,花在消除警告上是没有用的。
  • @jotik:这总是会发生的。 “变量”不是一个独特的对象;它是某个其他对象的子对象。那个“其他对象”只会在离开作用域时被销毁。你不能随便破坏一个对象的一部分。
猜你喜欢
  • 2020-02-09
  • 2017-05-15
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-07
相关资源
最近更新 更多