Apache Mesos
result.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_RESULT_HPP__
14 #define __STOUT_RESULT_HPP__
15 
16 #include <assert.h>
17 
18 #include <iostream>
19 #include <string>
20 #include <utility>
21 
22 #include <stout/abort.hpp>
23 #include <stout/error.hpp>
24 #include <stout/none.hpp>
25 #include <stout/option.hpp>
26 #include <stout/some.hpp>
27 #include <stout/try.hpp>
28 
29 // This class is equivalent to Try<Option<T>> and can represent only
30 // one of these states at a time:
31 // 1) A value of T.
32 // 2) No value of T.
33 // 3) An error state, with a corresponding error string.
34 // Calling 'isSome' will return true if it stores a value, in which
35 // case calling 'get' will return a constant reference to the T
36 // stored. Calling 'isNone' returns true if no value is stored and
37 // there is no error. Calling 'isError' will return true if it stores
38 // an error, in which case calling 'error' will return the error
39 // string.
40 template <typename T>
41 class Result
42 {
43 public:
44  static Result<T> none()
45  {
46  return Result<T>(None());
47  }
48 
49  static Result<T> some(const T& t)
50  {
51  return Result<T>(t);
52  }
53 
54  static Result<T> error(const std::string& message)
55  {
56  return Result<T>(Error(message));
57  }
58 
59  Result(const T& _t)
60  : data(Some(_t)) {}
61 
62  Result(T&& _t)
63  : data(Some(std::move(_t))) {}
64 
65  template <
66  typename U,
67  typename = typename std::enable_if<
68  std::is_constructible<T, const U&>::value>::type>
69  Result(const U& u)
70  : data(Some(u)) {}
71 
72  Result(const Option<T>& option)
73  : data(option.isSome() ?
74  Try<Option<T>>(Some(option.get())) :
75  Try<Option<T>>(None())) {}
76 
77  Result(const Try<T>& _t)
78  : data(_t.isSome() ?
79  Try<Option<T>>(Some(_t.get())) :
80  Try<Option<T>>(Error(_t.error()))) {}
81 
82  Result(const None& none)
83  : data(none) {}
84 
85  template <typename U>
87  : data(some) {}
88 
89  Result(const Error& error)
90  : data(error) {}
91 
93  : data(error) {}
94 
95 #ifdef __WINDOWS__
96  Result(const WindowsError& error)
97  : data(error) {}
98 #endif // __WINDOWS__
99 
100  // We don't need to implement these because we are leveraging
101  // Try<Option<T>>.
102  Result(const Result<T>& that) = default;
103  Result(Result&& that) = default;
104 
105  ~Result() = default;
106 
107  Result<T>& operator=(const Result<T>& that) = default;
108  Result<T>& operator=(Result<T>&& that) = default;
109 
110  // 'isSome', 'isNone', and 'isError' are mutually exclusive. They
111  // correspond to the underlying unioned state of the Option and Try.
112  bool isSome() const { return data.isSome() && data->isSome(); }
113  bool isNone() const { return data.isSome() && data->isNone(); }
114  bool isError() const { return data.isError(); }
115 
116  T& get() & { return get(*this); }
117  const T& get() const& { return get(*this); }
118  T&& get() && { return get(std::move(*this)); }
119  const T&& get() const&& { return get(std::move(*this)); }
120 
121  const T* operator->() const { return &get(); }
122  T* operator->() { return &get(); }
123 
124  const T& operator*() const& { return get(); }
125  T& operator*() & { return get(); }
126  const T&& operator*() const&& { return std::move(*this).get(); }
127  T&& operator*() && { return std::move(*this).get(); }
128 
129  const std::string& error() const { assert(isError()); return data.error(); }
130 
131 private:
132  // This is made static to decouple us from the `const` qualifier of `this`.
133  template <typename Self>
134  static auto get(Self&& self)
135  -> decltype(**(std::forward<Self>(self).data))
136  {
137  if (!self.isSome()) {
138  std::string errorMessage = "Result::get() but state == ";
139  if (self.isError()) {
140  errorMessage += "ERROR: " + self.data.error();
141  } else if (self.isNone()) {
142  errorMessage += "NONE";
143  }
144  ABORT(errorMessage);
145  }
146  return **(std::forward<Self>(self).data);
147  }
148 
149  // We leverage Try<Option<T>> to avoid dynamic allocation of T. This
150  // means we can take advantage of all the RAII features of 'Try' and
151  // makes the implementation of this class much simpler!
152  Try<Option<T>> data;
153 };
154 
155 #endif // __STOUT_RESULT_HPP__
bool isNone() const
Definition: result.hpp:113
Definition: errorbase.hpp:36
Result(const _Some< U > &some)
Definition: result.hpp:86
Definition: option.hpp:29
#define ABORT(...)
Definition: abort.hpp:40
Result(const Try< T > &_t)
Definition: result.hpp:77
~Result()=default
Definition: check.hpp:33
Result(const U &u)
Definition: result.hpp:69
static Result< T > error(const std::string &message)
Definition: result.hpp:54
Definition: error.hpp:108
Result< T > & operator=(const Result< T > &that)=default
Definition: type_utils.hpp:619
Definition: errorbase.hpp:50
const T * operator->() const
Definition: result.hpp:121
Definition: check.hpp:30
Result(const None &none)
Definition: result.hpp:82
const T & operator*() const &
Definition: result.hpp:124
Result(const T &_t)
Definition: result.hpp:59
Result(const Error &error)
Definition: result.hpp:89
Result(T &&_t)
Definition: result.hpp:62
Definition: some.hpp:33
static Result< T > some(const T &t)
Definition: result.hpp:49
bool isSome() const
Definition: try.hpp:77
static Try error(const E &e)
Definition: try.hpp:43
T * operator->()
Definition: result.hpp:122
_Some< typename std::decay< T >::type > Some(T &&t)
Definition: some.hpp:42
T && operator*()&&
Definition: result.hpp:127
Definition: none.hpp:27
bool isError() const
Definition: try.hpp:78
const T && operator*() const &&
Definition: result.hpp:126
T & get()&
Definition: result.hpp:116
Try< uint32_t > type(const std::string &path)
bool isSome() const
Definition: result.hpp:112
bool isError() const
Definition: result.hpp:114
Result(const ErrnoError &error)
Definition: result.hpp:92
const std::string & error() const
Definition: result.hpp:129
static Result< T > none()
Definition: result.hpp:44
Result(const Option< T > &option)
Definition: result.hpp:72
T & operator*()&
Definition: result.hpp:125