hyperledger/iroha
Iroha - A simple, decentralized ledger http://iroha.tech
result.hpp
Go to the documentation of this file.
1 
6 #ifndef IROHA_RESULT_HPP
7 #define IROHA_RESULT_HPP
8 
9 #include <ciso646>
10 
11 #include <boost/optional.hpp>
12 #include <boost/variant.hpp>
13 
14 #include "common/visitor.hpp"
15 
16 /*
17  * Result is a type which represents value or an error, and values and errors
18  * are template parametrized. Working with value wrapped in result is done using
19  * match() function, which accepts 2 functions: for value and error cases. No
20  * accessor functions are provided.
21  */
22 
23 namespace iroha {
24  namespace expected {
25 
26  /*
27  * Value and error types can be constructed from any value or error, if
28  * underlying types are constructible. Example:
29  *
30  * @code
31  * Value<std::string> v = Value<const char *>("hello");
32  * @nocode
33  */
34 
35  template <typename T>
36  struct Value {
37  T value;
38  template <typename V>
39  operator Value<V>() {
40  return {value};
41  }
42  };
43 
44  template <>
45  struct Value<void> {};
46 
47  template <typename E>
48  struct Error {
49  E error;
50  template <typename V>
51  operator Error<V>() {
52  return {error};
53  }
54  };
55 
56  template <>
57  struct Error<void> {};
58 
65  template <typename V, typename E>
66  class Result : public boost::variant<Value<V>, Error<E>> {
67  using variant_type = boost::variant<Value<V>, Error<E>>;
68  using variant_type::variant_type; // inherit constructors
69 
70  public:
71  using ValueType = Value<V>;
72  using ErrorType = Error<E>;
73 
83  template <typename ValueMatch, typename ErrorMatch>
84  constexpr auto match(ValueMatch &&value_func, ErrorMatch &&error_func) {
85  return visit_in_place(*this,
86  std::forward<ValueMatch>(value_func),
87  std::forward<ErrorMatch>(error_func));
88  }
89 
93  template <typename ValueMatch, typename ErrorMatch>
94  constexpr auto match(ValueMatch &&value_func,
95  ErrorMatch &&error_func) const {
96  return visit_in_place(*this,
97  std::forward<ValueMatch>(value_func),
98  std::forward<ErrorMatch>(error_func));
99  }
100 
112  template <typename Value>
113  constexpr Result<Value, E> and_res(const Result<Value, E> &new_res) const
114  noexcept {
115  return visit_in_place(
116  *this,
117  [res = new_res](ValueType) { return res; },
118  [](ErrorType err) -> Result<Value, E> { return err; });
119  }
120 
132  template <typename Value>
133  constexpr Result<Value, E> or_res(const Result<Value, E> &new_res) const
134  noexcept {
135  return visit_in_place(
136  *this,
137  [](ValueType val) -> Result<Value, E> { return val; },
138  [res = new_res](ErrorType) { return res; });
139  }
140  };
141 
142  template <typename ResultType>
143  using ValueOf = typename ResultType::ValueType;
144  template <typename ResultType>
145  using ErrorOf = typename ResultType::ErrorType;
146 
153  template <typename Err1, typename Err2, typename V, typename Fn>
154  Result<V, Err1> map_error(const Result<V, Err2> &res, Fn &&map) noexcept {
155  return visit_in_place(res,
156  [](Value<V> val) -> Result<V, Err1> { return val; },
157  [map](Error<Err2> err) -> Result<V, Err1> {
158  return Error<Err1>{map(err.error)};
159  });
160  }
161 
162  // Factory methods for avoiding type specification
163  template <typename T>
164  Value<T> makeValue(T &&value) {
165  return Value<T>{std::forward<T>(value)};
166  }
167 
168  template <typename E>
169  Error<E> makeError(E &&error) {
170  return Error<E>{std::forward<E>(error)};
171  }
172 
180  template <typename T, typename E, typename Transform>
181  constexpr auto operator|(Result<T, E> r, Transform &&f) ->
182  typename std::enable_if<
183  not std::is_same<decltype(f(std::declval<T>())), void>::value,
184  decltype(f(std::declval<T>()))>::type {
185  using return_type = decltype(f(std::declval<T>()));
186  return r.match(
187  [&f](const Value<T> &v) { return f(v.value); },
188  [](const Error<E> &e) { return return_type(makeError(e.error)); });
189  }
190 
197  template <typename T, typename E, typename Procedure>
198  constexpr auto operator|(Result<T, E> r, Procedure f) ->
199  typename std::enable_if<not std::is_same<decltype(f()), void>::value,
200  decltype(f())>::type {
201  using return_type = decltype(f());
202  return r.match(
203  [&f](const Value<T> &v) { return f(); },
204  [](const Error<E> &e) { return return_type(makeError(e.error)); });
205  }
206 
220  template <typename V,
221  typename E,
222  typename VContainer = std::shared_ptr<V>,
223  typename EContainer = std::shared_ptr<E>>
224  using PolymorphicResult = Result<VContainer, EContainer>;
225 
226  } // namespace expected
227 } // namespace iroha
228 #endif // IROHA_RESULT_HPP
auto operator|(T &&t, Transform &&f) -> std::enable_if_t< not std::is_same< decltype(std::forward< Transform >(f)(*std::forward< T >(t))), void >::value, decltype(std::forward< Transform >(f)(*std::forward< T >(t)))>
Definition: bind.hpp:42
Definition: block_query.hpp:16
static const std::regex e("\\bdbname=([^ ]*)")