EnTT 3.13.0
Loading...
Searching...
No Matches
compressed_pair.hpp
1#ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
2#define ENTT_CORE_COMPRESSED_PAIR_HPP
3
4#include <cstddef>
5#include <tuple>
6#include <type_traits>
7#include <utility>
8#include "type_traits.hpp"
9
10namespace entt {
11
13namespace internal {
14
15template<typename Type, std::size_t, typename = void>
16struct compressed_pair_element {
17 using reference = Type &;
18 using const_reference = const Type &;
19
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>)
22 : value{} {}
23
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)} {}
27
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))...} {}
31
32 [[nodiscard]] constexpr reference get() noexcept {
33 return value;
34 }
35
36 [[nodiscard]] constexpr const_reference get() const noexcept {
37 return value;
38 }
39
40private:
41 Type value;
42};
43
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;
49
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>)
52 : base_type{} {}
53
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)} {}
57
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))...} {}
61
62 [[nodiscard]] constexpr reference get() noexcept {
63 return *this;
64 }
65
66 [[nodiscard]] constexpr const_reference get() const noexcept {
67 return *this;
68 }
69};
70
71} // namespace internal
83template<typename First, typename Second>
84class compressed_pair final
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>;
89
90public:
92 using first_type = First;
94 using second_type = Second;
95
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>)
106 : first_base{},
107 second_base{} {}
108
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;
114
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;
120
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)} {}
132
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...>{}} {}
144
150 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;
151
157 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;
158
163 [[nodiscard]] constexpr first_type &first() noexcept {
164 return static_cast<first_base &>(*this).get();
165 }
166
168 [[nodiscard]] constexpr const first_type &first() const noexcept {
169 return static_cast<const first_base &>(*this).get();
170 }
171
176 [[nodiscard]] constexpr second_type &second() noexcept {
177 return static_cast<second_base &>(*this).get();
178 }
179
181 [[nodiscard]] constexpr const second_type &second() const noexcept {
182 return static_cast<const second_base &>(*this).get();
183 }
184
189 constexpr void swap(compressed_pair &other) noexcept(std::is_nothrow_swappable_v<first_type> &&std::is_nothrow_swappable_v<second_type>) {
190 using std::swap;
191 swap(first(), other.first());
192 swap(second(), other.second());
193 }
194
201 template<std::size_t Index>
202 constexpr decltype(auto) get() noexcept {
203 if constexpr(Index == 0u) {
204 return first();
205 } else {
206 static_assert(Index == 1u, "Index out of bounds");
207 return second();
208 }
209 }
210
212 template<std::size_t Index>
213 constexpr decltype(auto) get() const noexcept {
214 if constexpr(Index == 0u) {
215 return first();
216 } else {
217 static_assert(Index == 1u, "Index out of bounds");
218 return second();
219 }
220 }
221};
222
228template<typename Type, typename Other>
229compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
230
238template<typename First, typename Second>
240 lhs.swap(rhs);
241}
242
243} // namespace entt
244
245// disable structured binding support for clang 6, it messes when specializing tuple_size
246#if !defined __clang_major__ || __clang_major__ > 6
247namespace std {
248
254template<typename First, typename Second>
255struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
256
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");
266};
267
268} // namespace std
269#endif
270
271#endif
A compressed pair.
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.
EnTT default namespace.
Definition dense_map.hpp:21
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.
Definition fwd.hpp:157