26#include "../concept.h"
27#include "./dispatch.h"
29#include "./val_union.h"
37template <
typename TL >
40 using ST = _val_union< TL >;
42 index_type index = null_index;
45 constexpr _val_core() noexcept = default;
47 constexpr _val_core( _val_core const& other ) noexcept(
48 all_nothrow_copy_constructible_v< TL > )
50 _copy_or_move_construct< false, TL >( *
this, other );
53 template <
typename UL >
54 requires( vconvertible_to< UL, TL > )
55 constexpr _val_core( _val_core< UL >
const& other )
noexcept(
56 all_nothrow_copy_constructible_v< UL > )
58 _copy_or_move_construct< false, UL >( *
this, other );
61 constexpr _val_core( _val_core&& other )
noexcept( all_nothrow_move_constructible_v< TL > )
63 _copy_or_move_construct< true, TL >( *
this, other );
66 template <
typename UL >
67 requires( vconvertible_to< UL, TL > )
68 constexpr _val_core( _val_core< UL >&& other )
noexcept(
69 all_nothrow_move_constructible_v< UL > )
71 _copy_or_move_construct< true, UL >( *
this, other );
74 template <
bool IS_MOVE,
typename UL >
75 static constexpr void _copy_or_move_construct(
auto& self,
auto& other )
noexcept(
76 IS_MOVE ? all_nothrow_move_constructible_v< UL > :
77 all_nothrow_copy_constructible_v< UL > )
79 if ( other.index == null_index )
81 _dispatch_index< 0, UL::size >(
82 other.index, [&]< index_type j >() ->
decltype(
auto ) {
83 static constexpr index_type i = _vptr_cnv_map< TL, UL >::conv( j );
84 using OST = typename _val_core< UL >::ST;
87 if constexpr ( IS_MOVE )
89 &ST::template get< i >( self.storage ),
90 std::move( OST::template get< j >( other.storage ) ) );
93 &ST::template get< i >( self.storage ),
94 OST::template get< j >( other.storage ) );
98 template <
typename O >
99 static constexpr bool is_nothrow_assignable =
100 noexcept( _val_core{ std::declval< O >() } ) &&
101 std::is_nothrow_swappable_v< _val_core >;
103 template <
typename O >
104 constexpr void assign( O&& other )
noexcept( is_nothrow_assignable< O > )
106 _val_core tmp{ (O&&) other };
110 friend constexpr void swap( _val_core& lh, _val_core& rh )
noexcept(
111 all_nothrow_swappable_v< TL > && all_nothrow_move_constructible_v< TL > &&
112 all_nothrow_destructible_v< TL > )
114 if ( lh.index == rh.index )
115 return _dispatch_index< 0, TL::size >(
116 lh.index, [&]< index_type j >() ->
decltype(
auto ) {
117 auto& l = ST::template get< j >( lh.storage );
118 auto& r = ST::template get< j >( rh.storage );
123 _val_core tmp{ std::move( lh ) };
124 if ( lh.index != null_index )
127 if ( rh.index != null_index )
128 move_from_to( rh, lh );
130 if ( tmp.index != null_index )
131 move_from_to( tmp, rh );
134 friend constexpr void move_from_to( _val_core& lh, _val_core& rh )
noexcept(
135 all_nothrow_move_constructible_v< TL > && all_nothrow_destructible_v< TL > )
137 _dispatch_index< 0, TL::size >(
138 lh.index, [&]< index_type j >() ->
decltype(
auto ) {
139 auto& l = ST::template get< j >( lh.storage );
140 auto& r = ST::template get< j >( rh.storage );
141 std::construct_at( &r, std::move( l ) );
143 std::destroy_at( &l );
148 template <
typename... Fs >
149 static constexpr decltype( auto ) visit_impl(
auto& self, Fs&&... fs )
151 return _dispatch_index< 0, TL::size >(
152 self.index, [&]< index_type j >() ->
decltype(
auto ) {
153 auto& p = ST::template get< j >( self.storage );
154 return _dispatch_fun( p, (Fs&&) fs... );
158 template <
typename F >
159 static constexpr decltype( auto ) visit_impl(
auto& self, F&& f )
161 return _dispatch_index< 0, TL::size >(
162 self.index, [&]< index_type j >() ->
decltype(
auto ) {
163 auto& p = ST::template get< j >( self.storage );
165 return ( (F&&) f )( p );
169 template <
typename T,
typename... Args >
171 emplace( Args&&... args )
noexcept( std::is_nothrow_constructible_v< T, Args... > )
173 constexpr index_type i = index_of_t_or_const_t_v< T, TL >;
176 return *std::construct_at( &ST::template get< i >( storage ), (Args&&) args... );
179 constexpr void destroy() noexcept( all_nothrow_destructible_v< TL > )
181 _dispatch_index< 0, TL::size >( index, [&]< index_type j > {
182 std::destroy_at( &ST::template get< j >( storage ) );
189 static constexpr std::partial_ordering three_way_compare(
191 _val_core
const& rh )
noexcept( all_nothrow_move_constructible_v< TL > )
195 index_type lh_i = lh.index;
196 index_type rh_i = rh.index;
198 return lh_i <=> rh_i;
199 return _dispatch_index< 0, TL::size >(
200 lh_i, [&]< index_type j >() -> std::partial_ordering {
201 return ST::template get< j >( lh.storage ) <=>
202 ST::template get< j >( rh.storage );
206 static constexpr decltype( auto ) compare(
208 _val_core
const& rh )
noexcept( all_nothrow_equality_comparable_v< TL > )
210 index_type lh_i = lh.index;
211 index_type rh_i = rh.index;
214 return _dispatch_index< 0, TL::size >( lh_i, [&]< index_type j > {
215 return ST::template get< j >( lh.storage ) ==
216 ST::template get< j >( rh.storage );
MIT License.
Definition: dispatch.h:32