这是 std::expected 的正确便捷包装吗?

问题描述 投票:0回答:1

如果我正在编写一个返回

std::expected
对象的函数,并可能调用返回
std::expected
对象的其他函数,我发现自己编写这样的代码片段非常常见。

struct Foo {  };
std::expected<Foo, std::string> f();

auto res = f();
if(!res) return std::unexpected { res.error() };
auto val = res.value();
// do something with val

所以我写了一个这样的宏,在成功的情况下“返回”值,在失败的情况下“返回”错误。

#define CHECK(expr)\
({\
auto res = expr;\
if(!res) return std::unexpected { res.error() };\
res.value();\
})

然后我可以这样使用它:

Foo foo = CHECK(f());

我假设内部作用域中变量的生命周期应该与赋值表达式一样长。它是否正确?有什么情况会出错吗?

c++ std std-expected
1个回答
0
投票

使用这个宏,您可以编写如下函数:

std::expected<Qux, std::string> g() {
  Foo foo = CHECK(f());
  Bar bar = CHECK(b(foo));
  return q(bar);
}
  • 无法从此模式推导出返回类型
  • 理解此代码的控制流需要了解(并记住)宏扩展为什么

我认为避免这种模式正是一元方法

std::expected<T,E>::and_then
的目的:

auto g() {
  return f()
      .and_then([](auto foo) { return b(foo); })
      .and_then([](auto bar) { return q(bar); });
}

在这种特殊情况下,它还可以进一步缩短:

auto g() {
  return f()
      .and_then(b)
      .and_then(q);
}

尽管实际上,我想在实际代码中写出 lambda 是更常见的情况。

© www.soinside.com 2019 - 2024. All rights reserved.