source: src/Common/option.h@ eff03a94

new-env
Last change on this file since eff03a94 was 5c14030, checked in by Aaron Moss <a3moss@…>, 7 years ago

Persistent-array environment compiles

  • Property mode set to 100644
File size: 6.5 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// option.h --
8//
9// Author : Aaron B. Moss
10// Created On : Wed Jul 03 15:41:00 2018
11// Last Modified By : Aaron B. Moss
12// Last Modified On : Wed Jul 03 15:41:00 2018
13// Update Count : 1
14//
15
16#pragma once
17
18#include <cassert>
19#include <functional>
20#include <type_traits>
21#include <utility>
22
23using std::move;
24
25/// A class that may or may not hold a value of type T
26/// Similar interface to the C++17 std::optional
27template<typename T>
28class option {
29 typename std::aligned_storage<sizeof(T), alignof(T)>::type storage;
30 bool filled;
31
32 /// gets the underlying value (filled must be true)
33 T& get() { return reinterpret_cast<T&>(storage); }
34 const T& get() const { return reinterpret_cast<const T&>(storage); }
35
36 /// copy-initializes from a value
37 void init( const T& x ) {
38 new(&storage) T(x);
39 filled = true;
40 }
41
42 /// move-initializes from a value
43 void init( T&& x ) {
44 new(&storage) T( move(x) );
45 filled = true;
46 }
47
48 /// destroys the underlying value (must be filled), sets filled to false
49 void destroy() {
50 get().~T();
51 filled = false;
52 }
53
54public:
55
56 option() : filled(false) {}
57 option( const T& x ) { init( x ); }
58 option( T&& x ) { init( move(x) ); }
59 option( const option<T>& o ) : filled(o.filled) { if ( filled ) init( o.get() ); }
60 option( option<T>&& o ) : filled(o.filled) { if ( filled ) init( move(o.get()) ); }
61 option& operator= ( const T& x ) {
62 if ( filled ) { get() = x; } else { init( x ); }
63 return *this;
64 }
65 option& operator= ( T&& x ) {
66 if ( filled ) { get() = move(x); } else { init( move(x) ); }
67 return *this;
68 }
69 option& operator= ( const option<T>& o ) {
70 if ( filled ) {
71 if ( o.filled ) {
72 get() = o.get();
73 } else {
74 destroy();
75 }
76 } else if ( o.filled ) {
77 init( o.get() );
78 }
79 return *this;
80 }
81 option& operator= ( option<T>&& o ) {
82 if ( filled ) {
83 if ( o.filled ) {
84 get() = move(o.get());
85 } else {
86 destroy();
87 }
88 } else if ( o.filled ) {
89 init( move(o.get()) );
90 }
91 return *this;
92 }
93 ~option() { if ( filled ) get().~T(); }
94
95 void swap( option<T>& o ) {
96 if ( filled ) {
97 if ( o.filled ) {
98 std::swap( get(), o.get() );
99 } else {
100 o.init( move(get()) );
101 destroy();
102 }
103 } else if ( o.filled ) {
104 init( move(o.get()) );
105 o.destroy();
106 }
107 }
108
109 /// Get contained value (unchecked)
110 T* operator->() { return &get(); }
111 const T* operator->() const { return &get(); }
112 T& operator*() & { return get(); }
113 const T& operator*() const& { return get(); }
114 T&& operator*() && { return move(get()); }
115 const T&& operator*() const&& { return move(get()); }
116
117 /// Check if option is filled
118 constexpr explicit operator bool() const { return filled; }
119 constexpr bool has_value() const { return filled; }
120
121 /// Get contained value (checked)
122 T& value() & { assertf(filled, "checked get failed"); return get(); }
123 const T& value() const& { assertf(filled, "checked get failed"); return get(); }
124 T&& value() && { assertf(filled, "checked get failed"); return move(get()); }
125 const T&& value() const&& { assertf(filled, "checked get failed"); return move(get()); }
126
127 /// Get contained or default value
128 template<typename U>
129 T value_or( U&& y ) const& { return filled ? get() : static_cast<T>(std::forward<U>(y)); }
130 template<typename U>
131 T value_or( U&& y ) && { return filled ? move(get()) : static_cast<T>(std::forward<U>(y)); }
132
133 /// Unset value if set
134 void reset() { if ( filled ) destroy(); }
135
136 /// Construct value in-place (destroys existing value if needed)
137 template<class... Args>
138 void emplace( Args&&... args ) {
139 if ( filled ) { destroy(); }
140 new(&storage) T{ std::forward<Args>(args)... };
141 filled = true;
142 }
143};
144
145template<typename T>
146bool operator== ( const option<T>& a, const option<T>& b ) {
147 return a ? (b && *a == *b) : !b;
148}
149
150template<typename T>
151bool operator!= ( const option<T>& a, const option<T>& b ) { return !(a == b); }
152
153template<typename T>
154bool operator< ( const option<T>& a, const option<T>& b ) {
155 return b && (!a || *a < *b);
156}
157
158template<typename T>
159bool operator<= ( const option<T>& a, const option<T>& b ) {
160 return !a || (b && *a <= *b);
161}
162
163template<typename T>
164bool operator> ( const option<T>& a, const option<T>& b ) { return b < a; }
165
166template<typename T>
167bool operator>= ( const option<T>& a, const option<T>& b ) { return b <= a; }
168
169template<typename T>
170bool operator== ( const option<T>& a, const T& x ) {
171 return a && *a == x;
172}
173
174template<typename T>
175bool operator!= ( const option<T>& a, const T& x ) { return !(a == x); }
176
177template<typename T>
178bool operator< ( const option<T>& a, const T& x ) {
179 return !a || *a < x;
180}
181
182template<typename T>
183bool operator<= ( const option<T>& a, const T& x ) {
184 return !a || *a <= x;
185}
186
187template<typename T>
188bool operator> ( const option<T>& a, const T& x ) {
189 return a && *a > x;
190}
191
192template<typename T>
193bool operator>= ( const option<T>& a, const T& x ) {
194 return a && *a >= x;
195}
196
197template<typename T>
198bool operator== ( const T& x, const option<T>& b ) { return b == x; }
199
200template<typename T>
201bool operator!= ( const T& x, const option<T>& b ) { return !(b == x); }
202
203template<typename T>
204bool operator< ( const T& x, const option<T>& b ) { return b > x; }
205
206template<typename T>
207bool operator<= ( const T& x, const option<T>& b ) { return b >= x; }
208
209template<typename T>
210bool operator> ( const T& x, const option<T>& b ) { return b < x; }
211
212template<typename T>
213bool operator>= ( const T& x, const option<T>& b ) { return b <= x; }
214
215template<typename T, typename... Args>
216option<T> make_option( Args&&... args ) {
217 option<T> o;
218 o.emplace( std::forward<Args>(args)... );
219 return o;
220}
221
222namespace std {
223 template<typename T>
224 void swap( option<T>& a, option<T>& b ) { a.swap(b); }
225
226 template<typename T>
227 struct hash< option<T> > {
228 size_t operator() ( const option<T>& a ) {
229 return a ? hash<T>{}( *a ) : size_t(1);
230 }
231 };
232}
Note: See TracBrowser for help on using the repository browser.