Horizon
Loading...
Searching...
No Matches
compressed_pair.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Eric Niebler 2013-present
5// Copyright Casey Carter 2016
6//
7// Use, modification and distribution is subject to the
8// Boost Software License, Version 1.0. (See accompanying
9// file LICENSE_1_0.txt or copy at
10// http://www.boost.org/LICENSE_1_0.txt)
11//
12// Project home: https://github.com/ericniebler/range-v3
13//
14
15#ifndef RANGES_V3_UTILITY_COMPRESSED_PAIR_HPP
16#define RANGES_V3_UTILITY_COMPRESSED_PAIR_HPP
17
18#include <type_traits>
19#include <utility>
20
21#include <meta/meta.hpp>
22
23#include <concepts/concepts.hpp>
24
26
28#include <range/v3/utility/static_const.hpp>
29
30#include <range/v3/detail/prologue.hpp>
31
32namespace ranges
33{
35 namespace compressed_tuple_detail
36 {
37 // tagging individual elements with the complete type list disambiguates
38 // base classes when composing compressed_tuples recursively.
39 template<typename T, std::size_t I, typename... Ts>
40 using storage = box<T, meta::list<meta::size_t<I>, Ts...>>;
41
42 template<typename List, typename Indices>
43 struct compressed_tuple_;
44 template<typename... Ts, std::size_t... Is>
45 struct RANGES_EMPTY_BASES
46 compressed_tuple_<meta::list<Ts...>, meta::index_sequence<Is...>>
47 : storage<Ts, Is, Ts...>...
48 {
49 static_assert(same_as<meta::index_sequence<Is...>,
50 meta::make_index_sequence<sizeof...(Is)>>,
51 "What madness is this?!?");
52
53 compressed_tuple_() = default;
54
55 template<typename... Args,
56 meta::if_<meta::and_c<META_IS_CONSTRUCTIBLE(Ts, Args)...>, int> = 0>
57 constexpr compressed_tuple_(Args &&... args) noexcept(
58 meta::strict_and<std::is_nothrow_constructible<storage<Ts, Is, Ts...>,
59 Args>...>::value)
60 : storage<Ts, Is, Ts...>{static_cast<Args &&>(args)}...
61 {}
62
63 template<
64 typename... Us,
65 meta::if_<meta::and_c<META_IS_CONSTRUCTIBLE(Us, Ts const &)...>, int> = 0>
66 constexpr operator std::tuple<Us...>() const noexcept(
67 meta::strict_and<std::is_nothrow_constructible<Us, Ts const &>...>::value)
68 {
69 return std::tuple<Us...>{get<Is>(*this)...};
70 }
71
72 template<std::size_t I, typename T = meta::at_c<meta::list<Ts...>, I>>
73 friend constexpr T & get(compressed_tuple_ & tuple) noexcept
74 {
75 return static_cast<storage<T, I, Ts...> &>(tuple).get();
76 }
77 template<std::size_t I, typename T = meta::at_c<meta::list<Ts...>, I>>
78 friend constexpr T const & get(compressed_tuple_ const & tuple) noexcept
79 {
80 return static_cast<storage<T, I, Ts...> const &>(tuple).get();
81 }
82 template<std::size_t I, typename T = meta::at_c<meta::list<Ts...>, I>>
83 friend constexpr T && get(compressed_tuple_ && tuple) noexcept
84 {
85 return static_cast<storage<T, I, Ts...> &&>(tuple).get();
86 }
87 template<std::size_t I, typename T = meta::at_c<meta::list<Ts...>, I>>
88 friend constexpr T const && get(compressed_tuple_ const && tuple) noexcept
89 {
90 return static_cast<storage<T, I, Ts...> const &&>(tuple).get();
91 }
92 };
93
94 template<typename... Ts>
95 using compressed_tuple RANGES_DEPRECATED(
96 "ranges::compressed_tuple is deprecated.") =
97 compressed_tuple_<meta::list<Ts...>,
98 meta::make_index_sequence<sizeof...(Ts)>>;
99 } // namespace compressed_tuple_detail
101
102 using compressed_tuple_detail::compressed_tuple;
103
105 {
106 // clang-format off
107 template<typename... Args>
108 constexpr auto CPP_auto_fun(operator())(Args &&... args) (const)
109 (
110 return compressed_tuple<bind_element_t<Args>...>{
111 static_cast<Args &&>(args)...}
112 )
113 // clang-format on
114 };
115
118 RANGES_INLINE_VARIABLE(make_compressed_tuple_fn, make_compressed_tuple)
119
120 template<typename First, typename Second>
121 struct RANGES_EMPTY_BASES compressed_pair
122 : box<First, meta::size_t<0>>
123 , box<Second, meta::size_t<1>>
124 {
125 using first_type = First;
126 using second_type = Second;
127
128 compressed_pair() = default;
129
130 template(typename U, typename V)(
131 requires constructible_from<First, U> AND constructible_from<Second, V>)
132 constexpr compressed_pair(U && u, V && v) //
133 noexcept(noexcept(First((U &&) u)) && noexcept(Second((V &&) v)))
134 : box<First, meta::size_t<0>>{(U &&) u}
135 , box<Second, meta::size_t<1>>{(V &&) v}
136 {}
137
138 constexpr First & first() &
139 {
140 return this->box<First, meta::size_t<0>>::get();
141 }
142 constexpr First const & first() const &
143 {
144 return this->box<First, meta::size_t<0>>::get();
145 }
146 constexpr First && first() &&
147 {
148 return static_cast<First &&>(this->box<First, meta::size_t<0>>::get());
149 }
150
151 constexpr Second & second() &
152 {
153 return this->box<Second, meta::size_t<1>>::get();
154 }
155 constexpr Second const & second() const &
156 {
157 return this->box<Second, meta::size_t<1>>::get();
158 }
159 constexpr Second && second() &&
160 {
161 return static_cast<Second &&>(this->box<Second, meta::size_t<1>>::get());
162 }
163
164 template(typename F, typename S)(
165 requires convertible_to<First const &, F> AND
166 convertible_to<Second const &, S>)
167 constexpr
168 operator std::pair<F, S>() const
169 {
170 return std::pair<F, S>{first(), second()};
171 }
172 };
173
175 {
176 // clang-format off
177 template<typename First, typename Second>
178 constexpr auto CPP_auto_fun(operator())(First &&f, Second &&s) (const)
179 (
180 return compressed_pair<bind_element_t<First>, bind_element_t<Second>>{
181 static_cast<First &&>(f), static_cast<Second &&>(s)
182 }
183 )
184 // clang-format on
185 };
186
189 RANGES_INLINE_VARIABLE(make_compressed_pair_fn, make_compressed_pair)
190} // namespace ranges
191
192RANGES_DIAGNOSTIC_PUSH
193RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
194namespace std
195{
196 template<typename... Ts, size_t... Is>
197 struct tuple_size<::ranges::compressed_tuple_detail::compressed_tuple_<
198 ::meta::list<Ts...>, ::meta::index_sequence<Is...>>>
199 : integral_constant<size_t, sizeof...(Ts)>
200 {};
201
202 template<size_t I, typename... Ts, size_t... Is>
203 struct tuple_element<I, ::ranges::compressed_tuple_detail::compressed_tuple_<
204 ::meta::list<Ts...>, ::meta::index_sequence<Is...>>>
205 {
206 using type = ::meta::at_c<::meta::list<Ts...>, I>;
207 };
208
209 template<typename First, typename Second>
210 struct tuple_size<::ranges::compressed_pair<First, Second>>
211 : integral_constant<size_t, 2>
212 {};
213
214 template<typename First, typename Second>
215 struct tuple_element<0, ::ranges::compressed_pair<First, Second>>
216 {
217 using type = First;
218 };
219
220 template<typename First, typename Second>
221 struct tuple_element<1, ::ranges::compressed_pair<First, Second>>
222 {
223 using type = Second;
224 };
225} // namespace std
226RANGES_DIAGNOSTIC_POP
227
228#include <range/v3/detail/epilogue.hpp>
229
230#endif
Definition box.hpp:163
_t< detail::make_indices_< N, index_sequence< 0 >, detail::strategy_(1, N)> > make_index_sequence
Generate index_sequence containing integer constants [0,1,2,...,N-1].
Definition meta.hpp:473
_t< detail::at_< L, N > > at_c
Return the N th element in the meta::list L.
Definition meta.hpp:1962
_t< detail::_if_< list< Args... > > > if_
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1247
Tiny meta-programming library.
Tiny metaprogramming library.
Definition meta.hpp:116
Definition meta.hpp:1383
A container for a sequence of compile-time integer constants.
Definition meta.hpp:434
A list of types.
Definition meta.hpp:1684
Definition compressed_pair.hpp:124
Definition compressed_pair.hpp:175
Definition compressed_pair.hpp:105