我有一组更简单的要求,不需要太多变体的机制。如果可以的话,我也不想依赖 boost。
我需要存储编译时已知的任意类型(可能是 void
)。它要么是可移动构造的,要么是可复制构造的,如果其中任何一个抛出异常,则允许包含的值未定义。
除了这个值,它还可以包含 ::std::exception_ptr
或 ::std::error_code
.
::boost::variant<T, ::std::exception_ptr, ::std::error_code>
如果 T
会起作用允许无效。除了 ::boost::variant
提供我在这种情况下实际上不需要的“永不空保证”。而且,如果我理解它是如何正确工作的,它与可以移动但不能复制的类型不太兼容。
现在我正在编写大量重复的代码,我不应该编写这些代码来分别处理这些类型中的每一种。我还存储了每种类型的对象的拷贝和标志值,说明哪个是相关的。最后,void
给整个系统 conniptions 并要求我在所有地方编写特化。
有没有更好的办法?
这是我所拥有的一个简化示例。这基本上是一个类,旨在保存要传输到另一个线程的结果,有点像 future :
template <typename ResultType>
class stored_result {
public:
stored_result() : is_val_(false), is_err_(false), is_exception_(false) { }
void set_bad_result(::std::error err) {
is_err_ = true;
error_ = ::std::move(err);
}
void set_bad_result(::std::exception_ptr exception) {
is_exception_ = true;
exception_ = ::std::move(exception);
}
void set_result(ResultType res) {
is_val_ = true;
val_ = ::std::move(res);
}
ResultType result() {
if (is_val_) {
is_val_ = false;
return ::std::move(val_);
} else if (is_exception_) {
is_exception_ = false;
::std::rethrow_exception(::std::move(exception_));
} else if (is_error_) {
is_error_ = false;
throw ::std::system_error(error_);
} else {
throw ::std::runtime_error("Asked for result when there was none.");
}
}
private:
bool is_val_, is_err_, is_exception_;
T val_;
::std::exception_ptr exception_;
::std::error_code error_;
};
最佳答案
如何使用您现在拥有的代码以透明方式处理 void
的示例:
struct empty_type {};
template<typename T>
using Store = typename std::conditional<std::is_void<T>::value, empty_type, T>::type;
template<typename T>
T&&
restore(T&& t)
{
return std::forward<T>(t);
}
void
restore(empty_type)
{}
template <typename ResultType>
class stored_result {
public:
// snipped everything that is left unchanged
template<
typename U = ResultType
, typename std::enable_if<
!std::is_void<U>::value
, int
>::type = 0
>
void set_result(U res) {
is_val_ = true;
val_ = std::move(res);
}
template<
typename U = ResultType
, typename std::enable_if<
std::is_void<U>::value
, int
>::type = 0
>
void set_result() {
is_val_ = true;
}
ResultType result() {
if (is_val_) {
is_val_ = false;
return restore(std::move(val_));
} else if {
// rest as before
}
private:
Store<T> val_;
};
尽管代码未经测试,但可能存在一些问题。
关于c++ - 如何制作简化版的 boost::variant?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9986595/