EnTT: src/entt/core/compressed_pair.hpp Source File

EnTT 3.16.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 "fwd.hpp"
9#include "type_traits.hpp"
10
11namespace entt {
12
14namespace internal {
15
16template<typename Type, std::size_t, typename = void>
17struct compressed_pair_element {
18 using reference = Type &;
19 using const_reference = const Type &;
20
21 template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
22 // NOLINTNEXTLINE(modernize-use-equals-default)
23 constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
24
25 template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
26 constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
27 : value{std::forward<Arg>(arg)} {}
28
29 template<typename... Args, std::size_t... Index>
30 constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
31 : value{std::forward<Args>(std::get<Index>(args))...} {}
32
33 [[nodiscard]] constexpr reference get() noexcept {
34 return value;
35 }
36
37 [[nodiscard]] constexpr const_reference get() const noexcept {
38 return value;
39 }
40
41private:
42 Type value{};
43};
44
45template<typename Type, std::size_t Tag>
46struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
47 using reference = Type &;
48 using const_reference = const Type &;
49 using base_type = Type;
50
51 template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
52 constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
53 : base_type{} {}
54
55 template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
56 constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
57 : base_type{std::forward<Arg>(arg)} {}
58
59 template<typename... Args, std::size_t... Index>
60 constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
61 : base_type{std::forward<Args>(std::get<Index>(args))...} {}
62
63 [[nodiscard]] constexpr reference get() noexcept {
64 return *this;
65 }
66
67 [[nodiscard]] constexpr const_reference get() const noexcept {
68 return *this;
69 }
70};
71
72} // namespace internal
74
84template<typename First, typename Second>
85 class compressed_pair final
86 : internal::compressed_pair_element<First, 0u>,
87 internal::compressed_pair_element<Second, 1u> {
88 using first_base = internal::compressed_pair_element<First, 0u>;
89 using second_base = internal::compressed_pair_element<Second, 1u>;
90
91public:
93 using first_type = First;
95 using second_type = Second;
96
105 template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
106 constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
107 : first_base{},
108 second_base{} {}
109
114 constexpr compressed_pair(const compressed_pair &other) = default;
115
120 constexpr compressed_pair(compressed_pair &&other) noexcept = default;
121
129 template<typename Arg, typename Other>
130 constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
131 : first_base{std::forward<Arg>(arg)},
132 second_base{std::forward<Other>(other)} {}
133
141 template<typename... Args, typename... Other>
142 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...>)
143 : first_base{std::move(args), std::index_sequence_for<Args...>{}},
144 second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
145
147 ~compressed_pair() = default;
148
154 constexpr compressed_pair &operator=(const compressed_pair &other) = default;
155
161 constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
162
167 [[nodiscard]] constexpr first_type &first() noexcept {
168 return static_cast<first_base &>(*this).get();
169 }
170
172 [[nodiscard]] constexpr const first_type &first() const noexcept {
173 return static_cast<const first_base &>(*this).get();
174 }
175
180 [[nodiscard]] constexpr second_type &second() noexcept {
181 return static_cast<second_base &>(*this).get();
182 }
183
185 [[nodiscard]] constexpr const second_type &second() const noexcept {
186 return static_cast<const second_base &>(*this).get();
187 }
188
193 constexpr void swap(compressed_pair &other) noexcept {
194 using std::swap;
195 swap(first(), other.first());
196 swap(second(), other.second());
197 }
198
205 template<std::size_t Index>
206 [[nodiscard]] constexpr decltype(auto) get() noexcept {
207 if constexpr(Index == 0u) {
208 return first();
209 } else {
210 static_assert(Index == 1u, "Index out of bounds");
211 return second();
212 }
213 }
214
216 template<std::size_t Index>
217 [[nodiscard]] constexpr decltype(auto) get() const noexcept {
218 if constexpr(Index == 0u) {
219 return first();
220 } else {
221 static_assert(Index == 1u, "Index out of bounds");
222 return second();
223 }
224 }
225};
226
232template<typename Type, typename Other>
233 compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
234
242template<typename First, typename Second>
243 constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
244 lhs.swap(rhs);
245}
246
247} // namespace entt
248
249namespace std {
250
256template<typename First, typename Second>
257 struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
258
265template<size_t Index, typename First, typename Second>
266 struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
267 static_assert(Index < 2u, "Index out of bounds");
268};
269
270} // namespace std
271
272#endif
entt::compressed_pair
A compressed pair.
Definition compressed_pair.hpp:87
entt::compressed_pair::second
constexpr second_type & second() noexcept
Returns the second element that a pair stores.
Definition compressed_pair.hpp:180
entt::compressed_pair::swap
constexpr void swap(compressed_pair &other) noexcept
Swaps two compressed pair objects.
Definition compressed_pair.hpp:193
entt::compressed_pair::first
constexpr const first_type & first() const noexcept
Returns the first element that a pair stores.
Definition compressed_pair.hpp:172
entt::compressed_pair::compressed_pair
constexpr compressed_pair(compressed_pair &&other) noexcept=default
Move constructor.
entt::compressed_pair::compressed_pair
constexpr compressed_pair(const compressed_pair &other)=default
Copy constructor.
entt::compressed_pair::compressed_pair
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.
Definition compressed_pair.hpp:130
entt::compressed_pair::get
constexpr decltype(auto) get() const noexcept
Extracts an element from the compressed pair.
Definition compressed_pair.hpp:217
entt::compressed_pair::get
constexpr decltype(auto) get() noexcept
Extracts an element from the compressed pair.
Definition compressed_pair.hpp:206
entt::compressed_pair::first
constexpr first_type & first() noexcept
Returns the first element that a pair stores.
Definition compressed_pair.hpp:167
entt::compressed_pair::compressed_pair
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.
Definition compressed_pair.hpp:142
entt::compressed_pair::first_type
First first_type
The type of the first element that the pair stores.
Definition compressed_pair.hpp:93
entt::compressed_pair::compressed_pair
constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v< first_base > &&std::is_nothrow_default_constructible_v< second_base >)
Default constructor, conditionally enabled.
Definition compressed_pair.hpp:106
entt::compressed_pair::operator=
constexpr compressed_pair & operator=(const compressed_pair &other)=default
Copy assignment operator.
entt::compressed_pair::~compressed_pair
~compressed_pair()=default
Default destructor.
entt::compressed_pair::second
constexpr const second_type & second() const noexcept
Returns the second element that a pair stores.
Definition compressed_pair.hpp:185
entt::compressed_pair::second_type
Second second_type
The type of the second element that the pair stores.
Definition compressed_pair.hpp:95
entt::compressed_pair::operator=
constexpr compressed_pair & operator=(compressed_pair &&other) noexcept=default
Move assignment operator.
entt
EnTT default namespace.
Definition dense_map.hpp:22
entt::swap
constexpr void swap(compressed_pair< First, Second > &lhs, compressed_pair< First, Second > &rhs) noexcept
Swaps two compressed pair objects.
Definition compressed_pair.hpp:243
entt::get
constexpr get_t< Type... > get
Variable template for lists of observed elements.
Definition fwd.hpp:167