在 C++17 中,可以使用带有初始值设定项的 if 语句来解压可选项吗?

Posted

技术标签:

【中文标题】在 C++17 中,可以使用带有初始值设定项的 if 语句来解压可选项吗?【英文标题】:In C++17 can an if statement with an initializer be used to unpack an optional? 【发布时间】:2017-01-28 16:22:22 【问题描述】:

我正在使用 std::optional 编写一些代码,我想知道 C++17 的“带有初始化程序的 if 语句”是否能够帮助解包值?

std::optional<int> optionalInt = GetOptionalInt();

我在这里编写函数Unpack:

if( auto [value, has_value] = optionalInt.Unpack(); has_value )

    // Use value here.

但是,我的问题是。 C++17 'if statement with initializer' 在这里有帮助吗?如果是这样,它将如何编码?

更新,这实际上主要是使用 optional 时的一个问题,这非常容易被误用,因为 optional 和 *optional 都返回 bools,并且当有人尝试访问该值并忘记 *.

【问题讨论】:

"if" 是一个语句,而不是表达式。 【参考方案1】:

没有,也不可能有这样的Unpack() 函数。

但你当然可以这样做:

if (std::optional<int> o = GetOptionalInt(); o) 
    // use *o here

虽然额外的o 检查有点多余。


如果optional&lt;T&gt; 建模一个最多包含一个元素的容器,那么这是其中之一,这样您就可以这样做:

for (int value : GetOptionalInt()) 
    // possibly not entered

但我们没有那个界面。

【讨论】:

不可能有一个解包,我猜是因为它必须复制构造你真正想要引用它的值,并且类型必须有一个默认构造函数用于何时没有价值? 我想这已经可以工作了: if (std::optional o = GetOptionalInt()) // 在这里使用 *o @ScottLangham 两个帐户都正确。 @ScottLangham:是的,因为optional 可以根据上下文转换为bool。对于这些情况,现有控制结构的 condition 部分已经足够了,因为它是对某些东西的声明。初始化器对所有 other 情况都很有用,例如if (auto it = m.find(key); it != m.end())。在这种情况下,只有 if (auto it = m.find()) 不起作用,因为单独的迭代器不会形成谓词。 @KerrekSB。是的。在使用 std::optional 的情况下,这一切都变得非常容易出错。很容易忘记 if 正文中的 *。因此,某种解包值并同时测试它是否有效的方法可能有助于避免该错误。我猜 Barry 的 for(int value : GetOptionalInt()) 可能是一个解决方案,一些适配器可以使它工作:for(int value: OptionalToZeroOrOneElementContainer(GetOptionalInt())。可能需要一个更简洁的名称!【参考方案2】:

为了使其工作,如果未打包的值不存在,则必须有一个值。

所以

template<class T, class U>
std::pair< T, bool > unpack_value( std::optional<T> const& o, U&& u ) 
  return  o.value_or(std::forward<U>(u)), (bool)o  )

会做你想做的。

但如果optional 参与bool 上下文,则它已经返回,你真的应该这样做:

if (auto i = get_optional())

然后在正文中使用*i

...

现在,如果optional 声明operator* 返回了一个引用,并且该返回值已定义但未定义访问它,那么您可以编写一个Unpack不需要默认值的方法或函数。

据我所知,这不是真的。而且由于它并没有真正添加任何东西,我不明白为什么它应该是真的。

【讨论】:

【参考方案3】:

也许这会起作用:

auto optValue = getOptional();
if (auto value = *optValue; optValue)  ...use value here... 

【讨论】:

以上是关于在 C++17 中,可以使用带有初始值设定项的 if 语句来解压可选项吗?的主要内容,如果未能解决你的问题,请参考以下文章

React 中是不是仍需要带有自动绑定和属性初始值设定项的构造函数

让编译器检查数组初始值设定项的数量

C中如何实现数组的传值引用

在 C++ 中指定初始值设定项的情况下的模板参数推导

如何使用 clang 格式控制数组初始值设定项的缩进?

SwiftUI 分段控制