提问人:dw218192 提问时间:10/17/2023 最后编辑:Jarod42dw218192 更新时间:10/17/2023 访问量:124
这是 std::expected 的正确便利包装器吗?
Is this a correct convenience wrapper for std::expected?
问:
如果我正在编写一个返回 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());
我假设内部作用域中变量的生存期应该与赋值表达式一样长。这是正确的吗?有没有可能出错的情况?
答:
6赞
Patrick Roberts
10/17/2023
#1
使用此宏,您可以编写如下函数:
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 将是实际代码中更常见的情况。
编译器资源管理器:https://godbolt.org/z/vovTYfxf4
评论