Support Class Library
A set of tools providing classes and utility
Result.h
Go to the documentation of this file.
1 #pragma once
2 #include <scl/utils/Either.h>
5 #include <functional>
6 
7 namespace scl{
8  namespace utils{
9  namespace details{
13  struct result_value final{};
14  struct result_error final{};
15  }
16 
17  template <class Value, class Error = Placeholder>
18  class Result{
19  public:
20  using value_type = Value;
21  using error_type = Error;
23 
24  protected:
26 
27  Result() = delete;
28 
29  template <class T>
30  Result(details::result_value, T&& value) : alt{impl_type::Left(std::forward<T>(value))} {
31  }
32 
33  template <class E>
34  Result(details::result_error, E&& err) : alt{impl_type::Right(std::forward<E>(err))} {
35  }
36 
37  public:
38  template <class T>
39  static Result Ok(T&& value){
40  return Result{
42  std::forward<T>(value)
43  };
44  }
45 
46  template <class T>
47  static Result ok(T&& value){
48  return Ok(std::forward<T>(value));
49  }
50 
51  template <class... Args>
52  static Result emplaceOk(Args&&... args){
53  return Ok(value_type{
54  std::forward<Args>(args)...
55  });
56  }
57 
58  template <class E>
59  static Result Err(E&& err){
60  return Result{
62  std::forward<E>(err)
63  };
64  }
65 
66  template <class E>
67  static Result err(E&& error){
68  return Err(std::forward<E>(error));
69  }
70 
71  template <class... Args>
72  static Result emplaceErr(Args&&... args){
73  return Err(error_type{
74  std::forward<Args>(args)...
75  });
76  }
77 
78  public:
79  bool isOk() const{
80  return this->alt.hasLeft();
81  }
82 
83  bool isErr() const{
84  return !this->isOk();
85  }
86 
87  const value_type& value() const{
88  try {
89  return this->alt.getLeft();
92  }
93  }
94 
95  const value_type& get() const{
96  return this->value();
97  }
98 
99  const error_type& error() const{
100  try{
101  return this->alt.getRight();
104  }
105  }
106 
107  operator bool() const{
108  return this->isOk();
109  }
110 
111  operator const value_type&() const{
112  return this->value();
113  }
114 
115  const value_type& operator*() const{
116  return this->get();
117  }
118 
120  return &(this->get());
121  }
122 
123  public:
125  if(this->isOk())
126  return this->value();
127  return none;
128  }
129 
131  return this->toOptional();
132  }
133 
134  template <class T = value_type>
135  Result<T, error_type> map(std::function<T(const value_type&)> mapper) const{
136  return this->isOk()
137  ? Result<T, error_type>::Ok(mapper(this->value()))
139  }
140 
141  template <class T = value_type>
142  Result<T, error_type> then(std::function<T(const value_type&)> mapper) const{
143  return this->map(mapper);
144  }
145 
146  template <class E = error_type>
147  Result<value_type, E> mapError(std::function<E(const error_type&)> mapper) const{
148  return this->isOk()
149  ? Result<value_type, E>::Ok(this->value())
150  : Result<value_type, E>::Err(mapper(this->error()));
151  }
152 
153  template <class T = value_type, class E = error_type>
154  Result<T, E> mapBoth(std::function<T(const value_type&)> valueMapper, std::function<E(const error_type&)> errorMapper) const{
155  //return this->map(valueMapper).mapError(errorMapper);
156  return this->isOk()
157  ? Result<T, E>::Ok(valueMapper(this->value()))
158  : Result<T, E>::Err(errorMapper(this->error()));
159  }
160 
161  template <class T = value_type, class E = error_type>
162  Result<T, E> flatMap(std::function<Result<T, E>(const value_type&)> mapper) const{
163  return this->isOk()
164  ? mapper(this->value())
165  : Result<T, E>::emplaceErr(this->error());
166  }
167 
168  template <class T = value_type, class E = error_type>
169  Result<T, E> andThen(std::function<Result<T, E>(const value_type&)> mapper) const{
170  return this->flatMap(mapper);
171  }
172 
173  template <class T = value_type, class E = error_type>
174  Result<T, E> flatMapError(std::function<Result<T, E>(const error_type&)> mapper) const{
175  return this->isOk()
176  ? Result<T, E>::emplaceOk(this->value())
177  : mapper(this->error());
178  }
179 
180  public:
181  const value_type& okOr(const value_type& value) const{
182  return this->isOk()
183  ? this->value()
184  : value;
185  }
186 
187  const value_type& okOr(std::function<const value_type&()> factory) const{
188  return this->isOk()
189  ? this->value()
190  : factory();
191  }
192 
193  const error_type& errOr(const error_type& error) const{
194  return this->isOk()
195  ? error
196  : this->error();
197  }
198 
199  const error_type& errOr(std::function<const error_type&()> factory) const{
200  return this->isOk()
201  ? factory()
202  : this->error();
203  }
204 
205  template <class E>
206  const value_type& okOrThrow(E ex) const{
207  if(!this->isOk())
208  throw ex;
209  return this->value();
210  }
211  };
212 
213  template <class T>
215  try{
216  auto value = f();
218  }catch(...){
220  std::current_exception()
221  );
222  }
223  }
224  }
225 }
decltype(std::cerr) & error(T &&value)
Output a value on stderr and terminate with a line break.
Definition: basic.h:25
Result< T, error_type > map(std::function< T(const value_type &)> mapper) const
Definition: Result.h:135
static Result err(E &&error)
Definition: Result.h:67
static InvalidResultAccess okWhenErr()
Helper function that creates an InvalidResultAccess when trying to access Ok when Err...
Global namespace of the SCL.
Definition: alias.hpp:3
static Result emplaceErr(Args &&... args)
Definition: Result.h:72
const value_type & okOr(const value_type &value) const
Definition: Result.h:181
const error_type & errOr(std::function< const error_type &()> factory) const
Definition: Result.h:199
Optional< value_type > toOptional() const
Definition: Result.h:124
#define realConst(type)
Definition: macros.h:3
bool hasLeft() const
Determines whether or not LHS is the active alternative.
Definition: Either.h:294
Result< T, E > mapBoth(std::function< T(const value_type &)> valueMapper, std::function< E(const error_type &)> errorMapper) const
Definition: Result.h:154
const value_type & okOrThrow(E ex) const
Definition: Result.h:206
Result< T, E > flatMapError(std::function< Result< T, E >(const error_type &)> mapper) const
Definition: Result.h:174
Result< value_type, E > mapError(std::function< E(const error_type &)> mapper) const
Definition: Result.h:147
const value_type & operator*() const
Definition: Result.h:115
static InvalidResultAccess errWhenOk()
Helper function that creates an InvalidResultAccess when trying to access Err when Ok is active...
bool isErr() const
Definition: Result.h:83
Result(details::result_value, T &&value)
Definition: Result.h:30
bool isOk() const
Definition: Result.h:79
const error_type & errOr(const error_type &error) const
Definition: Result.h:193
const error_type & error() const
Definition: Result.h:99
Optional< value_type > asOptional() const
Definition: Result.h:130
Result< T, E > andThen(std::function< Result< T, E >(const value_type &)> mapper) const
Definition: Result.h:169
constexpr None none
A constant global variable of type None.
Definition: Optional.h:41
const value_type *const operator->() const
Definition: Result.h:119
const Rhs & getRight() const
Attempts to get the RHS value.
Definition: Either.h:319
static Result Err(E &&err)
Definition: Result.h:59
const value_type & okOr(std::function< const value_type &()> factory) const
Definition: Result.h:187
static Result emplaceOk(Args &&... args)
Definition: Result.h:52
Result< T, std::exception_ptr > wrapInResult(std::function< T()> f)
Definition: Result.h:214
const value_type & value() const
Definition: Result.h:87
static Result ok(T &&value)
Definition: Result.h:47
impl_type alt
Definition: Result.h:25
details::map_toolbox< T, U > map(F &&mapper)
Map a stream.
Definition: map.h:97
Exception class used when attempting to access the wrong type stored in an scl::utils::Either.
Error error_type
Definition: Result.h:21
Result(details::result_error, E &&err)
Definition: Result.h:34
scl::utils::Result< T, E > err(const E &error)
Definition: result.h:15
Value value_type
Definition: Result.h:20
Result< T, E > flatMap(std::function< Result< T, E >(const value_type &)> mapper) const
Definition: Result.h:162
const Lhs & getLeft() const
Attempts to get the LHS value.
Definition: Either.h:307
Result< T, error_type > then(std::function< T(const value_type &)> mapper) const
Definition: Result.h:142
static Result Ok(T &&value)
Definition: Result.h:39