2#ifndef LIBSBX_CONTAINERS_COMPRESSED_PAIR_HPP_
3#define LIBSBX_CONTAINERS_COMPRESSED_PAIR_HPP_
8namespace sbx::containers {
12template<
typename Type>
13struct is_ebco_eligible : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> { };
15template<
typename Type>
18template<
typename Type, std::
size_t,
typename =
void>
23 using value_type = Type;
24 using reference = value_type&;
25 using const_reference =
const value_type&;
27 template<
typename Dummy = value_type,
typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
30 template<
typename Arg,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
32 : _value{std::forward<Arg>(arg)} { }
34 template<
typename... Args, std::size_t... Index>
35 constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
noexcept(std::is_nothrow_constructible_v<value_type, Args...>)
36 : _value{std::forward<Args>(std::get<Index>(args))...} { }
38 [[nodiscard]]
constexpr auto get()
noexcept -> reference {
42 [[nodiscard]]
constexpr auto get()
const noexcept -> const_reference {
52template<
typename Type, std::
size_t Tag>
57 using value_type = Type;
58 using reference = value_type&;
59 using const_reference =
const value_type&;
60 using base_type = Type;
62 template<
typename Dummy = value_type,
typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
66 template<
typename Arg,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
68 : base_type{std::forward<Arg>(arg)} { }
70 template<
typename... Args, std::size_t... Index>
71 constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
72 : base_type{std::forward<Args>(std::get<Index>(args))...} {}
74 [[nodiscard]]
constexpr auto get()
noexcept -> reference {
78 [[nodiscard]]
constexpr auto get()
const noexcept -> const_reference {
86template<
typename First,
typename Second>
94 using first_type = First;
95 using second_type = Second;
97 template<
bool Dummy = true,
typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
98 constexpr compressed_pair()
noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
106 template<
typename Arg,
typename Other>
107 constexpr compressed_pair(Arg&& arg, Other&& other)
noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
111 template<
typename... Args,
typename... Other>
112 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...>)
113 :
first_base{std::move(args), std::index_sequence_for<Args...>{}},
114 second_base{std::move(other), std::index_sequence_for<Other...>{}} { }
122 [[nodiscard]]
constexpr auto first()
noexcept -> first_type& {
126 [[nodiscard]]
constexpr auto first()
const noexcept ->
const first_type& {
127 return static_cast<const first_base&
>(*this).get();
130 [[nodiscard]]
constexpr auto second()
noexcept -> second_type& {
134 [[nodiscard]]
constexpr auto second()
const noexcept ->
const second_type& {
135 return static_cast<const second_base&
>(*this).get();
140 swap(first(), other.first());
141 swap(second(), other.second());
143 template<std::
size_t Index>
144 [[nodiscard]]
constexpr auto get()
noexcept ->
decltype(
auto) {
145 if constexpr (Index == 0u) {
148 static_assert(Index == 1u,
"Index out of bounds");
154 template<std::
size_t Index>
155 [[nodiscard]]
constexpr auto get() const noexcept -> decltype(auto) {
156 if constexpr (Index == 0u) {
159 static_assert(Index == 1u,
"Index out of bounds");
166template<
typename Type,
typename Other>
167compressed_pair(Type&&, Other&&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
169template<
typename First,
typename Second>
170constexpr auto swap(compressed_pair<First, Second>& lhs, compressed_pair<First, Second>& rhs)
noexcept ->
void {
176template<
typename First,
typename Second>
177struct std::tuple_size<sbx::containers::compressed_pair<First, Second>> : std::integral_constant<std::size_t, 2u> { };
179template<std::
size_t Index,
typename First,
typename Second>
180struct std::tuple_element<Index, sbx::containers::compressed_pair<First, Second>> : std::conditional<Index == 0u, First, Second> {
181 static_assert(Index < 2u,
"Index out of bounds");
Definition: compressed_pair.hpp:87
constexpr auto get() const noexcept -> decltype(auto)
Definition: compressed_pair.hpp:155
Definition: compressed_pair.hpp:19
Definition: compressed_pair.hpp:13