#include <variant>
#include <exception>
#include <type_traits>
#include <cassert>
template <typename T>
struct Promise {
std::variant<
std::monostate,
std::conditional_t<std::is_void_v<T>, std::monostate, T>,
std::exception_ptr
> result_;
T await_resume() const {
assert(result_.index() > 0);
#if 1
// old code that I want to optimise
if (result_.index() == 2) {
std::rethrow_exception(std::get<2>(result_));
}
if constexpr (!std::is_void_v<T>) {
return std::get<1>(result_);
}
#else
// new code, won't compile
return std::visit([](auto&& arg) {
using TT = std::decay_t<decltype(arg)>;
if constexpr (!std::is_same_v<TT, std::exception_ptr>) {
std::rethrow_exception(arg);
} else if constexpr (!std::is_void_v<T>) {
return arg;
}
});
#endif
}
};
template int Promise<int>::await_resume() const;
template std::exception_ptr Promise<std::exception_ptr>::await_resume() const;
template void Promise<void>::await_resume() const;
Promise::await_resume是一个简单的函数,它执行以下操作:
- 如果变体的值为
std::exception_ptr
,则重新抛出异常。 - 如果变体的值是
T
(而 T 由用户设置,也可能是 std::exception_ptr),则将其返回。如果 T 的类型为 void,则什么也不做。
最初我使用.index()
check 和std::get
. 它可以工作,但是会在std::get
内部产生额外的检查以及std::__1::__throw_bad_variant_access()
不会发生的事情:https ://godbolt.org/z/YnjxDy
我想根据cppreference使用 std::visit 优化代码,但无法编译。
另一个问题是,当 T 的类型是 std::exception_ptr 时,我怎么知道我是否应该抛出它?