c++ 这是一个正确的std::expected的便利 Package 器吗?

laik7k3q  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(86)

如果我正在编写一个返回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());

我假设内部作用域中变量的生存期应该和赋值表达式一样长。是这样吗?有没有可能出问题的情况?

uxhixvfz

uxhixvfz1#

有了这个宏,你可以写这样的函数:

std::expected<Qux, std::string> g() {
  Foo foo = CHECK(f());
  Bar bar = CHECK(b(foo));
  return q(bar);
}
  • 返回类型不能从该模式中推导出来
  • 理解这段代码的控制流需要知道(并记住)宏扩展到什么

我认为避免这种模式是monadic方法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);
}

尽管现实地说,我认为写出这些语句在实际代码中是更常见的情况。
浏览器浏览器:https://godbolt.org/z/vovTYfxf4

相关问题