Lumiera  0.pre.03
»edit your freedom«
result.hpp
Go to the documentation of this file.
1 /*
2  RESULT.hpp - intermediary token representing the result of an operation
3 
4  Copyright (C) Lumiera.org
5  2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
46 #ifndef LIB_RESULT_H
47 #define LIB_RESULT_H
48 
49 #include "lib/error.hpp"
50 #include "lib/wrapper.hpp"
51 #include "lib/meta/util.hpp"
52 #include "lib/null-value.hpp"
53 
54 #include <type_traits>
55 #include <exception>
56 #include <utility>
57 
58 
59 
60 namespace lib {
61 
62  namespace error = lumiera::error;
63 
72  template<class FUN, typename...ARGS>
73  inline auto
74  failsafeInvoke (std::exception_ptr& capturedFailure
75  ,FUN&& callable
76  ,ARGS&& ...args) noexcept
77  {
78  using Res = std::invoke_result_t<FUN,ARGS...>;
79  try {
80  capturedFailure = nullptr;
81  if constexpr (std::is_void_v<Res>)
82  std::invoke (std::forward<FUN>(callable), std::forward<ARGS>(args)...);
83  else
84  return std::invoke (std::forward<FUN>(callable), std::forward<ARGS>(args)...);
85  }
86  catch(...)
87  {
88  capturedFailure = std::current_exception();
89  if constexpr (not std::is_void_v<Res>)
90  return lib::NullValue<Res>::get();
91  }
92  }
93 
94 
95 
105  template<typename RES>
106  class Result;
107 
108 
113  template<>
114  class Result<void>
115  {
116  protected:
117  std::exception_ptr failure_;
118 
119  public:
121  Result (bool success =false)
122  : failure_{success? nullptr: std::make_exception_ptr (error::State{"operation failed"})}
123  { }
124 
126  Result (lumiera::Error const& reason)
127  : failure_{std::make_exception_ptr (reason)}
128  { }
129 
131  template<class FUN, typename...ARGS, typename=lib::meta::enable_if<std::is_invocable<FUN,ARGS...>>>
132  Result (FUN&& callable, ARGS&& ...args) noexcept
133  : failure_{}
134  {
135  failsafeInvoke (failure_
136  ,std::forward<FUN> (callable)
137  ,std::forward<ARGS>(args)...);
138  }
139 
140  explicit
141  operator bool() const { return isValid(); }
142  bool isValid() const { return not failure_; }
143 
144  void
145  maybeThrow() const
146  {
147  if (failure_)
148  std::rethrow_exception(failure_);
149  }
150  };
151 
152 
162  template<typename RES>
163  class Result
164  : public Result<void>
165  {
167 
168  public:
170  Result (lumiera::Error const& reason)
171  : Result<void>{reason}
172  { }
173 
175  template< typename=lib::meta::disable_if<std::is_invocable<RES>>>
176  Result (RES&& value)
177  : Result<void>{true}
178  , value_{std::forward<RES> (value)}
179  { }
180 
182  template<class FUN, typename...ARGS, typename=lib::meta::enable_if<std::is_invocable<FUN,ARGS...>>>
183  Result (FUN&& callable, ARGS&& ...args) noexcept
184  : Result<void>{true}
185  , value_{failsafeInvoke (failure_
186  ,std::forward<FUN> (callable)
187  ,std::forward<ARGS>(args)...)}
188  { }
189 
190  // is or is not copyable depending on RES
191 
192 
193  operator RES() const
194  {
195  maybeThrow();
196  return *value_;
197  }
198 
199  template<typename TY =RES>
200  TY
201  get() const
202  {
203  maybeThrow();
204  return static_cast<TY> (*value_);
205  }
206 
207  template<typename O>
208  RES
209  value_or (O&& defaultVal)
210  {
211  return isValid()? *value_ : std::forward<O> (defaultVal);
212  }
213 
214  template<typename MAKE, typename...ARGS>
215  RES
216  or_else (MAKE&& producer, ARGS ...args)
217  {
218  if (isValid())
219  return *value_;
220  else
221  return std::invoke(std::forward<MAKE> (producer), std::forward<ARGS> (args)...);
222  }
223  };
224 
226  template<typename VAL, typename=lib::meta::disable_if<std::is_invocable<VAL>>>
227  Result (VAL&&) -> Result<VAL>;
228 
230  template<typename FUN, typename...ARGS>
231  Result (FUN&&, ARGS&&...) -> Result<std::invoke_result_t<FUN,ARGS...>>;
232 
233 
234 
235 } // namespace lib
236 #endif
The base case is just to capture success or failure, without returning any value result.
Definition: result.hpp:114
Representation of the result of some operation, EITHER a value or a failure.
Definition: result.hpp:106
Result(lumiera::Error const &reason)
mark failed result, with reason given.
Definition: result.hpp:170
Simple and lightweight helpers for metaprogramming and type detection.
Singleton holder for NIL or default value objects.
Definition: null-value.hpp:71
Result(lumiera::Error const &reason)
failed result, with reason given.
Definition: result.hpp:126
Singleton-style holder for NIL or default values.
Implementation namespace for support and library code.
typename enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition: meta/util.hpp:92
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
void maybeThrow(string description="")
Check the lumiera error state and throw a specific exception in case a non-cleared errorflag is detec...
Definition: error.hpp:258
Lumiera error handling (C++ interface).
Result(bool success=false)
mark either failure (default) or success
Definition: result.hpp:121
auto failsafeInvoke(std::exception_ptr &capturedFailure, FUN &&callable, ARGS &&...args) noexcept
Helper to invoke an arbitrary callable in a failsafe way.
Definition: result.hpp:74
Result(FUN &&callable, ARGS &&...args) noexcept
invoke a callable and mark success or failure
Definition: result.hpp:132
Library implementation: smart-pointer variations, wrappers and managing holders.
Interface and Base definition for all Lumiera Exceptions.
Definition: error.hpp:71