1#ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
2#define ENTT_CORE_COMPRESSED_PAIR_HPP
8#include "type_traits.hpp"
15template<
typename Type, std::
size_t,
typename =
void>
16struct compressed_pair_element {
17 using reference = Type &;
18 using const_reference =
const Type &;
20 template<
bool Dummy = true,
typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
21 constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>)
24 template<
typename Arg,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
25 constexpr compressed_pair_element(Arg &&arg)
noexcept(std::is_nothrow_constructible_v<Type, Arg>)
26 : value{std::forward<Arg>(arg)} {}
28 template<
typename... Args, std::size_t... Index>
29 constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
noexcept(std::is_nothrow_constructible_v<Type, Args...>)
30 : value{std::forward<Args>(std::
get<Index>(args))...} {}
32 [[nodiscard]]
constexpr reference
get() noexcept {
36 [[nodiscard]]
constexpr const_reference
get() const noexcept {
44template<
typename Type, std::
size_t Tag>
45struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
46 using reference = Type &;
47 using const_reference =
const Type &;
48 using base_type = Type;
50 template<
bool Dummy = true,
typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
51 constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
54 template<
typename Arg,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
55 constexpr compressed_pair_element(Arg &&arg)
noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
56 : base_type{std::forward<Arg>(arg)} {}
58 template<
typename... Args, std::size_t... Index>
59 constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
60 : base_type{std::forward<Args>(std::
get<Index>(args))...} {}
62 [[nodiscard]]
constexpr reference
get() noexcept {
66 [[nodiscard]]
constexpr const_reference
get() const noexcept {
83template<
typename First,
typename Second>
85 : internal::compressed_pair_element<First, 0u>,
86 internal::compressed_pair_element<Second, 1u> {
87 using first_base = internal::compressed_pair_element<First, 0u>;
88 using second_base = internal::compressed_pair_element<Second, 1u>;
104 template<
bool Dummy = true,
typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
105 constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> &&std::is_nothrow_default_constructible_v<second_base>)
113 constexpr compressed_pair(
const compressed_pair &other)
noexcept(std::is_nothrow_copy_constructible_v<first_base> &&std::is_nothrow_copy_constructible_v<second_base>) =
default;
119 constexpr compressed_pair(
compressed_pair &&other)
noexcept(std::is_nothrow_move_constructible_v<first_base> &&std::is_nothrow_move_constructible_v<second_base>) =
default;
128 template<
typename Arg,
typename Other>
129 constexpr compressed_pair(Arg &&arg, Other &&other)
noexcept(std::is_nothrow_constructible_v<first_base, Arg> &&std::is_nothrow_constructible_v<second_base, Other>)
130 : first_base{std::forward<Arg>(arg)},
131 second_base{std::forward<Other>(other)} {}
140 template<
typename... Args,
typename... Other>
141 constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other)
noexcept(std::is_nothrow_constructible_v<first_base, Args...> &&std::is_nothrow_constructible_v<second_base, Other...>)
142 : first_base{std::move(args), std::index_sequence_for<Args...>{}},
143 second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
164 return static_cast<first_base &
>(*this).get();
169 return static_cast<const first_base &
>(*this).get();
177 return static_cast<second_base &
>(*this).get();
182 return static_cast<const second_base &
>(*this).get();
189 constexpr void swap(
compressed_pair &other)
noexcept(std::is_nothrow_swappable_v<first_type> &&std::is_nothrow_swappable_v<second_type>) {
191 swap(first(), other.first());
192 swap(second(), other.second());
201 template<std::
size_t Index>
202 constexpr decltype(
auto)
get()
noexcept {
203 if constexpr(Index == 0u) {
206 static_assert(Index == 1u,
"Index out of bounds");
212 template<std::
size_t Index>
213 constexpr decltype(
auto)
get()
const noexcept {
214 if constexpr(Index == 0u) {
217 static_assert(Index == 1u,
"Index out of bounds");
228template<
typename Type,
typename Other>
238template<
typename First,
typename Second>
246#if !defined __clang_major__ || __clang_major__ > 6
254template<
typename First,
typename Second>
255struct tuple_size<
entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
263template<
size_t Index,
typename First,
typename Second>
264struct tuple_element<Index,
entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
265 static_assert(Index < 2u,
"Index out of bounds");
constexpr second_type & second() noexcept
Returns the second element that a pair stores.
constexpr const first_type & first() const noexcept
Returns the first element that a pair stores.
constexpr compressed_pair(const compressed_pair &other) noexcept(std::is_nothrow_copy_constructible_v< first_base > &&std::is_nothrow_copy_constructible_v< second_base >)=default
Copy constructor.
constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v< first_base, Arg > &&std::is_nothrow_constructible_v< second_base, Other >)
Constructs a pair from its values.
constexpr decltype(auto) get() const noexcept
Extracts an element from the compressed pair.
constexpr decltype(auto) get() noexcept
Extracts an element from the compressed pair.
constexpr compressed_pair & operator=(compressed_pair &&other) noexcept(std::is_nothrow_move_assignable_v< first_base > &&std::is_nothrow_move_assignable_v< second_base >)=default
Move assignment operator.
constexpr first_type & first() noexcept
Returns the first element that a pair stores.
constexpr compressed_pair(std::piecewise_construct_t, std::tuple< Args... > args, std::tuple< Other... > other) noexcept(std::is_nothrow_constructible_v< first_base, Args... > &&std::is_nothrow_constructible_v< second_base, Other... >)
Constructs a pair by forwarding the arguments to its parts.
First first_type
The type of the first element that the pair stores.
constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v< first_base > &&std::is_nothrow_default_constructible_v< second_base >)
Default constructor, conditionally enabled.
constexpr void swap(compressed_pair &other) noexcept(std::is_nothrow_swappable_v< first_type > &&std::is_nothrow_swappable_v< second_type >)
Swaps two compressed pair objects.
constexpr const second_type & second() const noexcept
Returns the second element that a pair stores.
constexpr compressed_pair & operator=(const compressed_pair &other) noexcept(std::is_nothrow_copy_assignable_v< first_base > &&std::is_nothrow_copy_assignable_v< second_base >)=default
Copy assignment operator.
constexpr compressed_pair(compressed_pair &&other) noexcept(std::is_nothrow_move_constructible_v< first_base > &&std::is_nothrow_move_constructible_v< second_base >)=default
Move constructor.
Second second_type
The type of the second element that the pair stores.
constexpr void swap(compressed_pair< First, Second > &lhs, compressed_pair< First, Second > &rhs)
Swaps two compressed pair objects.
constexpr get_t< Type... > get
Variable template for lists of observed components.