Commit 88210301 authored by Dominik Charousset's avatar Dominik Charousset

Add serialization code for maybe<T>

parent 296c20de
...@@ -322,7 +322,7 @@ private: ...@@ -322,7 +322,7 @@ private:
template <class V> template <class V>
void assign_value(V&& x) { void assign_value(V&& x) {
using x_type = typename std::decay<V>::type; using x_type = typename std::remove_reference<V>::type;
using fwd_type = using fwd_type =
typename std::conditional< typename std::conditional<
std::is_rvalue_reference<decltype(x)>::value std::is_rvalue_reference<decltype(x)>::value
...@@ -403,6 +403,111 @@ private: ...@@ -403,6 +403,111 @@ private:
}; };
}; };
// Represents a computation performing side effects only and
// optionally return a `std::error_condition`.
template <>
class maybe<void> {
public:
using type = unit_t;
using reference = const type&;
using const_reference = const type&;
using pointer = const type*;
using const_pointer = const type*;
using error_type = caf::error;
maybe() = default;
maybe(const none_t&) {
// nop
}
maybe(error_type err) : error_(std::move(err)) {
// nop
}
template <class E,
class = typename std::enable_if<
std::is_same<
decltype(make_error(std::declval<const E&>())),
error_type
>::value
>::type>
maybe(E error_code) : error_(make_error(error_code)) {
// nop
}
maybe& operator=(const none_t&) {
error_.clear();
return *this;
}
maybe& operator=(error_type err) {
error_ = std::move(err);
return *this;
}
template <class E,
class = typename std::enable_if<
std::is_same<
decltype(make_error(std::declval<const E&>())),
error_type
>::value
>::type>
maybe& operator=(E error_code) {
return *this = make_error(error_code);
}
bool valid() const {
return false;
}
explicit operator bool() const {
return valid();
}
bool operator!() const {
return ! valid();
}
reference get() {
CAF_ASSERT(! "should never be called");
return unit;
}
const_reference get() const {
CAF_ASSERT(! "should never be called");
return unit;
}
reference operator*() {
return get();
}
const_reference operator*() const {
return get();
}
pointer operator->() {
return &get();
}
const_pointer operator->() const {
return &get();
}
bool empty() const {
return ! error();
}
const error_type& error() const {
return error_;
}
private:
error_type error_;
};
/// Allows element-wise access of STL-compatible tuples. /// Allows element-wise access of STL-compatible tuples.
/// @relates maybe /// @relates maybe
template <size_t X, class T> template <size_t X, class T>
...@@ -527,110 +632,45 @@ bool operator!=(const none_t&, const maybe<T>& x) { ...@@ -527,110 +632,45 @@ bool operator!=(const none_t&, const maybe<T>& x) {
return ! x.empty(); return ! x.empty();
} }
// Represents a computation performing side effects only and /// @relates maybe
// optionally return a `std::error_condition`. template <class InOrOut, class T>
template <> typename std::enable_if<InOrOut::is_saving::value>::type
class maybe<void> { serialize(InOrOut& sink, maybe<T>& x, const unsigned int) {
public: uint8_t flag = x.empty() ? 0 : (x.valid() ? 1 : 2);
using type = unit_t; sink & flag;
using reference = const type&; if (x.valid())
using const_reference = const type&; sink & *x;
using pointer = const type*; if (x.invalid()) {
using const_pointer = const type*; auto err = x.error();
using error_type = caf::error; sink & err;
maybe() = default;
maybe(const none_t&) {
// nop
}
maybe(error_type err) : error_(std::move(err)) {
// nop
}
template <class E,
class = typename std::enable_if<
std::is_same<
decltype(make_error(std::declval<const E&>())),
error_type
>::value
>::type>
maybe(E error_code) : error_(make_error(error_code)) {
// nop
}
maybe& operator=(const none_t&) {
error_.clear();
return *this;
}
maybe& operator=(error_type err) {
error_ = std::move(err);
return *this;
}
template <class E,
class = typename std::enable_if<
std::is_same<
decltype(make_error(std::declval<const E&>())),
error_type
>::value
>::type>
maybe& operator=(E error_code) {
return *this = make_error(error_code);
}
bool valid() const {
return false;
}
explicit operator bool() const {
return valid();
}
bool operator!() const {
return ! valid();
}
reference get() {
CAF_ASSERT(! "should never be called");
return unit;
}
const_reference get() const {
CAF_ASSERT(! "should never be called");
return unit;
}
reference operator*() {
return get();
}
const_reference operator*() const {
return get();
}
pointer operator->() {
return &get();
}
const_pointer operator->() const {
return &get();
}
bool empty() const {
return ! error();
} }
}
const error_type& error() const { /// @relates maybe
return error_; template <class InOrOut, class T>
typename std::enable_if<InOrOut::is_loading::value>::type
serialize(InOrOut& source, maybe<T>& x, const unsigned int) {
uint8_t flag;
source & flag;
switch (flag) {
case 1: {
T value;
source & value;
x = std::move(value);
break;
}
case 2: {
error err;
source & err;
x = std::move(err);
break;
}
default:
x = none;
} }
}
private: /// @relates maybe
error_type error_;
};
template <class T> template <class T>
std::string to_string(const maybe<T>& x) { std::string to_string(const maybe<T>& x) {
if (x) if (x)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment