41 #include <type_traits>
64 template<
class ... Types>
82 template<std::
size_t I,
class Variant>
91 template<
class T,
class Variant>
97 template<
class Variant>
100 template<std::
size_t I,
class Variant>
103 #ifndef VARIANT_IN_DOXYGEN_PARSING
105 template<std::
size_t I,
class Variant>
108 typedef typename std::add_const< typename variant_element<I, Variant>::type >::type type;
111 template<std::
size_t I,
class Variant>
114 typedef typename std::add_volatile< typename variant_element<I, Variant>::type >::type type;
117 template<std::
size_t I,
class Variant>
120 typedef typename std::add_cv< typename variant_element<I, Variant>::type >::type type;
123 template<std::
size_t I,
class Variant>
126 typedef typename std::add_lvalue_reference< typename variant_element<I, Variant>::type >::type type;
129 template<std::
size_t I,
class Variant>
132 typedef typename std::add_rvalue_reference< typename variant_element<I, Variant>::type >::type type;
135 template<std::size_t I,
class Head,
class ... Args>
139 template<
class Head,
class ... Args>
145 template<
class T,
class Variant>
148 template<
class T,
class Variant>
151 template<
class T,
class Variant>
154 template<
class T,
class Variant>
157 template<
class T,
class Variant>
160 template<
class T,
class Head,
class ... Args>
162 std::integral_constant<
164 variant_index<T, variant<Args ...> >::value + 1
167 template<
class Head,
class ... Args>
169 std::integral_constant<
174 template<
class ... Args>
175 struct variant_size<
variant<Args...> > : std::integral_constant<std::size_t, sizeof ... (Args) > {};
177 template<
class Variant>
180 template<
class Variant>
183 template<
class Variant>
186 template<
class Variant>
189 template<
class Variant>
192 #endif //VARIANT_IN_DOXYGEN_PARSING
194 template<
class ... Types>
198 struct deduce_overload_helper;
200 template<
class Head,
class ... Tail>
201 struct deduce_overload_helper<Head, Tail...> : deduce_overload_helper<Tail...>
203 using deduce_overload_helper<Tail...>::operator();
205 std::integral_constant< std::size_t,
206 sizeof ... (Types) -
sizeof ... (Tail) - 1> operator()( Head );
210 struct deduce_overload_helper<Head>
212 std::integral_constant< std::size_t,
sizeof ... (Types) - 1>
operator()( Head );
235 template<
class T,
class X =
void>
236 struct deduce_overload
238 static_assert( std::conditional_t<true, std::false_type, X>::value,
"Type deduction for T is ambiguous" );
242 struct deduce_overload<
244 typename std::enable_if<
245 detail::or_< std::is_same< std::decay_t<T>, Types > ... >::value
252 struct deduce_overload<
254 typename std::enable_if<
255 !detail::or_< std::is_same< std::decay_t<T>, Types > ... >::value,
256 decltype(std::result_of_t< deduce_overload_helper<Types...>(T) >{}, void() )
259 typedef std::result_of_t< deduce_overload_helper<Types...>(T) >
type;
263 using deduce_overload_t =
typename deduce_overload<T>::type;
266 friend class variant_deduce_overload_Test;
269 template<
class T,
class ... Args>
270 struct all_different :
272 all_different< Args ... >,
273 detail::not_< std::is_same<T,Args> >...
277 struct all_different<T> : std::true_type {};
279 template<
class ... OtherTypes>
282 constexpr std::size_t which_map[] = { deduce_overload_t<OtherTypes>::value ... };
283 return which_map[ v.which() ];
288 static_assert( all_different< Types ...>::value,
"Variant type parameters must be all different" );
289 static_assert( !detail::or_< std::is_reference<Types>... >::value,
"Variant type parameters can not be references" );
290 static_assert( !detail::or_< std::is_const<Types>... >::value,
"Variant type parameters can not be const" );
291 static_assert( !detail::or_< std::is_volatile<Types>... >::value,
"Variant type parameters can not be volatile" );
292 static_assert(
sizeof ... (Types) > 0,
"Type list can not be empty" );
302 variant() noexcept( std::is_nothrow_constructible<
storage_t, std::integral_constant<std::
size_t, 0> >::value ) :
304 storage_( std::integral_constant<std::
size_t, 0>{} )
314 noexcept( detail::and_< std::is_nothrow_copy_constructible<Types> ... >::value ) :
316 which_( other.which_ )
321 typedef typename std::remove_reference<decltype(val)>::type T;
323 new (& get< variant_index<T, variant>::value >(storage_)) T(val);
330 noexcept( detail::and_<std::is_nothrow_copy_constructible<Types> ... >::value ) :
332 which_( other.which_ )
337 typedef typename std::remove_reference<decltype(val)>::type T;
339 new (& get< variant_index<T, variant>::value >(storage_)) T(val);
350 which_( other.which_ )
355 typedef typename std::remove_reference<decltype(val)>::type T;
357 new (& get< variant_index<T, variant>::value >(storage_)) T(std::move(val) );
367 template<
class ... OtherTypes>
369 noexcept( detail::and_<std::is_nothrow_copy_constructible<OtherTypes> ... >::value ) :
371 which_( get_which_for(other) )
376 typedef typename std::remove_reference<decltype(val)>::type T;
378 new (& get< deduce_overload_t<T>::value >(storage_)) T(val);
388 template<
class ... OtherTypes>
390 noexcept(
detail::and_<std::is_nothrow_move_constructible<OtherTypes> ... >::value ) :
392 which_( get_which_for(other) )
397 typedef typename std::remove_reference<decltype(val)>::type T;
399 new (& get< deduce_overload_t<T>::value >(storage_)) T(std::move(val));
413 noexcept( std::is_nothrow_constructible<
415 deduce_overload_t<T&&>,
418 which_( deduce_overload_t<T&&>::value ),
419 storage_( deduce_overload_t<T&&>{},
420 std::forward<T>(value) )
431 noexcept( std::is_nothrow_constructible<
433 deduce_overload_t< std::initializer_list<T> >,
434 std::initializer_list<T> >::value) :
436 which_( deduce_overload_t< std::initializer_list<T> >::value ),
437 storage_( deduce_overload_t< std::initializer_list<T> >{}, init_list )
444 ~variant() noexcept(
detail::and_< std::is_nothrow_destructible< Types > ... >::value)
449 typedef typename std::remove_reference<decltype(val)>::type T;
471 noexcept( detail::and_ <
472 std::is_nothrow_copy_assignable< Types > ...,
473 std::is_nothrow_copy_constructible< Types > ... >::value)
475 static_assert( detail::and_< std::is_nothrow_destructible<Types> ... >::value,
476 "Can not implement any exception safety on variant copy assignement if a destructor can throw" );
478 if ( which_ == other.which_ )
483 typedef typename std::remove_reference<decltype(val)>::type T;
485 get< variant_index<T, variant>::value >( storage_ ) = val;
492 constexpr
bool is_nothrow_copy_constructible[] = { std::is_nothrow_copy_constructible<Types>::value ... };
494 if ( is_nothrow_copy_constructible[ other.which_ ] )
505 static_assert( detail::and_< std::is_nothrow_move_constructible<Types> ... >::value,
506 "Can not implement any exception safety on variant copy assignement if a move constructor can throw" );
515 new (
this)
variant( std::move(other) );
533 if ( which_ == other.which_ )
538 typedef typename std::remove_reference<decltype(val)>::type T;
540 get< variant_index<T, variant>::value >( storage_ ) = std::move(val);
548 static_assert( detail::and_< std::is_nothrow_move_constructible<Types > ... >::value,
549 "Can not implement any exception safety on variant move assignement if a move constructor can throw" );
551 static_assert( detail::and_< std::is_nothrow_destructible<Types > ... >::value,
552 "Can not implement any exception safety on variant move assignement if a destructor can throw" );
558 new (
this)
variant( std::move(other) );
566 std::size_t
which() const noexcept {
return which_; }
571 const std::type_info &
type() const noexcept
574 [&](
auto & val) ->
const std::type_info &
576 return typeid(
typename std::remove_reference<decltype(val)>::type);
588 template<
class T,
class Variant,
class =
typename
590 std::is_same< variant, typename std::decay< Variant >::type >::value
592 friend variant_element_t< variant_index<T, Variant>::value, Variant >
get(Variant && v)
596 return get< variant_index<T, variant>::value >(std::forward<Variant>(v).storage_);
599 storage_t& get_storage() & noexcept {
return storage_; }
600 storage_t&& get_storage() && noexcept {
return std::move(storage_); }
601 const storage_t& get_storage() const & noexcept {
return storage_; }
variant(variant< OtherTypes...> &&other) noexcept(detail::and_< std::is_nothrow_move_constructible< OtherTypes >... >::value)
Move from a compatible variant.
Definition: variant.hpp:389
variant(const variant &other) noexcept(detail::and_< std::is_nothrow_copy_constructible< Types >... >::value)
Copy constructor, invokes the copy constructor of the type currently bound on other.
Definition: variant.hpp:313
Obtain the index of a variant type.
Definition: variant.hpp:92
Exception class thrown when a type that is not currently bound is accessed via variant::get.
Definition: variant.hpp:70
variant(std::initializer_list< T > init_list) noexcept(std::is_nothrow_constructible< storage_t, deduce_overload_t< std::initializer_list< T > >, std::initializer_list< T > >::value)
Initializer list constructor, tries to deduce the desired type.
Definition: variant.hpp:430
variant_storage< Types... > storage_t
The underlying variant_storage type.
Definition: variant.hpp:288
Implements the class variant_storage.
std::size_t which() const noexcept
Return the index of the current bound object.
Definition: variant.hpp:566
variant & operator=(variant &&other) noexcept(detail::and_< std::is_nothrow_move_assignable< Types >... >::value)
Move assignment operator.
Definition: variant.hpp:531
~variant() noexcept(detail::and_< std::is_nothrow_destructible< Types >... >::value)
Destructor, calls the destructor on the currently bound type.
Definition: variant.hpp:444
Defines the member type type to the Ith type of the variant.
Definition: variant.hpp:83
Definition: relational.hpp:33
A templated generalized union.
Definition: variant_storage.hpp:64
const std::type_info & type() const noexcept
Return the type_info of the current bound object.
Definition: variant.hpp:571
A type safe generalized union.
Definition: variant.hpp:65
variant(const variant< OtherTypes...> &other) noexcept(detail::and_< std::is_nothrow_copy_constructible< OtherTypes >... >::value)
Copy from a compatible variant.
Definition: variant.hpp:368
Provides access to the number of elements in a variant as a compile-time constant expression...
Definition: variant.hpp:98
variant() noexcept(std::is_nothrow_constructible< storage_t, std::integral_constant< std::size_t, 0 > >::value)
Default construct this variant using the first type in Types.
Definition: variant.hpp:302
variant(T &&value) noexcept(std::is_nothrow_constructible< storage_t, deduce_overload_t< T && >, T && >::value)
Generic constructor, tries to deduce the desired type.
Definition: variant.hpp:412
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
variant(variant &&other) noexcept(detail::and_< std::is_nothrow_move_constructible< Types >... >::value)
Move constructor, invokes the move constructor of the type currently bound on other.
Definition: variant.hpp:349
variant & operator=(const variant &other) noexcept(detail::and_< std::is_nothrow_copy_assignable< Types >..., std::is_nothrow_copy_constructible< Types >... >::value)
Copy assignment operator.
Definition: variant.hpp:470