1#ifndef LIBSBX_CONTAINERS_COMPRESSED_PAIR_HPP_
2#define LIBSBX_CONTAINERS_COMPRESSED_PAIR_HPP_
7namespace sbx::containers {
11template<
typename Type>
12struct is_ebco_eligible : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> { };
14template<
typename Type>
17template<
typename Type, std::
size_t,
typename =
void>
22 using value_type = Type;
23 using reference = value_type&;
24 using const_reference =
const value_type&;
26 template<
typename Dummy = value_type,
typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
29 template<
typename Arg,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
31 : _value{std::forward<Arg>(arg)} { }
33 template<
typename... Args, std::size_t... Index>
34 constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
noexcept(std::is_nothrow_constructible_v<value_type, Args...>)
35 : _value{std::forward<Args>(std::get<Index>(args))...} { }
37 [[nodiscard]]
constexpr auto get()
noexcept -> reference {
41 [[nodiscard]]
constexpr auto get()
const noexcept -> const_reference {
51template<
typename Type, std::
size_t Tag>
56 using value_type = Type;
57 using reference = value_type&;
58 using const_reference =
const value_type&;
59 using base_type = Type;
61 template<
typename Dummy = value_type,
typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
65 template<
typename Arg,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
67 : base_type{std::forward<Arg>(arg)} { }
69 template<
typename... Args, std::size_t... Index>
70 constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>)
noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
71 : base_type{std::forward<Args>(std::get<Index>(args))...} {}
73 [[nodiscard]]
constexpr auto get()
noexcept -> reference {
77 [[nodiscard]]
constexpr auto get()
const noexcept -> const_reference {
85template<
typename First,
typename Second>
93 using first_type = First;
94 using second_type = Second;
96 template<
bool Dummy = true,
typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
97 constexpr compressed_pair()
noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
105 template<
typename Arg,
typename Other>
106 constexpr compressed_pair(Arg&& arg, Other&& other)
noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
110 template<
typename... Args,
typename... Other>
111 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...>)
112 :
first_base{std::move(args), std::index_sequence_for<Args...>{}},
113 second_base{std::move(other), std::index_sequence_for<Other...>{}} { }
121 [[nodiscard]]
constexpr auto first()
noexcept -> first_type& {
125 [[nodiscard]]
constexpr auto first()
const noexcept ->
const first_type& {
126 return static_cast<const first_base&
>(*this).get();
129 [[nodiscard]]
constexpr auto second()
noexcept -> second_type& {
133 [[nodiscard]]
constexpr auto second()
const noexcept ->
const second_type& {
134 return static_cast<const second_base&
>(*this).get();
139 swap(first(), other.first());
140 swap(second(), other.second());
142 template<std::
size_t Index>
143 [[nodiscard]]
constexpr auto get()
noexcept ->
decltype(
auto) {
144 if constexpr (Index == 0u) {
147 static_assert(Index == 1u,
"Index out of bounds");
153 template<std::
size_t Index>
154 [[nodiscard]]
constexpr auto get() const noexcept -> decltype(auto) {
155 if constexpr (Index == 0u) {
158 static_assert(Index == 1u,
"Index out of bounds");
165template<
typename Type,
typename Other>
166compressed_pair(Type&&, Other&&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
168template<
typename First,
typename Second>
169constexpr auto swap(compressed_pair<First, Second>& lhs, compressed_pair<First, Second>& rhs)
noexcept ->
void {
175template<
typename First,
typename Second>
176struct std::tuple_size<sbx::containers::compressed_pair<First, Second>> : std::integral_constant<std::size_t, 2u> { };
178template<std::
size_t Index,
typename First,
typename Second>
179struct std::tuple_element<Index, sbx::containers::compressed_pair<First, Second>> : std::conditional<Index == 0u, First, Second> {
180 static_assert(Index < 2u,
"Index out of bounds");
Definition: compressed_pair.hpp:86
constexpr auto get() const noexcept -> decltype(auto)
Definition: compressed_pair.hpp:154
Definition: compressed_pair.hpp:18
Definition: compressed_pair.hpp:12