+-
如何最好地测试和解包std :: if语句中的可选参数

我有多个函数返回std::optional<T>。这是一个虚构类型MyType的示例:

struct MyType {
    // ...
}

std::optional<MyType> calculateOptional() {
    // ... lengthy calculation

    if (success) {
        return MyType(/* etc */);
    }

    return std::nullopt;
}

让我们假设这些函数的运行成本很高,我想避免多次调用它们。

调用它们时,我想立即测试该可选内容,如果它包含一个值,我想立即使用它,不再使用。例如,在Swift中,我可以使用标准的if-let语句:

if let result = calculateOptional() {
    // Use result var
}

我想在C ++中复制这种测试和拆包行为,同时在使用时保持代码尽可能的干净。例如,显而易见的简单解决方案(至少对我来说)是:

if (auto result = calculateOptional()) {
    MyType result_unwrapped = *result;
    // Use result_unwrapped var
}

但是您必须解开if内部,或在任何地方使用*result,这与Swift无关。

到目前为止,我真正能真正接近Swift外观的唯一解决方案是:

template<typename T> bool optionalTestUnwrap(std::optional<T> opt, T& value) {
    if (!opt.has_value()) { return false; }
    value = *opt;
    return true;
}

#define ifopt(var, opt) if (typename decltype((opt))::value_type (var); optionalTestUnwrap((opt), (var)))

ifopt (result, calculateOptional()) {
    // Use result var
}

...但是我也不是喜欢使用宏来替换普通的if语句。

1
投票

个人,我会做:

0
投票

您在ifopt宏中所做的事情实际上是将if语句限制为never

0
投票

您可以将可选内容包装在自己的类型中,并隐式转换为该类型并显式转换为bool。抱歉,到目前为止,我尚未对此进行测试,但我认为它应该可以工作。