vari
Loading...
Searching...
No Matches
vopt.h
1
23
24#include "vari/bits/typelist.h"
25#include "vari/bits/util.h"
26#include "vari/bits/val_core.h"
27#include "vari/forward.h"
28#include "vari/uvref.h"
29#include "vari/vptr.h"
30#include "vari/vref.h"
31#include "vari/vval.h"
32
33#include <type_traits>
34#include <utility>
35
36#pragma once
37
38namespace vari
39{
40
41// WARNING: experimental
42// WARNING: untested
43template < typename... Ts >
44class _vopt
45{
46 using core_type = _val_core< typelist< Ts... > >;
47
48public:
49 using types = typelist< Ts... >;
50 using pointer = _vptr< Ts... >;
51 using const_pointer = _vptr< Ts const... >;
52 using reference = _vref< Ts... >;
53 using const_reference = _vref< Ts const... >;
54
55 constexpr _vopt() noexcept = default;
56
57 template < typename U >
58 requires( vconvertible_type< std::remove_cvref_t< U >, types > )
59 constexpr _vopt( U&& v ) noexcept( _forward_nothrow_constructible< U > )
60 {
61 _core.template emplace< std::remove_cvref_t< U > >( (U&&) v );
62 }
63
64 template < typename U, typename... Args >
65 requires( vconvertible_type< U, types > )
66 constexpr _vopt( std::in_place_type_t< U >, Args&&... args ) noexcept(
67 std::is_nothrow_constructible_v< U, Args... > )
68 {
69 _core.template emplace< U >( (Args&&) args... );
70 }
71
72 constexpr _vopt( _vopt&& p ) noexcept( std::is_nothrow_move_constructible_v< core_type > )
73 : _core( std::move( p._core ) )
74 {
75 }
76
77 template < typename... Us >
78 requires( vconvertible_to< typelist< Us... >, types > )
79 constexpr _vopt( _vopt< Us... >&& p ) noexcept(
80 std::is_nothrow_constructible_v< core_type, typename _vopt< Us... >::core_type&& > )
81 : _core( std::move( p._core ) )
82 {
83 }
84
85 template < typename... Us >
86 requires( vconvertible_to< typelist< Us... >, types > )
87 constexpr _vopt( _vval< Us... >&& p ) noexcept(
88 std::is_nothrow_constructible_v< core_type, typename _vval< Us... >::core_type&& > )
89 : _core( std::move( p._core ) )
90 {
91 }
92
93 constexpr _vopt( _vopt const& p ) noexcept(
94 std::is_nothrow_copy_constructible_v< core_type > )
95 : _core( p._core )
96 {
97 }
98
99 template < typename... Us >
100 requires( vconvertible_to< typelist< Us... >, types > )
101 constexpr _vopt( _vopt< Us... > const& p ) noexcept(
102 std::
103 is_nothrow_constructible_v< core_type, typename _vopt< Us... >::core_type const& > )
104 : _core( p._core )
105 {
106 }
107
108 template < typename... Us >
109 requires( vconvertible_to< typelist< Us... >, types > )
110 constexpr _vopt( _vval< Us... > const& p ) noexcept(
111 std::
112 is_nothrow_constructible_v< core_type, typename _vval< Us... >::core_type const& > )
113 : _core( p._core )
114 {
115 }
116
117 template < typename U >
118 requires( vconvertible_type< std::remove_cvref_t< U >, types > )
119 constexpr _vopt& operator=( U&& v ) noexcept( _forward_nothrow_constructible< U > )
120 {
121 if ( _core.index != null_index )
122 _core.destroy();
123 _core.template emplace< std::remove_cvref_t< U > >( (U&&) v );
124 return *this;
125 }
126
127 constexpr _vopt& operator=( _vopt&& p ) noexcept(
128 core_type::template is_nothrow_assignable< typename _vopt::core_type&& > )
129 {
130 // XXX not null friendly
131 _core.assign( std::move( p._core ) );
132 return *this;
133 }
134
135 template < typename... Us >
136 requires( vconvertible_to< typelist< Us... >, types > )
137 constexpr _vopt& operator=( _vopt< Us... >&& p ) noexcept(
138 core_type::template is_nothrow_assignable< typename _vopt< Us... >::core_type&& > )
139 {
140 // XXX not null friendly
141 _core.assign( std::move( p._core ) );
142 return *this;
143 }
144
145 constexpr _vopt& operator=( _vopt const& p ) noexcept(
146 core_type::template is_nothrow_assignable< typename _vopt::core_type const& > )
147 {
148 // XXX not null friendly
149 _core.assign( p._core );
150 return *this;
151 }
152
153 template < typename... Us >
154 requires( vconvertible_to< typelist< Us... >, types > )
155 constexpr _vopt& operator=( _vopt< Us... > const& p ) noexcept(
156 core_type::template is_nothrow_assignable< typename _vopt< Us... >::core_type const& > )
157 {
158 // XXX not null friendly
159 _core.assign( p._core );
160 return *this;
161 }
162
163 template < typename T, typename... Args >
164 requires( vconvertible_type< T, types > )
165 constexpr T&
166 emplace( Args&&... args ) noexcept( std::is_nothrow_constructible_v< T, Args... > )
167 {
168 if ( _core.index != null_index )
169 _core.destroy();
170 return _core.template emplace< T >( (Args&&) args... );
171 }
172
173 [[nodiscard]] constexpr index_type index() const noexcept
174 {
175 return _core.index;
176 }
177
178 constexpr auto& operator*() const noexcept
179 requires( types::size == 1 )
180 {
181 return core_type::ST::template get< 0 >( _core.storage );
182 }
183
184 constexpr auto* operator->() const noexcept
185 requires( types::size == 1 )
186 {
187 return &**this;
188 }
189
190 template < typename... Us >
191 requires( vconvertible_to< types, typelist< Us... > > )
192 constexpr operator _vptr< Us... >() & noexcept
193 {
194 if ( _core.index == null_index )
195 return _vptr< Us... >{};
196 return core_type::visit_impl( _core, [&]( auto& item ) {
197 return _vptr< Us... >( &item );
198 } );
199 }
200
201 template < typename... Us >
202 requires( vconvertible_to< types, typelist< Us... > > )
203 constexpr operator _vptr< Us... >() const& noexcept
204 {
205 static_assert( all_is_const_v< typelist< Us... > > );
206 if ( _core.index == null_index )
207 return _vptr< Us... >{};
208 return core_type::visit_impl( _core, [&]( auto& item ) {
209 return _vptr< Us... >( &item );
210 } );
211 }
212
213 constexpr explicit operator bool() const noexcept
214 {
215 return _core.index != null_index;
216 }
217
218 constexpr reference vref() & noexcept
219 {
220 VARI_ASSERT( *this );
221 return vptr().vref();
222 }
223
224 constexpr const_reference vref() const& noexcept
225 {
226 VARI_ASSERT( *this );
227 return vptr().vref();
228 }
229
230 constexpr pointer vptr() & noexcept
231 {
232 return pointer{ *this };
233 }
234
235 constexpr const_pointer vptr() const& noexcept
236 {
237 return const_pointer{ *this };
238 }
239
240 // XXX: noexcept if possible
241 // XXX: test
242 // XXX: test visit?
243 constexpr _vval< Ts... > vval() &&
244 {
245 VARI_ASSERT( !!*this );
246 _vval< Ts... > res;
247 swap( res._core, _core );
248 return res;
249 }
250
251 template < typename... Fs >
252 constexpr decltype( auto ) visit( Fs&&... f ) const
253 {
254 typename _check_unique_invocability< types >::template with_nullable_pure_cref<
255 Fs... >
256 _{};
257 if ( _core.index == null_index )
258 return _dispatch_fun( empty, (Fs&&) f... );
259 return core_type::visit_impl( _core, (Fs&&) f... );
260 }
261
262 template < typename... Fs >
263 constexpr decltype( auto ) visit( Fs&&... f )
264 {
265 typename _check_unique_invocability< types >::template with_nullable_pure_ref<
266 Fs... >
267 _{};
268 if ( _core.index == null_index )
269 return _dispatch_fun( empty, (Fs&&) f... );
270 return core_type::visit_impl( _core, (Fs&&) f... );
271 }
272
273 constexpr friend void
274 swap( _vopt& lh, _vopt& rh ) noexcept( std::is_nothrow_swappable_v< core_type > )
275 {
276 // XXX: not null friendly
277 swap( lh._core, rh._core );
278 }
279
280 constexpr ~_vopt() noexcept( std::is_nothrow_destructible_v< core_type > )
281 {
282 if ( _core.index != null_index )
283 _core.destroy();
284 }
285
286 friend constexpr std::partial_ordering operator<=>(
287 _vopt const& lh,
288 _vopt const& rh ) noexcept( all_nothrow_three_way_comparable_v< types > )
289 {
290 if ( lh._core.index == null_index || rh._core.index == null_index )
291 return lh._core.index <=> rh._core.index;
292 return core_type::three_way_compare( lh._core, rh._core );
293 };
294
295 friend constexpr auto operator==( _vopt const& lh, _vopt const& rh ) noexcept(
296 all_nothrow_equality_comparable_v< types > )
297 {
298 if ( lh._core.index == null_index || rh._core.index == null_index )
299 return lh._core.index == rh._core.index;
300 return core_type::compare( lh._core, rh._core );
301 };
302
303private:
304 template < typename... Us >
305 friend class _vopt;
306
307 core_type _core;
308};
309
310template < typename... Ts >
311using vopt = _define_variadic< _vopt, typelist< Ts... > >;
312
313} // namespace vari
MIT License.
Definition: dispatch.h:32
_define_variadic< _vref, typelist< Ts... > > vref
A non-nullable pointer to types derived out of Ts... list by flattening it and filtering for unique t...
Definition: vref.h:162
_define_variadic< _vptr, typelist< Ts... > > vptr
A nullable pointer to types derived out of Ts... list by flattening it and filtering for unique types...
Definition: vptr.h:189
_vptr_apply_t< T, unique_typelist_t< flatten_t< TL > >, Extra... > _define_variadic
Given a templated type T and typelist of types TL, aliases T<Us...> where Us... is flattend version o...
Definition: util.h:61