File Coverage

src/panda/excepted.h
Criterion Covered Total %
statement 14 26 53.8
branch 4 14 28.5
condition n/a
subroutine n/a
pod n/a
total 18 40 45.0


line stmt bran cond sub pod time code
1             #pragma once
2             #include "expected.h"
3              
4             namespace panda {
5              
6             namespace {
7             template
8 0           inline typename std::enable_if::type>::value, void>::type exthrow (E&& e) {
9 0           throw bad_expected_access::type>(std::forward(e));
10             }
11              
12             template
13             inline typename std::enable_if::type>::value, void>::type exthrow (E&& e) {
14             throw std::forward(e);
15             }
16             }
17              
18             template
19             struct excepted {
20             using value_type = T;
21             using error_type = E;
22             using unexpected_type = unexpected;
23              
24             template ::value>::type>
25 1           excepted () {
26 1           _has_val = true;
27 1 50         ::new (&_val) T();
28 1           }
29              
30 1           excepted (const excepted& ex) {
31 1 50         if (ex._has_val) construct_val(ex._val);
32             else {
33 0           construct_err(ex._err);
34 0           ex._checked = true;
35             }
36 1           }
37              
38             excepted (excepted&& ex) {
39             if (ex._has_val) construct_val(std::move(ex._val));
40             else {
41             construct_err(std::move(ex._err));
42             ex._checked = true;
43             }
44             }
45              
46             template
47             explicit excepted (const excepted& ex) {
48             if (ex._has_val) construct_val(ex._val);
49             else {
50             construct_err(ex._err);
51             ex._checked = true;
52             }
53             }
54              
55             template
56             explicit excepted (excepted&& ex) {
57             if (ex._has_val) construct_val(std::move(ex._val));
58             else {
59             construct_err(std::move(ex._err));
60             ex._checked = true;
61             }
62             }
63              
64             template ::value>::type>
65             excepted (T2&& v) {
66             construct_val(std::forward(v));
67             }
68              
69             template
70             excepted (const unexpected& uex) {
71             construct_err(uex.value());
72             }
73              
74             template
75             excepted (unexpected&& uex) {
76             construct_err(std::move(uex.value()));
77             }
78              
79 2           ~excepted () noexcept(false) {
80 2 50         if (_has_val) _val.~T();
81 0 0         else if (_checked) _err.~E();
82             else {
83 0           auto tmp = std::move(_err);
84             _err.~E();
85 0 0         exthrow(std::move(tmp));
86             }
87 2           }
88              
89             excepted& operator= (const excepted& ex) {
90             if (ex._has_val) set_val(ex._val);
91             else {
92             set_err(ex._err);
93             ex._checked = true;
94             }
95             return *this;
96             }
97              
98             excepted& operator= (excepted&& ex) {
99             if (ex._has_val) set_val(std::move(ex._val));
100             else {
101             set_err(std::move(ex._err));
102             ex._checked = true;
103             }
104             return *this;
105             }
106              
107             template
108             excepted& operator= (T2&& v) {
109             set_val(std::forward(v));
110             }
111              
112             template
113             excepted& operator= (const unexpected& uex) {
114             set_err(uex.value());
115             }
116              
117             template
118             excepted& operator= (unexpected&& uex) {
119             set_err(std::move(uex.value()));
120             }
121              
122             constexpr bool has_value () const noexcept { _checked = true; return _has_val; }
123             constexpr explicit operator bool () const noexcept { _checked = true; return _has_val; }
124              
125             const T& value () const & { if (!has_value()) exthrow(_err); return _val; }
126             T& value () & { if (!has_value()) exthrow(_err); return _val; }
127             const T&& value () const && { if (!has_value()) exthrow(_err); return std::move(_val); }
128             T&& value () && { if (!has_value()) exthrow(_err); return std::move(_val); }
129              
130             template constexpr T value_or (T2&& v) const & { _checked = true; return bool(*this) ? this->_val : static_cast(std::forward(v)); }
131             template constexpr T value_or (T2&& v) && { _checked = true; return bool(*this) ? std::move(this->_val) : static_cast(std::forward(v)); }
132              
133             const E& error () const & { return _err; }
134             E& error () & { return _err; }
135             const E&& error () const && { return std::move(_err); }
136             E&& error () && { return std::move(_err); }
137              
138             const T* operator-> () const { return &_val; }
139             T* operator-> () { return &_val; }
140              
141             const T& operator* () const & { return _val; }
142             T& operator* () & { return _val; }
143             const T&& operator* () const && { return std::move(_val); }
144             T&& operator* () && { return std::move(_val); }
145              
146             template
147             void emplace (Args&&... args) {
148             if (_has_val) _val = T(std::forward(args)...);
149             else {
150             auto tmp = std::move(_err);
151             _err.~E();
152             try {
153             ::new (&_val) T(std::forward(args)...);
154             _has_val = true;
155             } catch (...) {
156             new (&_err) E(std::move(tmp));
157             throw;
158             }
159             }
160             }
161              
162             template
163             auto and_then (F&& f) const & -> decltype(f(std::declval())) {
164             _checked = true;
165             if (!_has_val) return unexpected_type(_err);
166             return f(_val);
167             }
168              
169             template
170             auto and_then (F&& f) const && -> decltype(f(std::declval())) {
171             _checked = true;
172             if (!_has_val) return unexpected_type(std::move(_err));
173             return f(std::move(_val));
174             }
175              
176             template
177             auto or_else (F&& f) const & -> decltype(f(std::declval())) {
178             _checked = true;
179             if (_has_val) return *this;
180             return f(_err);
181             }
182              
183             template
184             auto or_else (F&& f) const && -> decltype(f(std::declval())) {
185             _checked = true;
186             if (_has_val) return std::move(*this);
187             return f(std::move(_err));
188             }
189              
190             template
191             auto map (F&& f) const & -> excepted())), E> {
192             _checked = true;
193             if (!_has_val) return unexpected_type(_err);
194             return f(_val);
195             }
196              
197             template
198             auto map (F&& f) const && -> excepted())), E> {
199             _checked = true;
200             if (!_has_val) return unexpected_type(std::move(_err));
201             return f(std::move(_val));
202             }
203              
204             template
205             auto map_error (F&& f) const & -> excepted()))> {
206             _checked = true;
207             if (_has_val) return _val;
208             return make_unexpected(f(_err));
209             }
210              
211             template
212             auto map_error (F&& f) const && -> excepted()))> {
213             _checked = true;
214             if (_has_val) return std::move(_val);
215             return make_unexpected(f(std::move(_err)));
216             }
217              
218             template
219             void swap (excepted& ex) {
220             if (_has_val) {
221             if (ex._has_val) std::swap(_val, ex._val);
222             else {
223             auto tmp = std::move(ex._err);
224             ex._err.~E();
225             ex._has_val = true;
226             new (&ex._val) T(std::move(_val));
227              
228             _val.~T();
229             _has_val = false;
230             new (&_err) E(std::move(tmp));
231             _checked = ex._checked;
232             }
233             }
234             else {
235             if (ex._has_val) ex.swap(*this);
236             else std::swap(_err, ex._err);
237             }
238             }
239              
240             void nevermind () const { _checked = true; }
241              
242             private:
243             template friend struct excepted;
244              
245             template
246 1           void construct_val (T2&& v) {
247 1           _has_val = true;
248 1 50         ::new (&_val) T(std::forward(v));
249 1           }
250              
251             template
252 0           void construct_err (E2&& e) {
253 0           _has_val = false;
254 0           _checked = false;
255 0 0         ::new (&_err) E(std::forward(e));
256 0           }
257              
258             template
259             void set_val (T2&& v) {
260             if (_has_val) _val = std::forward(v);
261             else {
262             _err.~E();
263             _has_val = true;
264             ::new (&_val) T(std::forward(v));
265             }
266             }
267              
268             template
269             void set_err (E2&& e) {
270             _checked = false;
271             if (_has_val) {
272             _val.~T();
273             _has_val = false;
274             ::new (&_err) E(std::forward(e));
275             }
276             else _err = std::forward(e);
277             }
278              
279             union {
280             T _val;
281             E _err;
282             };
283             bool _has_val;
284             mutable bool _checked;
285             };
286              
287              
288             template
289             struct excepted {
290             using value_type = void;
291             using error_type = E;
292             using unexpected_type = unexpected;
293              
294             excepted () { _has_val = true; }
295              
296             excepted (const excepted& ex) {
297             if (ex._has_val) _has_val = true;
298             else {
299             construct_err(ex._err);
300             ex._checked = true;
301             }
302             }
303              
304             excepted (excepted&& ex) {
305             if (ex._has_val) _has_val = true;
306             else {
307             construct_err(std::move(ex._err));
308             ex._checked = true;
309             }
310             }
311              
312             template
313             explicit excepted (const excepted& ex) {
314             if (ex._has_val) _has_val = true;
315             else {
316             construct_err(ex._err);
317             ex._checked = true;
318             }
319             }
320              
321             template
322             explicit excepted (excepted&& ex) {
323             if (ex._has_val) _has_val = true;
324             else {
325             construct_err(std::move(ex._err));
326             ex._checked = true;
327             }
328             }
329              
330             template
331             excepted (const unexpected& uex) {
332             construct_err(uex.value());
333             }
334              
335             template
336             excepted (unexpected&& uex) {
337             construct_err(std::move(uex.value()));
338             }
339              
340             ~excepted () noexcept(false) {
341             if (_has_val) return;
342             else if (_checked) _err.~E();
343             else {
344             auto tmp = std::move(_err);
345             _err.~E();
346             exthrow(std::move(tmp));
347             }
348             }
349              
350             excepted& operator= (const excepted& ex) {
351             if (ex._has_val) set_val();
352             else {
353             set_err(ex._err);
354             ex._checked = true;
355             }
356             return *this;
357             }
358              
359             excepted& operator= (excepted&& ex) {
360             if (ex._has_val) set_val();
361             else {
362             set_err(std::move(ex._err));
363             ex._checked = true;
364             }
365             return *this;
366             }
367              
368             template
369             excepted& operator= (const unexpected& uex) {
370             set_err(uex.value());
371             }
372              
373             template
374             excepted& operator= (unexpected&& uex) {
375             set_err(std::move(uex.value()));
376             }
377              
378             constexpr bool has_value () const noexcept { _checked = true; return _has_val; }
379             constexpr explicit operator bool () const noexcept { _checked = true; return _has_val; }
380              
381             const E& error () const & { return _err; }
382             E& error () & { return _err; }
383             const E&& error () const && { return std::move(_err); }
384             E&& error () && { return std::move(_err); }
385              
386             template
387             auto and_then (F&& f) const & -> decltype(f()) {
388             _checked = true;
389             if (!_has_val) return unexpected_type(_err);
390             return f();
391             }
392              
393             template
394             auto and_then (F&& f) const && -> decltype(f()) {
395             _checked = true;
396             if (!_has_val) return unexpected_type(std::move(_err));
397             return f();
398             }
399              
400             template
401             auto or_else (F&& f) const & -> decltype(f(std::declval())) {
402             _checked = true;
403             if (_has_val) return *this;
404             return f(_err);
405             }
406              
407             template
408             auto or_else (F&& f) const && -> decltype(f(std::declval())) {
409             _checked = true;
410             if (_has_val) return std::move(*this);
411             return f(std::move(_err));
412             }
413              
414             template
415             auto map (F&& f) const & -> excepted {
416             _checked = true;
417             if (!_has_val) return unexpected_type(_err);
418             return f();
419             }
420              
421             template
422             auto map (F&& f) const && -> excepted {
423             _checked = true;
424             if (!_has_val) return unexpected_type(std::move(_err));
425             return f();
426             }
427              
428             template
429             auto map_error (F&& f) const & -> excepted()))> {
430             _checked = true;
431             if (_has_val) return {};
432             return make_unexpected(f(_err));
433             }
434              
435             template
436             auto map_error (F&& f) const && -> excepted()))> {
437             _checked = true;
438             if (_has_val) return {};
439             return make_unexpected(f(std::move(_err)));
440             }
441              
442             template
443             void swap (excepted& ex) {
444             if (_has_val) {
445             if (!ex._has_val) {
446             new (&_err) E(std::move(ex._err));
447             ex._err.~E();
448             std::swap(_has_val, ex._has_val);
449             _checked = ex._checked;
450             }
451             }
452             else {
453             if (ex._has_val) ex.swap(*this);
454             else std::swap(_err, ex._err);
455             }
456             }
457              
458             void nevermind () const { _checked = true; }
459              
460             private:
461             template friend struct excepted;
462              
463             template
464             void construct_err (E2&& e) {
465             _has_val = false;
466             _checked = false;
467             ::new (&_err) E(std::forward(e));
468             }
469              
470             void set_val () {
471             if (_has_val) return;
472             _err.~E();
473             _has_val = true;
474             }
475              
476             template
477             void set_err (E2&& e) {
478             _checked = false;
479             if (_has_val) {
480             _has_val = false;
481             ::new (&_err) E(std::forward(e));
482             }
483             else _err = std::forward(e);
484             }
485              
486             union {
487             E _err;
488             };
489             bool _has_val;
490             mutable bool _checked;
491             };
492              
493             template
494             bool operator== (const excepted& lhs, const excepted& rhs) {
495             if (lhs.has_value() != rhs.has_value()) return false;
496             return lhs.has_value() ? *lhs == *rhs : lhs.error() == rhs.error();
497             }
498              
499             template
500             bool operator== (const excepted& lhs, const excepted& rhs) {
501             if (lhs.has_value() != rhs.has_value()) return false;
502             return lhs.has_value() ? true : lhs.error() == rhs.error();
503             }
504              
505             template
506             bool operator!= (const excepted& lhs, const excepted& rhs) { return !operator==(lhs, rhs); }
507              
508             template
509             typename std::enable_if::value, bool>::type
510             operator== (const excepted& x, const T2& v) { return x.has_value() ? *x == v : false; }
511              
512             template
513             bool operator== (const T2& v, const excepted& x) { return x == v; }
514              
515             template
516             bool operator!= (const excepted& x, const T2& v) { return !(x == v); }
517              
518             template
519             bool operator!= (const T2& v, const excepted& x) { return !(x == v); }
520              
521             template
522             bool operator== (const excepted& x, const unexpected& e) { return x.has_value() ? false : x.error() == e.value(); }
523             template
524             bool operator== (const unexpected& e, const excepted& x) { return x == e; }
525             template
526             bool operator!= (const excepted& x, const unexpected& e) { return !(x == e); }
527             template
528             bool operator!= (const unexpected& e, const excepted& x) { return !(x == e); }
529              
530             template
531             void swap (excepted& lhs, excepted& rhs) { lhs.swap(rhs); }
532              
533             }