namespace eggs { namespace variants { // variant for object types template <class ...Ts> class variant; // In-place construction template <std::size_t I> using in_place_index_t = void(*)(unspecified<I>); template <class T> using in_place_type_t = void(*)(unspecified<T>); template <std::size_t I> void in_place(unspecified<I>); template <class T> void in_place(unspecified<T>); // Class bad_variant_access class bad_variant_access; // Class template variant template <class ...Ts> class variant { public: static constexpr std::size_t npos = std::size_t(-1); // Constructors constexpr variant() noexcept; constexpr variant(variant const&); constexpr variant(variant&&) noexcept(see below); template <class U> constexpr variant(U&&); template <class U> constexpr explicit variant(U&&); template <std::size_t I, class ...Args> constexpr explicit variant(in_place_index_t<I>, Args&&...); template <std::size_t I, class U, class ...Args> constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U>, Args&&...); template <class T, class ...Args> constexpr explicit variant(in_place_type_t<T>, Args&&...); template <class T, class U, class ...Args> constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U>, Args&&...); // Destructor ~variant(); // Assignment constexpr variant& operator=(variant const&); constexpr variant& operator=(variant&&) noexcept(see below); template <class U> constexpr variant& operator=(U&&); template <std::size_t I, class ...Args> constexpr T& emplace(Args&&...); template <std::size_t I, class U, class ...Args> constexpr T& emplace(std::initializer_list<U>, Args&&...); template <class T, class ...Args> constexpr T& emplace(Args&&...); template <class T, class U, class ...Args> constexpr T& emplace(std::initializer_list<U>, Args&&...); // Swap constexpr void swap(variant&) noexcept(see below); // Observers constexpr explicit operator bool() const noexcept; constexpr std::size_t which() const noexcept; constexpr std::type_info const& target_type() const noexcept; constexpr void* target() noexcept; constexpr void const* target() const noexcept; template <class T> constexpr T* target() noexcept; template <class T> constexpr T const* target() const noexcept; }; // Class bad_variant_access class bad_variant_access : public std::exception { public: bad_variant_access() noexcept; char const* what() const noexcept override; }; // Helper classes template <class T> struct variant_size; template <class ...Ts> struct variant_size<variant<Ts...>>; template <class T> struct variant_size<T const>; template <class T> inline constexpr std::size_t variant_size_v = variant_size<T>::value; template <std::size_t I, class T> struct variant_element; // undefined template <std::size_t I, class ...Ts> struct variant_element<I, variant<Ts...>>; template <std::size_t I, class T> struct variant_element<I, T const>; template <std::size_t I, class T> using variant_element_t = class variant_element<I, T>::type; // Element access template <std::size_t I, class ...Ts> constexpr variant_element_t<I, variant<Ts...>>& get(variant<Ts...>&); template <std::size_t I, class ...Ts> constexpr variant_element_t<I, variant<Ts...>> const& get(variant<Ts...> const&); template <std::size_t I, class ...Ts> constexpr variant_element_t<I, variant<Ts...>>&& get(variant<Ts...>&&); template <std::size_t I, class ...Ts> constexpr variant_element_t<I, variant<Ts...>> const&& get(variant<Ts...> const&&); template <class T, class ...Ts> constexpr T& get(variant<Ts...>&); template <class T, class ...Ts> constexpr T const& get(variant<Ts...> const&); template <class T, class ...Ts> constexpr T&& get(variant<Ts...>&&); template <class T, class ...Ts> constexpr T const&& get(variant<Ts...> const&&); template <std::size_t I, class ...Ts> constexpr variant_element_t<I, variant<Ts...>>* get_if(variant<Ts...>*) noexcept; template <std::size_t I, class ...Ts> constexpr variant_element_t<I, variant<Ts...>> const* get_if(variant<Ts...> const*) noexcept; template <class T, class ...Ts> constexpr T* get_if(variant<Ts...>*) noexcept; template <class T, class ...Ts> constexpr T const* get_if(variant<Ts...> const*) noexcept; // Relational operators template <class ...Ts> constexpr bool operator==(variant<Ts...> const&, variant<Ts...> const&); template <class ...Ts> constexpr bool operator!=(variant<Ts...> const&, variant<Ts...> const&); template <class ...Ts> constexpr bool operator<(variant<Ts...> const&, variant<Ts...> const&); template <class ...Ts> constexpr bool operator>(variant<Ts...> const&, variant<Ts...> const&); template <class ...Ts> constexpr bool operator<=(variant<Ts...> const&, variant<Ts...> const&); template <class ...Ts> constexpr bool operator>=(variant<Ts...> const&, variant<Ts...> const&); // Comparison with Ts template <class ...Ts, class U> constexpr bool operator==(variant<Ts...> const&, U const&); template <class U, class ...Ts> constexpr bool operator==(U const&, variant<Ts...> const&); template <class ...Ts, class U> constexpr bool operator!=(variant<Ts...> const&, U const&); template <class U, class ...Ts> constexpr bool operator!=(U const&, variant<Ts...> const&); template <class ...Ts, class U> constexpr bool operator<(variant<Ts...> const&, U const&); template <class U, class ...Ts> constexpr bool operator<(U const&, variant<Ts...> const&); template <class ...Ts, class U> constexpr bool operator>(variant<Ts...> const&, U const&); template <class U, class ...Ts> constexpr bool operator>(U const&, variant<Ts...> const&); template <class ...Ts, class U> constexpr bool operator<=(variant<Ts...> const&, U const&); template <class U, class ...Ts> constexpr bool operator<=(U const&, variant<Ts...> const&); template <class ...Ts, class U> constexpr bool operator>=(variant<Ts...> const&, U const&); template <class U, class ...Ts> constexpr bool operator>=(U const&, variant<Ts...> const&); // Calling a function with variants of arguments template <class R, class F, class ...Vs> constexpr R apply(F&&, Vs&&...); template <class F, class ...Vs> constexpr see below apply(F&&, Vs&&...); // Specialized algorithms template <class ...Ts> constexpr void swap(variant<Ts...>&, variant<Ts...>&) noexcept(see below); }} // Hash support namespace std { template <class ...Ts> struct hash<::eggs::variants::variant<Ts...>>; } namespace eggs { using variants::variant; using variants::variant_size; using variants::variant_size_v; using variants::variant_element; using variants::variant_element_t; constexpr std::size_t variant_npos = std::size_t(-1); using variants::bad_variant_access; using variants::get; using variants::get_if; using variants::apply; }
varianttemplate <class ...Ts> class variant { public: static constexpr std::size_t npos = std::size_t(-1); // Constructors constexpr variant() noexcept; constexpr variant(variant const&); constexpr variant(variant&&) noexcept(see below); template <class U> constexpr variant(U&&); template <class U> constexpr explicit variant(U&&); template <std::size_t I, class ...Args> constexpr explicit variant(in_place_index_t<I>, Args&&...); template <std::size_t I, class U, class ...Args> constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U>, Args&&...); template <class T, class ...Args> constexpr explicit variant(in_place_type_t<T>, Args&&...); template <class T, class U, class ...Args> constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U>, Args&&...); // Destructor ~variant(); // Assignment constexpr variant& operator=(variant const&); constexpr variant& operator=(variant&&) noexcept(see below); template <class U> constexpr variant& operator=(U&&); template <std::size_t I, class ...Args> constexpr T& emplace(Args&&...); template <std::size_t I, class U, class ...Args> constexpr T& emplace(std::initializer_list<U>, Args&&...); template <class T, class ...Args> constexpr T& emplace(Args&&...); template <class T, class U, class ...Args> constexpr T& emplace(std::initializer_list<U>, Args&&...); // Swap constexpr void swap(variant&) noexcept(see below); // Observers constexpr explicit operator bool() const noexcept; constexpr std::size_t which() const noexcept; constexpr std::type_info const& target_type() const noexcept; constexpr void* target() noexcept; constexpr void const* target() const noexcept; template <class T> constexpr T* target() noexcept; template <class T> constexpr T const* target() const noexcept; };
In a variant, at most one of the members can be active at any time, that is, the value of at most one of the members can be stored in a variant at any time. Implementations are not permitted to use additional storage, such as dynamic memory, to allocate its contained value. The contained value shall be allocated in a region of the variant<Ts...> storage suitably aligned for the types Ts....
All T in Ts... shall be object types and shall satisfy the requirements of Destructible.
constexpr variant() noexcept;
*this does not have an active member.Ts... this constructor shall be a constexpr constructor.constexpr variant(variant const& rhs);
rhs has an active member of type T, initializes the active member as if direct-non-list-initializing an object of type T with the expression *rhs.target<T>(); otherwise, no member is initialized.rhs.which() == this->which().T.std::is_copy_constructible_v<T> is true for all T in Ts.... If std::is_trivially_copyable_v<T> is true for all T in Ts..., then this copy constructor shall be a trivial constexpr constructor.constexpr variant(variant&& rhs) noexcept(see below);
rhs has an active member of type T, initializes the active member as if direct-non-list-initializing an object of type T with the expression std::move(*rhs.target<T>()); otherwise, no member is initialized. bool(rhs) is unchanged.rhs.which() == this->which().T.noexcept is equivalent to the logical AND of std::is_nothrow_move_constructible_v<Ts>.... This constructor shall not participate in overload resolution unless std::is_move_constructible_v<T> is true for all T in Ts.... If std::is_trivially_copyable_v<T> is true for all T in Ts..., then this move constructor shall be a trivial constexpr constructor.template <class U>
constexpr variant(U&& v);
T be one of the types in Ts... for which std::forward<U>(u) is unambiguously convertible to by overload resolution rules.T with the expression std::forward<U>(v).*this has an active member.T.std::is_same_v<std::decay_t<U>, variant> is false, there is a type T in Ts... for which std::forward<U>(u) is unambiguously convertible to by overload resolution rules, and std::is_constructible_v<T, U> is true. If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.template <class U>
constexpr explicit variant(U&& v);
T be one of the types in Ts... for which std::is_constructible_v<T, U> is true.T with the expression std::forward<U>(v).*this has an active member.T.std::is_same_v<std::decay_t<U>, variant> is false, std::forward<U>(u) is not convertible to any T in Ts..., and there is a single type T in Ts... for which std::is_constructible_v<T, U> is true. If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.template <std::size_t I, class ...Args>
constexpr explicit variant(in_place_index_t<I>, Args&&... args);
T be the Ith element in Ts..., where indexing is zero-based.T with the arguments std::forward<Args>(args)....*this has an active member of type T.T.I < sizeof...(Ts), and std::is_constructible_v<T, Args...> is true. If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.template <std::size_t I, class U, class ...Args>
constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U> il, Args&&... args);
T be the Ith element in Ts..., where indexing is zero-based.T with the arguments il, std::forward<Args>(args)....*this has an active member of type T.T.I < sizeof...(Ts), and std::is_constructible_v<T, std::initializer_list<U>&, Args...> is true. If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.template <class T, class ...Args>
constexpr explicit variant(in_place_type_t<T>, Args&&... args);
variant(in_place<I>, std::forward<Args>(args)...) where I is the zero-based index of T in Ts....T in Ts..., and std::is_constructible_v<T, Args...> is true. If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.template <class T, class U, class ...Args>
constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U> il, Args&&... args);
variant(in_place<I>, il, std::forward<Args>(args)...) where I is the zero-based index of T in Ts....T in Ts..., and std::is_constructible_v<T, std::initializer_list<U>&, Args...> is true. If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.~variant();
*this has an active member of type T, destroys the active member as if by calling target<T>()->~T().std::is_trivially_destructible_v<T> is true for all T in Ts..., then this destructor shall be trivial.constexpr variant& operator=(variant const& rhs);
*this and rhs have an active member of type T, assigns to the active member the expression *rhs.target<T>();*this has an active member of type U, destroys the active member by calling target<U>()->~U(). Then, if rhs has an active member of type T, initializes the active member as if direct-non-list-initializing an object of type T with the expression *rhs.target<T>().*this.rhs.which() == this->which().T's copy assignment, the state of the active member is as defined by the exception safety guarantee of T's copy assignment. If an exception is thrown during the call to T's copy constructor, *this has no active member, and the previous active member (if any) has been destroyed. This function shall be defined as deleted unless std::is_copy_assignable_v<T> && std::is_copy_constructible_v<T> is true for all T in Ts.... If std::is_trivially_copyable_v<T> is true for all T in Ts..., then this copy assignment operator shall be a trivial constexpr assignment operator.constexpr variant& operator=(variant&& rhs) noexcept(see below);
*this and rhs have an active member of type T, assigns to the active member the expression std::move(*rhs.target<T>());*this has an active member of type U, destroys the active member by calling target<U>()->~U(). Then, if rhs has an active member of type T, initializes the active member as if direct-non-list-initializing an object of type T with the expression std::move(*rhs.target<Tn>()).bool(rhs) is unchanged.*this.rhs.which() == this->which().T's move assignment, the state of both active members is determined by the exception safety guarantee of T's move assignment. If an exception is thrown during the call to T's move constructor, *this has no active member, the previous active member (if any) has been destroyed, and the state of the active member of rhs is determined by the exception safety guarantee of T's move constructor. The expression inside noexcept is equivalent to the logical AND of std::is_nothrow_move_assignable_v<Ts>... and std::is_nothrow_move_constructible_v<Ts>.... This function shall not participate in overload resolution unless std::is_move_assignable_v<T> && std::is_move_constructible_v<T> is true for all T in Ts.... If std::is_trivially_copyable_v<T> is true for all T in Ts..., then this move assignment operator shall be a trivial constexpr assignment operator.template <class U>
constexpr variant& operator=(U&& v);
T be one of the types in Ts... for which std::forward<U>(u) is unambiguously convertible to by overload resolution rules.*this has an active member of type T, assigns to the active member the expression std::forward<U>(v);*this = {}. Then, initializes the active member as if direct-non-list-initializing an object of type T with the expression std::forward<U>(v).*this.*this has an active member.T's assignment, the state of the active member is as defined by the exception safety guarantee of T's assignment. If an exception is thrown during the call to T's constructor, *this has no active member, and the previous active member (if any) has been destroyed. This function shall not participate in overload resolution unless std::is_same_v<std::decay_t<U>, variant> is false, there is a type T in Ts... for which std::forward<U>(u) is unambiguously convertible to by overload resolution rules, and std::is_constructible_v<T, U> is true. This function shall be defined as deleted unless std::is_assignable_v<T&, U> is true. If std::is_trivially_copyable_v<T> is true for all T in Ts... and T's selected constructor is a constexpr constructor, then this function shall be a constexpr function.template <std::size_t I, class ...Args>
constexpr T& emplace(Args&&... args);
T be the Ith element in Ts..., where indexing is zero-based.I < sizeof...(Ts).*this = {}. Then, initializes the active member as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....*this has an active member of type T.T.T's constructor, *this has no active member, and the previous active member (if any) has been destroyed. This function shall not participate in overload resolution unless std::is_constructible_v<T, Args...> is true. If std::is_trivially_copyable_v<T> && std::is_copy_assignable_v<T> is true for all T in Ts... and T's selected constructor is a constexpr constructor, then this function shall be a constexpr function.template <std::size_t I, class U, class ...Args>
constexpr T& emplace(std::initializer_list<U> il, Args&&... args);
T be the Ith element in Ts..., where indexing is zero-based.I < sizeof...(Ts).*this = {}. Then, initializes the active member as if direct-non-list-initializing an object of type T with the arguments il, std::forward<Args>(args)....*this has an active member of type T.T.T's constructor, *this has no active member, and the previous active member (if any) has been destroyed. This function shall not participate in overload resolution unless std::is_constructible_v<T, std::initializer_list<U>&, Args...> is true. If std::is_trivially_copyable_v<T> && std::is_copy_assignable_v<T> is true for all T in Ts... and T's selected constructor is a constexpr constructor, then this function shall be a constexpr function.template <class T, class ...Args>
constexpr T& emplace(Args&&... args);
T shall occur exactly once in Ts....emplace<I>(std::forward<Args>(args)...) where I is the zero-based index of T in Ts....std::is_constructible_v<T, Args...> is true. If std::is_trivially_copyable_v<T> && std::is_copy_assignable_v<T> is true for all T in Ts... and T's selected constructor is a constexpr constructor, then this function shall be a constexpr function.template <class T, class U, class ...Args>
constexpr T& emplace(std::initializer_list<U> il, Args&&... args);
T shall occur exactly once in Ts....emplace<I>(il, std::forward<Args>(args)...) where I is the zero-based index of T in Ts....std::is_constructible_v<T, std::initializer_list<U>&, Args...> is true. If std::is_trivially_copyable_v<T> && std::is_copy_assignable_v<T> is true for all T in Ts... and T's selected constructor is a constexpr constructor, then this function shall be a constexpr function.constexpr void swap(variant& rhs) noexcept(see below);
T shall be swappable and std::is_move_constructible_v<T> is true for all T in Ts....*this and rhs have an active member of type T, calls swap(*this->target<T>(), *rhs.target<T>());std::swap(*this, rhs).swap the state of the active members of type T is determined by the exception safety guarantee of swap for lvalues of T. If an exception is thrown during the call to a move constructor, the state of *this and rhs is unspecified. The expression inside noexcept is equivalent to the logical AND of std::is_nothrow_move_constructible_v<T> && std::is_nothrow_swappable_v<T> for all T in Ts.... If std::is_trivially_copyable_v<T> && std::is_copy_assignable_v<T> is true for all T in Ts..., then this function shall be a constexpr function.constexpr explicit operator bool() const noexcept;
true if and only if *this has an active member.constexpr function.constexpr std::size_t which() const noexcept;
*this has one. Otherwise, returns npos.constexpr function.constexpr std::type_info const& target_type() const noexcept;
*this has an active member of type T, typeid(T); otherwise typeid(void).constexpr function.constexpr void* target() noexcept;
*this has an active member, a pointer to the active member; otherwise a null pointer.constexpr function.constexpr void const* target() const noexcept;
*this has an active member, a pointer to the active member; otherwise a null pointer.constexpr function.template <class T>
constexpr T* target() noexcept;
*this has an active member of type T or of a type of which T is an unambiguous and accessible base class, a pointer to the active member; otherwise a null pointer.constexpr function.template <class T>
constexpr T const* target() const noexcept;
*this has an active member of type T or of a type of which T is an unambiguous and accessible base class, a pointer to the active member; otherwise a null pointer.constexpr function.template <std::size_t I> using in_place_index_t = void(*)(unspecified<I>); template <class T> using in_place_type_t = void(*)(unspecified<T>); template <std::size_t I> void in_place(unspecified<I>); template <class T> void in_place(unspecified<T>);
The template aliases in_place_index_t and in_place_type_t are used as unique types to disambiguate constructor and function overloading. Specifically, variant<Ts...> has a constructor with in_place_type_t<T> as the first parameter, followed by a parameter pack; this indicates that T should be constructed in-place (as if by a call to a placement new expression) with the forwarded pack expansion as arguments for the initialization of T.
bad_variant_accessclass bad_variant_access : public std::exception { public: bad_variant_access() noexcept; char const* what() const noexcept override; };
Objects of type bad_variant_access are thrown to report attempts to access an inactive member of a variant object.
bad_variant_access() noexcept;
bad_variant_access object.char const* what() const noexcept override;
template <class T>
struct variant_size;
variant_size<T> shall meet the UnaryTypeTrait requirements with a BaseCharacteristic of std::integral_constant<std::size_t, N> for some N if T is a variant-like type; otherwise it shall be empty.template <class ...Ts>
struct variant_size<variant<Ts...>>;
BaseCharacteristic of std::integral_constant<std::size_t, sizeof...(Ts)>.template <class T>
struct variant_size<T const>;
VS denote variant_size<T> of the cv-unqualified type T. Has a BaseCharacteristic of std::integral_constant<std::size_t, VS::value> if T is a variant-like type; otherwise it is empty.template <std::size_t I, class T>
struct variant_element;
variant_element<I, T> shall meet the TransformationTrait requirements with a member typedef type that names the Ith member of T, where indexing is zero-based.template <std::size_t I, class ...Ts>
struct variant_element<I, variant<Ts...>>;
I < sizeof...(Ts). Otherwise, the program is ill-formed.type shall name the type of the Ith element of Ts..., where indexing is zero-based.template <std::size_t I, class T>
struct variant_element<I, T const>;
VE denote variant_element<I, T> of the cv-unqualified type T. The member typedef type names std::add_const_t<typename VE::type>.template <std::size_t I, class ...Ts>
constexpr variant_element_t<I, variant<Ts...>>& get(variant<Ts...>& v);
I < sizeof...(Ts). Otherwise, the program is ill-formed.Ith member of v if it is active, where indexing is zero-based.bad_variant_access if the Ith member of v is not active.constexpr function.template <std::size_t I, class ...Ts>
constexpr variant_element_t<I, variant<Ts...>> const& get(variant<Ts...> const& v);
I < sizeof...(Ts). Otherwise, the program is ill-formed.Ith member of v if it is active, where indexing is zero-based.bad_variant_access if the Ith member of v is not active.constexpr function.template <std::size_t I, class ...Ts>
constexpr variant_element_t<I, variant<Ts...>>&& get(variant<Ts...>&& v);
I < sizeof...(Ts). Otherwise, the program is ill-formed.std::forward<variant_element_t<I, variant<Ts...>>>(get<I>(v)).constexpr function.template <std::size_t I, class ...Ts>
constexpr variant_element_t<I, variant<Ts...>> const&& get(variant<Ts...> const&& v);
I < sizeof...(Ts). Otherwise, the program is ill-formed.std::forward<variant_element_t<I, variant<Ts...>> const>(get<I>(v)).constexpr function.template <class T, class ...Ts>
constexpr T& get(variant<Ts...>& v);
T occurs exactly once in Ts.... Otherwise, the program is ill-formed.v if it is of type T.bad_variant_access if the active member of v is not of type T.constexpr function.template <class T, class ...Ts>
constexpr T const& get(variant<Ts...> const& v);
T occurs exactly once in Ts.... Otherwise, the program is ill-formed.v if it is of type T.bad_variant_access if the active member of v is not of type T.constexpr function.template <class T, class ...Ts>
constexpr T&& get(variant<Ts...>&& v);
T occurs exactly once in Ts.... Otherwise, the program is ill-formed.std::forward<T>(get<T>(v)).constexpr function.template <class T, class ...Ts>
constexpr T const&& get(variant<Ts...> const&& v);
T occurs exactly once in Ts.... Otherwise, the program is ill-formed.std::forward<T const>(get<T>(v)).constexpr function.template <std::size_t I, class ...Ts>
constexpr variant_element_t<I, variant<Ts...>>* get_if(variant<Ts...>* v) noexcept;
I < sizeof...(Ts). Otherwise, the program is ill-formed.v != nullptr, a pointer to the Ith member of *v if it is active, where indexing is zero-based; otherwise, nullptr.constexpr function.template <std::size_t I, class ...Ts>
constexpr variant_element_t<I, variant<Ts...>> const* get_if(variant<Ts...> const* v) noexcept;
I < sizeof...(Ts). Otherwise, the program is ill-formed.v != nullptr, a const pointer to the Ith member of *v if it is active, where indexing is zero-based; otherwise, nullptr.constexpr function.template <class T, class ...Ts>
constexpr T* get_if(variant<Ts...>* v) noexcept;
T occurs exactly once in Ts.... Otherwise, the program is ill-formed.v != nullptr, a pointer to the active member of *v if it is of type T; otherwise, nullptr.constexpr function.template <class T, class ...Ts>
constexpr T const* get_if(variant<Ts...> const* v) noexcept;
T occurs exactly once in Ts.... Otherwise, the program is ill-formed.v != nullptr, a const pointer to the active member of *v if it is of type T; otherwise, nullptr.constexpr function.template <class ...Ts>
constexpr bool operator==(variant<Ts...> const& lhs, variant<Ts...> const& rhs);
*lhs.target<T>() == *rhs.target<T>() shall be convertible to bool for all T in Ts....lhs.which() != rhs.which(), false; otherwise, if !bool(lhs), true; otherwise, *lhs.target<T>() == *rhs.target<T>() where T is the type of the active member of both lhs and rhs.*lhs.target<T>() == *rhs.target<T>() is well-formed for all T in Ts.... This function shall be a constexpr function unless lhs.which() == rhs.which() and *lhs.target<T>() == *rhs.target<T>() where T is the type of the active member of both lhs and rhs is not a constant expression.template <class ...Ts>
constexpr bool operator!=(variant<Ts...> const& lhs, variant<Ts...> const& rhs);
*lhs.target<T>() != *rhs.target<T>() shall be convertible to bool for all T in Ts....lhs.which() != rhs.which(), true; otherwise, if !bool(lhs), false; otherwise, *lhs.target<T>() != *rhs.target<T>() where T is the type of the active member of both lhs and rhs.*lhs.target<T>() != *rhs.target<T>() is well-formed for all T in Ts.... This function shall be a constexpr function unless lhs.which() == rhs.which() and *lhs.target<T>() != *rhs.target<T>() where T is the type of the active member of both lhs and rhs is not a constant expression.template <class ...Ts>
constexpr bool operator<(variant<Ts...> const& lhs, variant<Ts...> const& rhs);
*lhs.target<T>() < *rhs.target<T>() shall be convertible to bool for all T in Ts....!bool(rhs), false; otherwise, if !bool(lhs), true; otherwise, if lhs.which() == rhs.which(), *lhs.target<T>() < *rhs.target<T>() where T is the type of the active member of both lhs and rhs; otherwise, lhs.which() < rhs.which().*lhs.target<T>() < *rhs.target<T>() is well-formed for all T in Ts.... This function shall be a constexpr function unless lhs.which() == rhs.which() and *lhs.target<T>() < *rhs.target<T>() where T is the type of the active member of both lhs and rhs is not a constant expression.template <class ...Ts>
constexpr bool operator>(variant<Ts...> const& lhs, variant<Ts...> const& rhs);
*lhs.target<T>() > *rhs.target<T>() shall be convertible to bool for all T in Ts....!bool(lhs), false; otherwise, if !bool(rhs), true; otherwise, if lhs.which() == rhs.which(), *lhs.target<T>() > *rhs.target<T>() where T is the type of the active member of both lhs and rhs; otherwise, lhs.which() > rhs.which().*lhs.target<T>() > *rhs.target<T>() is well-formed for all T in Ts.... This function shall be a constexpr function unless lhs.which() == rhs.which() and *lhs.target<T>() > *rhs.target<T>() where T is the type of the active member of both lhs and rhs is not a constant expression.template <class ...Ts>
constexpr bool operator<=(variant<Ts...> const& lhs, variant<Ts...> const& rhs);
*lhs.target<T>() <= *rhs.target<T>() shall be convertible to bool for all T in Ts....!bool(lhs), true; otherwise, if !bool(rhs), false; otherwise, if lhs.which() == rhs.which(), *lhs.target<T>() <= *rhs.target<T>() where T is the type of the active member of both lhs and rhs; otherwise, lhs.which() < rhs.which().*lhs.target<T>() <= *rhs.target<T>() is well-formed for all T in Ts.... This function shall be a constexpr function unless lhs.which() == rhs.which() and *lhs.target<T>() <= *rhs.target<T>() where T is the type of the active member of both lhs and rhs is not a constant expression.template <class ...Ts>
constexpr bool operator>=(variant<Ts...> const& lhs, variant<Ts...> const& rhs);
*lhs.target<T>() >= *rhs.target<T>() shall be convertible to bool for all T in Ts....!bool(rhs), true; otherwise, if !bool(lhs), false; otherwise, if lhs.which() == rhs.which(), *lhs.target<T>() >= *rhs.target<T>() where T is the type of the active member of both lhs and rhs; otherwise, lhs.which() > rhs.which().*lhs.target<T>() >= *rhs.target<T>() is well-formed for all T in Ts.... This function shall be a constexpr function unless lhs.which() == rhs.which() and *lhs.target<T>() >= *rhs.target<T>() where T is the type of the active member of both lhs and rhs is not a constant expression.Tstemplate <class ...Ts, class U>
constexpr bool operator==(variant<Ts...> const& lhs, U const& rhs);
T be one of the types in Ts... for which rhs is unambiguously convertible to by overload resolution rules.*lhs.target<T>() == rhs shall be convertible to bool.lhs has an active member of type T, *lhs.target<T>() == rhs; otherwise, false.T in Ts... for which rhs is unambiguously convertible to by overload resolution rules, and the expression *lhs.target<T>() == rhs is well-formed. This function shall be a constexpr function unless lhs has an active member of type T and *lhs.target<T>() == rhs is not a constant expression.template <class U, class ...Ts>
constexpr bool operator==(U const& lhs, variant<Ts...> const& rhs);
T be one of the types in Ts... for which lhs is unambiguously convertible to by overload resolution rules.lhs == *rhs.target<T>() shall be convertible to bool.rhs has an active member of type T, lhs == *rhs.target<T>(); otherwise, false.T in Ts... for which lhs is unambiguously convertible to by overload resolution rules, and the expression lhs == *rhs.target<T>() is well-formed. This function shall be a constexpr function unless rhs has an active member of type T and lhs == *rhs.target<T>() is not a constant expression.template <class ...Ts, class U>
constexpr bool operator!=(variant<Ts...> const& lhs, U const& rhs);
T be one of the types in Ts... for which rhs is unambiguously convertible to by overload resolution rules.*lhs.target<T>() != rhs shall be convertible to bool.lhs has an active member of type T, *lhs.target<T>() != rhs; otherwise, true.T in Ts... for which rhs is unambiguously convertible to by overload resolution rules, and the expression *lhs.target<T>() != rhs is well-formed. This function shall be a constexpr function unless lhs has an active member of type T and *lhs.target<T>() != rhs is not a constant expression.template <class U, class ...Ts>
constexpr bool operator!=(U const& lhs, variant<Ts...> const& rhs);
T be one of the types in Ts... for which lhs is unambiguously convertible to by overload resolution rules.lhs != *rhs.target<T>() shall be convertible to bool.rhs has an active member of type T, lhs != *rhs.target<T>(); otherwise, true.T in Ts... for which lhs is unambiguously convertible to by overload resolution rules, and the expression lhs != *rhs.target<T>() is well-formed. This function shall be a constexpr function unless rhs has an active member of type T and lhs != *rhs.target<T>() is not a constant expression.template <class ...Ts, class U>
constexpr bool operator<(variant<Ts...> const& lhs, U const& rhs);
T be one of the types in Ts... for which rhs is unambiguously convertible to by overload resolution rules.*lhs.target<T>() < rhs shall be convertible to bool.!bool(lhs), true; otherwise, if lhs has an active member of type T, *lhs.target<T>() < rhs; otherwise, lhs.which() < I where I is the zero-based index of T in Ts....T in Ts... for which rhs is unambiguously convertible to by overload resolution rules, and the expression *lhs.target<T>() < rhs is well-formed. This function shall be a constexpr function unless lhs has an active member of type T and *lhs.target<T>() < rhs is not a constant expression.template <class U, class ...Ts>
constexpr bool operator<(U const& lhs, variant<Ts...> const& rhs);
T be one of the types in Ts... for which lhs is unambiguously convertible to by overload resolution rules.lhs < *rhs.target<T>() shall be convertible to bool.!bool(rhs), false; otherwise, if rhs has an active member of type T, lhs < *rhs.target<T>(); otherwise, I < rhs.which() where I is the zero-based index of T in Ts....T in Ts... for which lhs is unambiguously convertible to by overload resolution rules, and the expression lhs < *rhs.target<T>() is well-formed. This function shall be a constexpr function unless rhs has an active member of type T and lhs < *rhs.target<T>() is not a constant expression.template <class ...Ts, class U>
constexpr bool operator>(variant<Ts...> const& lhs, U const& rhs);
T be one of the types in Ts... for which rhs is unambiguously convertible to by overload resolution rules.*lhs.target<T>() > rhs shall be convertible to bool.!bool(lhs), false; otherwise, if lhs has an active member of type T, *lhs.target<T>() > rhs; otherwise, lhs.which() > I where I is the zero-based index of T in Ts....T in Ts... for which rhs is unambiguously convertible to by overload resolution rules, and the expression *lhs.target<T>() > rhs is well-formed. This function shall be a constexpr function unless lhs has an active member of type T and *lhs.target<T>() > rhs is not a constant expression.template <class U, class ...Ts>
constexpr bool operator>(U const& lhs, variant<Ts...> const& rhs);
T be one of the types in Ts... for which lhs is unambiguously convertible to by overload resolution rules.lhs > *rhs.target<T>() shall be convertible to bool.!bool(rhs), true; otherwise, if rhs has an active member of type T, lhs > *rhs.target<T>(); otherwise, I > rhs.which() where I is the zero-based index of T in Ts....T in Ts... for which lhs is unambiguously convertible to by overload resolution rules, and the expression lhs > *rhs.target<T>() is well-formed. This function shall be a constexpr function unless rhs has an active member of type T and lhs > *rhs.target<T>() is not a constant expression.template <class ...Ts, class U>
constexpr bool operator<=(variant<Ts...> const& lhs, U const& rhs);
T be one of the types in Ts... for which rhs is unambiguously convertible to by overload resolution rules.*lhs.target<T>() <= rhs shall be convertible to bool.!bool(lhs), true; otherwise, if lhs has an active member of type T, *lhs.target<T>() <= rhs; otherwise, lhs.which() < I where I is the zero-based index of T in Ts....T in Ts... for which rhs is unambiguously convertible to by overload resolution rules, and the expression *lhs.target<T>() <= rhs is well-formed. This function shall be a constexpr function unless lhs has an active member of type T and *lhs.target<T>() <= rhs is not a constant expression.template <class U, class ...Ts>
constexpr bool operator<=(U const& lhs, variant<Ts...> const& rhs);
T be one of the types in Ts... for which lhs is unambiguously convertible to by overload resolution rules.lhs <= *rhs.target<T>() shall be convertible to bool.!bool(rhs), false; otherwise, if rhs has an active member of type T, lhs <= *rhs.target<T>(); otherwise, I < rhs.which() where I is the zero-based index of T in Ts....T in Ts... for which lhs is unambiguously convertible to by overload resolution rules, and the expression lhs <= *rhs.target<T>() is well-formed. This function shall be a constexpr function unless rhs has an active member of type T and lhs <= *rhs.target<T>() is not a constant expression.template <class ...Ts, class U>
constexpr bool operator>=(variant<Ts...> const& lhs, U const& rhs);
T be one of the types in Ts... for which rhs is unambiguously convertible to by overload resolution rules.*lhs.target<T>() >= rhs shall be convertible to bool.!bool(lhs), false; otherwise, if lhs has an active member of type T, *lhs.target<T>() >= rhs; otherwise, lhs.which() > I where I is the zero-based index of T in Ts....T in Ts... for which rhs is unambiguously convertible to by overload resolution rules, and the expression *lhs.target<T>() >= rhs is well-formed. This function shall be a constexpr function unless lhs has an active member of type T and *lhs.target<T>() >= rhs is not a constant expression.template <class U, class ...Ts>
constexpr bool operator>=(U const& lhs, variant<Ts...> const& rhs);
T be one of the types in Ts... for which lhs is unambiguously convertible to by overload resolution rules.lhs >= *rhs.target<T>() shall be convertible to bool.!bool(rhs), true; otherwise, if rhs has an active member of type T, lhs >= *rhs.target<T>(); otherwise, I > rhs.which() where I is the zero-based index of T in Ts....T in Ts... for which lhs is unambiguously convertible to by overload resolution rules, and the expression lhs >= *rhs.target<T>() is well-formed. This function shall be a constexpr function unless rhs has an active member of type T and lhs >= *rhs.target<T>() is not a constant expression.template <class R, class F, class ...Vs>
constexpr R apply(F&& f, Vs&&... vs);
Vi be the i-th type in Vs..., where all indexing is zero-based.i, Vi shall be either a specialization of variant or publicly and unambiguously derived, directly or indirectly, from one. Let Ui be the i-th variant specialization. INVOKE(std::forward<F>(f), get<Is>(std::forward<Vs>(vs))..., R) shall be a valid expression for all Is... in the range [0u, variant_size_v<Ui>)....INVOKE(std::forward<F>(f), get<Is>(std::forward<Vs>(vs))...), R) where Is... are the zero-based indices of the active members of vs....bad_variant_access if any of vs... has no active member.constexpr function.template <class F, class ...Vs>
constexpr R apply(F&& f, Vs&&... vs);
Ri... be the return types of every potentially evaluated INVOKE expression; if every Ri... is the same type, then let R be that type.
apply<R>(std::forward<F>(f), std::forward<Vs>(vs)...).INVOKE expression is the same type. If the selected function is a constant expression, then this function shall be a constexpr function.template <class ...Ts>
constexpr void swap(variant<Ts...>& x, variant<Ts...>& y) noexcept(noexcept(x.swap(y)));
x.swap(y).std::is_move_constructible_v<T> && std::is_swappable_v<T> is true for all T in Ts.... If std::is_trivially_copyable_v<T> && std::is_copy_assignable_v<T> is true for all T in Ts..., then this function shall be a constexpr function.template <class ...Ts>
struct std::hash<eggs::variants::variant<Ts...>>;
std::hash<variant<Ts...>> is enabled if and only if every specialization in std::hash<std::remove_const_t<Ts>>... is enabled. When enabled, for an object v of type variant<Ts...>, if v has an active member of type T, std::hash<variant<Ts...>>()(v) shall evaluate to the same value as std::hash<T>()(*v.target<T>()); otherwise it evaluates to an unspecified value. The member functions are guaranteed to be noexcept if the member functions of every specialization in std::hash<std::remove_const_t<Ts>>... are noexcept.
Copyright Agustín Bergé, Fusion Fenix 2014-2017
Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)