VCCC  2024.05
VisualCamp Common C++ library
compressed_pair.hpp
Go to the documentation of this file.
1 # /*
2 # * Created by YongGyu Lee on 2021/11/14.
3 # */
4 #
5 # ifndef VCCC_UTILITY_COMPRESSED_PAIR_HPP
6 # define VCCC_UTILITY_COMPRESSED_PAIR_HPP
7 #
8 # include <cstddef>
9 # include <type_traits>
10 # include <utility>
11 #
15 
16 namespace vccc {
17 
18 namespace detail {
19 
21 struct compressed_slot {
22  constexpr compressed_slot() = default;
23 
24  template<typename U, std::enable_if_t<std::is_same<std::decay_t<U>, compressed_slot>::value == false, int> = 0>
25  constexpr compressed_slot(U&& u) : value_(std::forward<U>(u)) {}
26 
27  template<std::size_t I> constexpr std::enable_if_t<(I == index), T&> get() & noexcept { return value_; }
28  template<std::size_t I> constexpr std::enable_if_t<(I == index), T&&> get() && noexcept { return std::move(value_); }
29  template<std::size_t I> constexpr std::enable_if_t<(I == index), const T&> get() const & noexcept { return value_; }
30  template<std::size_t I> constexpr std::enable_if_t<(I == index), const T&&> get() const && noexcept { return std::move(value_); }
31 
32  private:
33  T value_;
34 };
35 
36 template<typename T, std::size_t index>
37 struct compressed_slot<T, index, true> : public T {
38  constexpr compressed_slot() = default;
39 
40  template<typename U, std::enable_if_t<std::is_same<std::decay_t<U>, compressed_slot>::value == false, int> = 0>
41  constexpr compressed_slot(U&& u) : T(std::forward<U>(u)) {}
42 
43  template<std::size_t I> constexpr std::enable_if_t<(I == index), T&> get() & noexcept { return static_cast<T&>(*this); }
44  template<std::size_t I> constexpr std::enable_if_t<(I == index), T&&> get() && noexcept { return static_cast<T&&>(*this); }
45  template<std::size_t I> constexpr std::enable_if_t<(I == index), const T&> get() const & noexcept { return static_cast<const T&>(*this); }
46  template<std::size_t I> constexpr std::enable_if_t<(I == index), const T&&> get() const && noexcept { return static_cast<const T&&>(*this); }
47 };
48 
49 } // namespace detail
50 
53 
56 
57 
59 template<typename T, typename U>
60 class compressed_pair : public detail::compressed_slot<T, 0>, public detail::compressed_slot<U, 1> {
61  private:
62  using first_base = detail::compressed_slot<T, 0>;
63  using second_base = detail::compressed_slot<U, 1>;
64 
65  public:
66  using first_type = T;
67  using second_type = U;
68  using first_base::get;
69  using second_base::get;
70 
71  constexpr compressed_pair() = default;
72 
74  constexpr compressed_pair(T2&& t, compressed_pair_empty_t) : first_base(std::forward<T2>(t)) {}
75 
77  constexpr compressed_pair(compressed_pair_empty_t, U2&& u) : second_base(std::forward<U2>(u)) {}
78 
79  template<typename T2, typename U2, std::enable_if_t<conjunction<
80  std::is_constructible<T, T2>,
81  std::is_constructible<U, U2>
82  >::value, int> = 0>
83  constexpr compressed_pair(T2&& t, U2&& u) : first_base(std::forward<T2>(t)), second_base(std::forward<U2>(u)) {}
84 
85  constexpr T& first() & noexcept { return first_base::template get<0>(); }
86  constexpr T&& first() && noexcept { return std::move(first_base::template get<0>()); }
87  constexpr const T& first() const & noexcept { return first_base::template get<0>(); }
88  constexpr const T&& first() const && noexcept { return std::move(first_base::template get<0>()); }
89 
90  constexpr U& second() & noexcept { return second_base::template get<1>(); }
91  constexpr U&& second() && noexcept { return std::move(second_base::template get<1>()); }
92  constexpr const U& second() const & noexcept { return second_base::template get<1>(); }
93  constexpr const U&& second() const && noexcept { return std::move(second_base::template get<1>()); }
94 
95  constexpr std::enable_if_t<conjunction<is_swappable<T>, is_swappable<U>>::value>
98  {
99  using std::swap;
100  swap(first(), other.first());
101  swap(second(), other.second());
102  }
103 };
104 
105 
106 template<typename T, typename U>
107 constexpr std::enable_if_t<conjunction<is_swappable<T>, is_swappable<U>>::value>
110 {
111  lhs.swap(rhs);
112 }
113 
115 
116 namespace detail {
117 
118 template<std::size_t I> struct compressed_pair_getter;
119 template<>
120 struct compressed_pair_getter<0> {
121  template<typename T, typename U> static constexpr T& get(compressed_pair<T, U>& p) noexcept { return p.first(); }
122  template<typename T, typename U> static constexpr const T& get(const compressed_pair<T, U>& p) noexcept { return p.first(); }
123  template<typename T, typename U> static constexpr T&& get(compressed_pair<T, U>&& p) noexcept { return std::move(p.first()); }
124  template<typename T, typename U> static constexpr const T&& get(const compressed_pair<T, U>&& p) noexcept { return std::move(p.first()); }
125 };
126 template<>
127 struct compressed_pair_getter<1> {
128  template<typename T, typename U> static constexpr U& get(compressed_pair<T, U>& p) noexcept { return p.second(); }
129  template<typename T, typename U> static constexpr const U& get(const compressed_pair<T, U>& p) noexcept { return p.second(); }
130  template<typename T, typename U> static constexpr U&& get(compressed_pair<T, U>&& p) noexcept { return std::move(p.second()); }
131  template<typename T, typename U> static constexpr const U&& get(const compressed_pair<T, U>&& p) noexcept { return std::move(p.second()); }
132 };
133 
134 } // namespace detail
135 
136 } // namespace vccc
137 
138 namespace std {
139 
140 template<typename T, typename U> struct tuple_element<0, vccc::compressed_pair<T, U>> { using type = T; };
141 template<typename T, typename U> struct tuple_element<1, vccc::compressed_pair<T, U>> { using type = U; };
142 template<typename T, typename U> struct tuple_size<vccc::compressed_pair<T, U>> : std::integral_constant<std::size_t, 2> {};
143 
144 template<std::size_t I, typename T, typename U>
145 constexpr tuple_element_t<I, vccc::compressed_pair<T, U>>& get(vccc::compressed_pair<T, U>& p) noexcept {
147 }
148 template<std::size_t I, typename T, typename U>
149 constexpr const tuple_element_t<I, vccc::compressed_pair<T, U>>& get(const vccc::compressed_pair<T, U>& p) noexcept {
151 }
152 template<std::size_t I, typename T, typename U>
153 constexpr tuple_element_t<I, vccc::compressed_pair<T, U>>&& get(vccc::compressed_pair<T, U>&& p) noexcept {
155 }
156 template<std::size_t I, typename T, typename U>
157 constexpr const tuple_element_t<I, vccc::compressed_pair<T, U>>&& get(const vccc::compressed_pair<T, U>&& p) noexcept {
159 }
160 
161 template<typename T, typename U> constexpr T& get(vccc::compressed_pair<T, U>& p) noexcept { return p.first(); }
162 template<typename T, typename U> constexpr const T& get(const vccc::compressed_pair<T, U>& p) noexcept { return p.first(); }
163 template<typename T, typename U> constexpr T&& get(vccc::compressed_pair<T, U>&& p) noexcept { return std::move(p.first()); }
164 template<typename T, typename U> constexpr const T&& get(const vccc::compressed_pair<T, U>&& p) noexcept { return std::move(p.first()); }
165 
166 template<typename T, typename U> constexpr T& get(vccc::compressed_pair<U, T>& p) noexcept { return p.second(); }
167 template<typename T, typename U> constexpr const T& get(const vccc::compressed_pair<U, T>& p) noexcept { return p.second(); }
168 template<typename T, typename U> constexpr T&& get(vccc::compressed_pair<U, T>&& p) noexcept { return std::move(p.second()); }
169 template<typename T, typename U> constexpr const T&& get(const vccc::compressed_pair<U, T>&& p) noexcept { return std::move(p.second()); }
170 
171 // template<std::size_t I, typename T, typename U>
172 
173 
174 } // namespace std
175 
176 #endif // VCCC_UTILITY_COMPRESSED_PAIR_HPP
An size-optimized pair using empty base optimization.
Definition: compressed_pair.hpp:60
constexpr T & first() &noexcept
Definition: compressed_pair.hpp:85
constexpr compressed_pair()=default
constexpr const U && second() const &&noexcept
Definition: compressed_pair.hpp:93
constexpr compressed_pair(compressed_pair_empty_t, U2 &&u)
Definition: compressed_pair.hpp:77
constexpr compressed_pair(T2 &&t, compressed_pair_empty_t)
Definition: compressed_pair.hpp:74
constexpr compressed_pair(T2 &&t, U2 &&u)
Definition: compressed_pair.hpp:83
constexpr std::enable_if_t< conjunction< is_swappable< T >, is_swappable< U > >::value > swap(compressed_pair &other) noexcept(conjunction< is_nothrow_swappable< T >, is_nothrow_swappable< U >>::value)
Definition: compressed_pair.hpp:96
constexpr U && second() &&noexcept
Definition: compressed_pair.hpp:91
constexpr const U & second() const &noexcept
Definition: compressed_pair.hpp:92
U second_type
Definition: compressed_pair.hpp:67
constexpr T && first() &&noexcept
Definition: compressed_pair.hpp:86
constexpr U & second() &noexcept
Definition: compressed_pair.hpp:90
constexpr const T && first() const &&noexcept
Definition: compressed_pair.hpp:88
T first_type
Definition: compressed_pair.hpp:66
constexpr const T & first() const &noexcept
Definition: compressed_pair.hpp:87
void swap(::vccc::optional< T > &lhs, ::vccc::optional< T > &rhs) noexcept(noexcept(lhs.swap(rhs)))
Definition: swap.h:30
constexpr std::enable_if_t< conjunction< is_swappable< T >, is_swappable< U > >::value > swap(compressed_pair< T, U > &lhs, compressed_pair< T, U > &rhs) noexcept(conjunction< is_nothrow_swappable< T >, is_nothrow_swappable< U >>::value)
Definition: compressed_pair.hpp:108
constexpr VCCC_INLINE_OR_STATIC compressed_pair_empty_t compressed_pair_empty
Definition: compressed_pair.hpp:55
constexpr variant_alternative_t< I, variant< Types... > > & get(variant< Types... > &v)
Definition: variant.hpp:770
#define VCCC_INLINE_OR_STATIC
Definition: inline_or_static.hpp:9
Definition: matrix.hpp:495
constexpr std::enable_if_t<(I< m *n), typename vccc::Matrix< T, m, n >::value_type & > get(vccc::Matrix< T, m, n > &matrix)
Definition: matrix.hpp:499
constexpr const T && get(const vccc::compressed_pair< U, T > &&p) noexcept
Definition: compressed_pair.hpp:169
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
T type
Definition: compressed_pair.hpp:140
U type
Definition: compressed_pair.hpp:141
Definition: compressed_pair.hpp:54
Definition: conjunction.hpp:22
Definition: is_swappable.hpp:125
Definition: is_swappable.hpp:119