28 #ifndef VARIANT_STORAGE_HPP
29 #define VARIANT_STORAGE_HPP
39 #include <type_traits>
42 #include "relational.hpp"
63 template<
class ... Args>
66 template<
class ... Args>
67 union literal_variant_storage;
69 template<
class ... Args>
70 union nonliteral_variant_storage;
75 template<std::
size_t I,
class VariantStorage>
81 template<
class VariantStorage>
84 #ifndef VARIANT_IN_DOXYGEN_PARSING
86 template<std::
size_t I,
class VariantStorage>
88 std::add_const< typename variant_storage_element<I, VariantStorage>::type >::type {};
90 template<std::
size_t I,
class VariantStorage>
92 std::add_volatile< typename variant_storage_element<I, VariantStorage>::type >::type {};
94 template<std::
size_t I,
class VariantStorage>
96 std::add_cv< typename variant_storage_element<I, VariantStorage>::type >::type {};
98 template<std::
size_t I,
class VariantStorage>
101 template<std::size_t I,
class Head,
class ... Args>
107 template<
class Head,
class ... Args>
114 template<
class ... Args>
117 template<
class ... Args>
120 template<
class ... Args>
123 template<
class ... Args>
126 #endif //VARIANT_IN_DOXYGEN_PARSING
128 template<
class ... Args>
129 union literal_variant_storage;
131 template<
class Head,
class ... Tail>
132 union literal_variant_storage<Head, Tail...>
134 constexpr literal_variant_storage() noexcept : empty{} {}
136 template<std::size_t I,
class ... Args>
137 constexpr literal_variant_storage( std::integral_constant<std::size_t, I>, Args && ... args)
138 noexcept( std::is_nothrow_constructible<
139 literal_variant_storage<Tail...>,
140 std::integral_constant<std::
size_t, I-1>,
141 Args && ... >::value ) :
143 tail( std::integral_constant<std::
size_t, I-1>{},
144 std::forward<Args>(args) ... )
147 template<
class ... Args>
148 constexpr literal_variant_storage( std::integral_constant<std::size_t, 0>, Args && ... args)
149 noexcept( std::is_nothrow_constructible< Head, Args && ... >::value ) :
151 head( std::forward<Args>(args) ... )
154 template<std::
size_t I>
155 constexpr variant_storage_element_t<I,
variant_storage<Head, Tail...>> &
get( std::integral_constant<std::size_t, I> ) & noexcept
157 return tail.get( std::integral_constant<std::size_t, I-1>() );
160 constexpr Head&
get( std::integral_constant<std::size_t, 0> ) & noexcept
165 template<std::
size_t I>
166 constexpr variant_storage_element_t<I,
variant_storage<Head, Tail...>> &&
get( std::integral_constant<std::size_t, I> ) && noexcept
168 return std::move(tail).get( std::integral_constant<std::size_t, I-1>() );
171 constexpr Head&&
get( std::integral_constant<std::size_t, 0> ) && noexcept
173 return std::move(head);
176 template<std::
size_t I>
177 constexpr variant_storage_element_t<I,
variant_storage<Head, Tail...>>
const &
get( std::integral_constant<std::size_t, I> )
const & noexcept
179 return tail.get( std::integral_constant<std::size_t, I-1>() );
182 constexpr
const Head&
get( std::integral_constant<std::size_t, 0> )
const & noexcept
190 literal_variant_storage<Tail ... > tail;
194 union literal_variant_storage<>
198 template<
class ... Args>
199 union nonliteral_variant_storage;
201 template<
class Head,
class ... Tail>
202 union nonliteral_variant_storage<Head, Tail...>
204 nonliteral_variant_storage() noexcept : empty{} {}
206 template<std::size_t I,
class ... Args>
207 nonliteral_variant_storage( std::integral_constant<std::size_t, I>, Args && ... args)
208 noexcept( std::is_nothrow_constructible<
209 nonliteral_variant_storage<Tail ... >,
210 std::integral_constant<std::
size_t, I-1>,
211 Args && ... >::value ) :
213 tail( std::integral_constant<std::
size_t, I-1>{},
214 std::forward<Args>(args) ... )
217 template<
class ... Args>
218 nonliteral_variant_storage( std::integral_constant<std::size_t, 0>, Args && ... args)
219 noexcept( std::is_nothrow_constructible< Head, Args && ... >::value ) :
221 head( std::forward<Args>(args) ... )
224 ~nonliteral_variant_storage() {}
226 template<std::
size_t I>
227 variant_storage_element_t<I,
variant_storage<Head, Tail...>> &
get( std::integral_constant<std::size_t, I> ) & noexcept
229 return tail.get( std::integral_constant<std::size_t, I-1>() );
232 Head&
get( std::integral_constant<std::size_t, 0> ) & noexcept
237 template<std::
size_t I>
238 variant_storage_element_t<I,
variant_storage<Head, Tail...>> &&
get( std::integral_constant<std::size_t, I> ) && noexcept
240 return std::move(tail).get( std::integral_constant<std::size_t, I-1>() );
243 Head&&
get( std::integral_constant<std::size_t, 0> ) && noexcept
245 return std::move(head);
248 template<std::
size_t I>
249 variant_storage_element_t<I,
variant_storage<Head, Tail...>>
const &
get( std::integral_constant<std::size_t, I> )
const & noexcept
251 return tail.get( std::integral_constant<std::size_t, I-1>() );
254 const Head&
get( std::integral_constant<std::size_t, 0> )
const & noexcept
262 nonliteral_variant_storage<Tail ... > tail;
266 union nonliteral_variant_storage<>
270 template<
class ... Args>
273 using storage_type =
typename std::conditional<
274 detail::and_< std::is_literal_type<Args> ... >::value,
275 literal_variant_storage<Args...>,
276 nonliteral_variant_storage<Args...>
280 constexpr
variant_storage() noexcept(std::is_nothrow_constructible<storage_type>::value) : value{} {}
282 template<std::size_t I,
class ... CArgs>
283 constexpr
variant_storage( std::integral_constant<std::size_t, I>, CArgs && ... args )
284 noexcept( std::is_nothrow_constructible< storage_type, std::integral_constant<std::
size_t, I>, CArgs && ... >::value ) :
286 value( std::integral_constant<std::
size_t, I>{}, std::forward<CArgs>(args) ... )
289 template<std::size_t I,
class ... OtherArgs>
292 template<std::size_t I,
class ... OtherArgs>
295 template<std::size_t I,
class ... OtherArgs>
302 template<std::size_t I,
class ... Args>
305 return v.value.get( std::integral_constant<std::size_t, I>() );
308 template<std::size_t I,
class ... Args>
311 return std::move(v.value).get( std::integral_constant<std::size_t, I>() );
314 template<std::size_t I,
class ... Args>
317 return v.value.get( std::integral_constant<std::size_t, I>() );
320 class invoke_variant_storage_t
322 template<std::
size_t I,
class Callable,
class VariantStorage>
323 static decltype(
auto)
invoke( Callable && c,
326 std::integral_constant<std::
size_t, I> )
329 return which == (I-1) ?
330 std::forward<Callable>(c)(
get<I-1>(std::forward<VariantStorage>(v)) ) :
331 invoke( std::forward<Callable>(c),
332 std::forward<VariantStorage>(v),
334 std::integral_constant<std::size_t, I-1>{} );
337 template<
class Callable,
class VariantStorage>
338 static decltype(
auto)
invoke( Callable && c, VariantStorage && v, std::
size_t which, std::integral_constant<std::
size_t, 1> )
340 assert( which == 0 );
341 return std::forward<Callable>(c)( get<0>(std::forward<VariantStorage>(v)) );
344 template<
class Callable,
345 class VariantStorage,
347 std::make_integer_sequence<
352 struct is_nothrow_callable;
354 template<
class Callable,
class VariantStorage, std::size_t ... Is>
355 struct is_nothrow_callable< Callable, VariantStorage, std::integer_sequence<std::size_t, Is...> > :
357 std::integral_constant<
359 noexcept( std::declval<Callable&&>()( get<Is>(std::declval<VariantStorage>()) ) ) > ...
363 constexpr invoke_variant_storage_t() noexcept {}
365 template<
class VariantStorage,
class Callable>
366 decltype(
auto) operator()( Callable && c, VariantStorage && v, std::
size_t which ) const
367 noexcept( is_nothrow_callable< Callable &&, VariantStorage && >::value )
369 return invoke( std::forward<Callable>(c),
370 std::forward<VariantStorage>(v),
373 typename std::remove_reference<VariantStorage>::type
385 template<
class VariantStorage,
class Callable>
386 decltype(
auto)
invoke( Callable && c, VariantStorage && v, std::
size_t which )
389 invoke_variant_storage_t{}(
390 std::forward<Callable>(c),
391 std::forward<VariantStorage>(v),
395 return invoke_variant_storage_t{}(
396 std::forward<Callable>(c),
397 std::forward<VariantStorage>(v),
401 #endif // VARIANT_STORAGE_HPP
Provides access to the number of elements in a variant_storage as a compile-time constant expression...
Definition: variant_storage.hpp:82
A templated generalized union.
Definition: variant_storage.hpp:64
Defines the member type type to the I-th type of the variant_storage.
Definition: variant_storage.hpp:76
decltype(auto) invoke(Callable &&c, VariantStorage &&v, std::size_t which) noexcept(noexcept(invoke_variant_storage_t{}(std::forward< Callable >(c), std::forward< VariantStorage >(v), which)))
Calls the provided Callable with an element of the supplied variant storage.
Definition: variant_storage.hpp:386