]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/leaf/result.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / leaf / result.hpp
1 #ifndef BOOST_LEAF_RESULT_HPP_INCLUDED
2 #define BOOST_LEAF_RESULT_HPP_INCLUDED
3
4 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
5
6 // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
9 #ifndef BOOST_LEAF_ENABLE_WARNINGS
10 # if defined(__clang__)
11 # pragma clang system_header
12 # elif (__GNUC__*100+__GNUC_MINOR__>301)
13 # pragma GCC system_header
14 # elif defined(_MSC_VER)
15 # pragma warning(push,1)
16 # endif
17 #endif
18
19 #include <boost/leaf/error.hpp>
20 #include <climits>
21
22 namespace boost { namespace leaf {
23
24 class bad_result:
25 public std::exception,
26 public error_id
27 {
28 char const * what() const noexcept final override
29 {
30 return "boost::leaf::bad_result";
31 }
32
33 public:
34
35 explicit bad_result( error_id id ) noexcept:
36 error_id(id)
37 {
38 BOOST_LEAF_ASSERT(value());
39 }
40 };
41
42 ////////////////////////////////////////
43
44 namespace leaf_detail
45 {
46 template <class T>
47 struct stored
48 {
49 using type = T;
50 using value_type = T;
51 using value_type_const = T const;
52 using value_cref = T const &;
53 using value_ref = T &;
54 using value_rv_cref = T const &&;
55 using value_rv_ref = T &&;
56 };
57
58 template <class T>
59 struct stored<T &>
60 {
61 using type = std::reference_wrapper<T>;
62 using value_type_const = T;
63 using value_type = T;
64 using value_ref = T &;
65 using value_cref = T &;
66 using value_rv_ref = T &;
67 using value_rv_cref = T &;
68 };
69
70 class result_discriminant
71 {
72 unsigned state_;
73
74 public:
75
76 enum kind_t
77 {
78 no_error = 0,
79 err_id = 1,
80 ctx_ptr = 2,
81 val = 3
82 };
83
84 explicit result_discriminant( error_id id ) noexcept:
85 state_(id.value())
86 {
87 BOOST_LEAF_ASSERT(state_==0 || (state_&3)==1);
88 }
89
90 struct kind_val { };
91 explicit result_discriminant( kind_val ) noexcept:
92 state_(val)
93 {
94 }
95
96 struct kind_ctx_ptr { };
97 explicit result_discriminant( kind_ctx_ptr ) noexcept:
98 state_(ctx_ptr)
99 {
100 }
101
102 kind_t kind() const noexcept
103 {
104 return kind_t(state_&3);
105 }
106
107 error_id get_error_id() const noexcept
108 {
109 BOOST_LEAF_ASSERT(kind()==no_error || kind()==err_id);
110 return make_error_id(state_);
111 }
112 };
113 }
114
115 ////////////////////////////////////////
116
117 template <class T>
118 class result
119 {
120 template <class U>
121 friend class result;
122
123 using result_discriminant = leaf_detail::result_discriminant;
124
125 struct error_result
126 {
127 error_result( error_result && ) = default;
128 error_result( error_result const & ) = delete;
129 error_result & operator=( error_result const & ) = delete;
130
131 result & r_;
132
133 error_result( result & r ) noexcept:
134 r_(r)
135 {
136 }
137
138 template <class U>
139 operator result<U>() noexcept
140 {
141 switch(r_.what_.kind())
142 {
143 case result_discriminant::val:
144 return result<U>(error_id());
145 case result_discriminant::ctx_ptr:
146 return result<U>(std::move(r_.ctx_));
147 default:
148 return result<U>(std::move(r_.what_));
149 }
150 }
151
152 operator error_id() noexcept
153 {
154 switch(r_.what_.kind())
155 {
156 case result_discriminant::val:
157 return error_id();
158 case result_discriminant::ctx_ptr:
159 {
160 error_id captured_id = r_.ctx_->propagate_captured_errors();
161 leaf_detail::id_factory<>::current_id = captured_id.value();
162 return captured_id;
163 }
164 default:
165 return r_.what_.get_error_id();
166 }
167 }
168 };
169
170 using stored_type = typename leaf_detail::stored<T>::type;
171 using value_type = typename leaf_detail::stored<T>::value_type;
172 using value_type_const = typename leaf_detail::stored<T>::value_type_const;
173 using value_ref = typename leaf_detail::stored<T>::value_ref;
174 using value_cref = typename leaf_detail::stored<T>::value_cref;
175 using value_rv_ref = typename leaf_detail::stored<T>::value_rv_ref;
176 using value_rv_cref = typename leaf_detail::stored<T>::value_rv_cref;
177
178 union
179 {
180 stored_type stored_;
181 context_ptr ctx_;
182 };
183
184 result_discriminant what_;
185
186 void destroy() const noexcept
187 {
188 switch(this->what_.kind())
189 {
190 case result_discriminant::val:
191 stored_.~stored_type();
192 break;
193 case result_discriminant::ctx_ptr:
194 BOOST_LEAF_ASSERT(!ctx_ || ctx_->captured_id_);
195 ctx_.~context_ptr();
196 default:
197 break;
198 }
199 }
200
201 template <class U>
202 result_discriminant move_from( result<U> && x ) noexcept
203 {
204 auto x_what = x.what_;
205 switch(x_what.kind())
206 {
207 case result_discriminant::val:
208 (void) new(&stored_) stored_type(std::move(x.stored_));
209 break;
210 case result_discriminant::ctx_ptr:
211 BOOST_LEAF_ASSERT(!x.ctx_ || x.ctx_->captured_id_);
212 (void) new(&ctx_) context_ptr(std::move(x.ctx_));
213 default:
214 break;
215 }
216 return x_what;
217 }
218
219 result( result_discriminant && what ) noexcept:
220 what_(std::move(what))
221 {
222 BOOST_LEAF_ASSERT(what_.kind()==result_discriminant::err_id || what_.kind()==result_discriminant::no_error);
223 }
224
225 error_id get_error_id() const noexcept
226 {
227 BOOST_LEAF_ASSERT(what_.kind()!=result_discriminant::val);
228 return what_.kind()==result_discriminant::ctx_ptr ? ctx_->captured_id_ : what_.get_error_id();
229 }
230
231 static int init_T_with_U( T && );
232
233 protected:
234
235 void enforce_value_state() const
236 {
237 if( what_.kind() != result_discriminant::val )
238 ::boost::leaf::throw_exception(bad_result(get_error_id()));
239 }
240
241 public:
242
243 result( result && x ) noexcept:
244 what_(move_from(std::move(x)))
245 {
246 }
247
248 template <class U>
249 result( result<U> && x ) noexcept:
250 what_(move_from(std::move(x)))
251
252 {
253 }
254
255 result():
256 stored_(stored_type()),
257 what_(result_discriminant::kind_val{})
258 {
259 }
260
261 result( value_type && v ) noexcept:
262 stored_(std::forward<value_type>(v)),
263 what_(result_discriminant::kind_val{})
264 {
265 }
266
267 result( value_type const & v ):
268 stored_(v),
269 what_(result_discriminant::kind_val{})
270 {
271 }
272
273 result( error_id err ) noexcept:
274 what_(err)
275 {
276 }
277
278 // SFINAE: T can be initialized with a U, e.g. result<std::string>("literal").
279 // Not using is_constructible on purpose, bug with COMPILER=/usr/bin/clang++ CXXSTD=11 clang 3.3.
280 template <class U>
281 result( U && u, decltype(init_T_with_U(std::forward<U>(u))) * = 0 ):
282 stored_(std::forward<U>(u)),
283 what_(result_discriminant::kind_val{})
284 {
285 }
286
287 result( std::error_code const & ec ) noexcept:
288 what_(error_id(ec))
289 {
290 }
291
292 template <class Enum>
293 result( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, int>::type * = 0 ) noexcept:
294 what_(error_id(e))
295 {
296 }
297
298 result( context_ptr && ctx ) noexcept:
299 ctx_(std::move(ctx)),
300 what_(result_discriminant::kind_ctx_ptr{})
301 {
302 }
303
304 ~result() noexcept
305 {
306 destroy();
307 }
308
309 result & operator=( result && x ) noexcept
310 {
311 destroy();
312 what_ = move_from(std::move(x));
313 return *this;
314 }
315
316 template <class U>
317 result & operator=( result<U> && x ) noexcept
318 {
319 destroy();
320 what_ = move_from(std::move(x));
321 return *this;
322 }
323
324 explicit operator bool() const noexcept
325 {
326 return what_.kind() == result_discriminant::val;
327 }
328
329 value_cref value() const &
330 {
331 enforce_value_state();
332 return stored_;
333 }
334
335 value_ref value() &
336 {
337 enforce_value_state();
338 return stored_;
339 }
340
341 value_rv_cref value() const &&
342 {
343 enforce_value_state();
344 return std::move(stored_);
345 }
346
347 value_rv_ref value() &&
348 {
349 enforce_value_state();
350 return std::move(stored_);
351 }
352
353 value_cref operator*() const &
354 {
355 return value();
356 }
357
358 value_ref operator*() &
359 {
360 return value();
361 }
362
363 value_rv_cref operator*() const &&
364 {
365 return value();
366 }
367
368 value_rv_ref operator*() &&
369 {
370 return value();
371 }
372
373 value_type_const * operator->() const
374 {
375 return &value();
376 }
377
378 value_type * operator->()
379 {
380 return &value();
381 }
382
383 error_result error() noexcept
384 {
385 return error_result{*this};
386 }
387
388 template <class... Item>
389 error_id load( Item && ... item ) noexcept
390 {
391 return error_id(error()).load(std::forward<Item>(item)...);
392 }
393 };
394
395 ////////////////////////////////////////
396
397 namespace leaf_detail
398 {
399 struct void_ { };
400 }
401
402 template <>
403 class result<void>:
404 result<leaf_detail::void_>
405 {
406 using result_discriminant = leaf_detail::result_discriminant;
407 using void_ = leaf_detail::void_;
408 using base = result<void_>;
409
410 template <class U>
411 friend class result;
412
413 result( result_discriminant && what ) noexcept:
414 base(std::move(what))
415 {
416 }
417
418 public:
419
420 using value_type = void;
421
422 result( result && x ) noexcept:
423 base(std::move(x))
424 {
425 }
426
427 result() noexcept
428 {
429 }
430
431 result( error_id err ) noexcept:
432 base(err)
433 {
434 }
435
436 result( std::error_code const & ec ) noexcept:
437 base(ec)
438 {
439 }
440
441 template <class Enum>
442 result( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, Enum>::type * = 0 ) noexcept:
443 base(e)
444 {
445 }
446
447 result( context_ptr && ctx ) noexcept:
448 base(std::move(ctx))
449 {
450 }
451
452 ~result() noexcept
453 {
454 }
455
456 void value() const
457 {
458 base::enforce_value_state();
459 }
460
461 using base::operator=;
462 using base::operator bool;
463 using base::get_error_id;
464 using base::error;
465 using base::load;
466 };
467
468 ////////////////////////////////////////
469
470 template <class R>
471 struct is_result_type;
472
473 template <class T>
474 struct is_result_type<result<T>>: std::true_type
475 {
476 };
477
478 } }
479
480 #endif