我有一套更为简单的要求,并且不需要太多的变种机器。如果我能帮助它,我也不想依靠提升。
我需要存储编译时已知的任意类型(可能是void
)。它可以是可构造的,也可以是可构造的,如果其中任何一个抛出,则允许包含的值未定义。
它可能还包含::std::exception_ptr
或::std::error_code
,而不是此值。
::boost::variant<T, ::std::exception_ptr, ::std::error_code>
无效,则 T
会起作用。除了::boost::variant
提供“永不空”的保证&#39;在这种情况下我实际上并不需要。而且,如果我理解它是如何正常工作的,那么它与可以移动但不能复制的类型不太兼容。
现在我写了很多重复的代码,我不应该写这些代码来分别处理这些类型。我还存储了每种类型的对象的副本,并标记了相关的值。最后,void
给出了整个系统的一致性,并要求我在整个地方编写专业化。
有更好的方法吗?
这是我所拥有的简化示例。这基本上是一个类,用于保存结果以传输到另一个线程,有点像未来:
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_;
};
答案 0 :(得分:2)
[编辑:问题已经编辑,在我写完之后添加了示例代码]。
它出现你所追求的是一种从函数返回有效结果(任意类型)的方法,或指示失败的东西。
如果是这样,那么下面的代码就可以很好地解决你的问题,即返回任意类型结果的部分(这个类类似于boost::optional
,而这个类基于Barton和Nackman的{ {1}}类)。
对于错误指示,只需将布尔值替换为错误信息,并将概念性“无”替换为概念性“失败”:
Fallible
答案 1 :(得分:2)
如何使用您现在拥有的代码以透明的方式处理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_;
};
虽然代码未经测试可能会有一些问题。