У меня гораздо более простой набор требований, и мне не нужно много вариантов машины.Я также не хочу зависеть от наддува, если смогу помочь.
Мне нужно хранить любой произвольный тип, известный во время компиляции (это может быть void
).Он может быть либо перемещаемым, либо копируемым, и, если любой из этих бросков, допустимо, чтобы содержащееся значение было неопределенным.
Вместо этого значения оно также может содержать либо ::std::exception_ptr
, либо ::std::error_code
.
::boost::variant<T, ::std::exception_ptr, ::std::error_code>
будет работать, если T
разрешено аннулировать.За исключением того, что ::boost::variant
предоставляет «никогда не пустую гарантию», которая мне на самом деле не нужна в этом случае.И, если я понимаю, как это работает правильно, это не очень совместимо с типами, которые можно перемещать, но не копировать.
Сейчас я пишу много дублированного кода, который мне не нужно было бы писатьобрабатывать каждый из этих типов отдельно.Я также храню копию объекта каждого типа и значений флагов, говоря, что является актуальным.Наконец, 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_;
};