Horizon
Loading...
Searching...
No Matches
tagged_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#ifndef RANGES_V3_UTILITY_TAGGED_PAIR_HPP
15#define RANGES_V3_UTILITY_TAGGED_PAIR_HPP
16
17#include <utility>
18
19#include <meta/meta.hpp>
20
21#include <concepts/concepts.hpp>
22
24
25#include <range/v3/detail/adl_get.hpp>
27
28#include <range/v3/detail/prologue.hpp>
29
30RANGES_DIAGNOSTIC_PUSH
31RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
32
33namespace ranges
34{
36 namespace detail
37 {
38 template<typename T>
39 using tag_spec = meta::front<meta::as_list<T>>;
40
41 template<typename T>
42 using tag_elem = meta::back<meta::as_list<T>>;
43
44 template<typename Base, std::size_t, typename...>
45 struct tagged_chain
46 {
47 using type = _tuple_wrapper_::forward_tuple_interface<Base>;
48 };
49 template<typename Base, std::size_t I, typename First, typename... Rest>
50 struct tagged_chain<Base, I, First, Rest...>
51 {
52 using type = typename First::template getter<
53 Base, I, meta::_t<tagged_chain<Base, I + 1, Rest...>>>;
54 };
55 } // namespace detail
56
57#if RANGES_BROKEN_CPO_LOOKUP
58 namespace _tagged_
59 {
60 struct adl_hook_
61 {};
62 } // namespace _tagged_
63#endif
65
66 template<typename Base, typename... Tags>
67 class RANGES_EMPTY_BASES RANGES_DEPRECATED(
68 "Class template tagged is deprecated.") tagged
69 : public meta::_t<detail::tagged_chain<Base, 0, Tags...>>
70#if RANGES_BROKEN_CPO_LOOKUP
71 , private _tagged_::adl_hook_
72#endif
73 {
74 CPP_assert(same_as<Base, uncvref_t<Base>>);
75 using base_t = meta::_t<detail::tagged_chain<Base, 0, Tags...>>;
76
77 template<typename Other>
78 struct can_convert
79 : meta::bool_<!RANGES_IS_SAME(Other, Base) &&
80 detail::is_convertible<Other, Base>::value>
81 {};
82
83 public:
84 tagged() = default;
85 using base_t::base_t;
86 template(typename Other)(
87 requires can_convert<Other>::value) //
88 constexpr tagged(tagged<Other, Tags...> && that) //
89 noexcept(std::is_nothrow_constructible<Base, Other>::value)
90 : base_t(static_cast<Other &&>(that))
91 {}
92 template(typename Other)(
93 requires can_convert<Other>::value) //
94 constexpr tagged(tagged<Other, Tags...> const & that) //
95 noexcept(std::is_nothrow_constructible<Base, Other const &>::value)
96 : base_t(static_cast<Other const &>(that))
97 {}
98 template(typename Other)(
99 requires can_convert<Other>::value) //
100 constexpr tagged & operator=(tagged<Other, Tags...> && that) //
101 noexcept(
102 noexcept(std::declval<Base &>() = static_cast<Other &&>(that)))
103 {
104 static_cast<Base &>(*this) = static_cast<Other &&>(that);
105 return *this;
106 }
107 template(typename Other)(
108 requires can_convert<Other>::value) //
109 constexpr tagged & operator=(tagged<Other, Tags...> const & that) //
110 noexcept(
111 noexcept(std::declval<Base &>() = static_cast<Other const &>(that)))
112 {
113 static_cast<Base &>(*this) = static_cast<Other const &>(that);
114 return *this;
115 }
116 template(typename U)(
117 requires (!same_as<tagged, detail::decay_t<U>>) AND
118 satisfies<Base &, std::is_assignable, U>)
119 constexpr tagged & operator=(U && u) //
120 noexcept(noexcept(std::declval<Base &>() = static_cast<U &&>(u)))
121 {
122 static_cast<Base &>(*this) = static_cast<U &&>(u);
123 return *this;
124 }
125 template(typename B = Base)(
126 requires is_swappable<B>::value) //
127 constexpr void swap(tagged & that) noexcept(is_nothrow_swappable<B>::value)
128 {
129 ranges::swap(static_cast<Base &>(*this), static_cast<Base &>(that));
130 }
131#if !RANGES_BROKEN_CPO_LOOKUP
132 template<typename B = Base>
133 friend constexpr auto swap(tagged & x, tagged & y) //
134 noexcept(is_nothrow_swappable<B>::value)
135 -> CPP_broken_friend_ret(void)(
136 requires is_swappable<B>::value)
137 {
138 x.swap(y);
139 }
140#endif
141 };
142
143#if RANGES_BROKEN_CPO_LOOKUP
144 namespace _tagged_
145 {
146 template(typename Base, typename... Tags)(
147 requires is_swappable<Base>::value) //
148 constexpr void swap(tagged<Base, Tags...> & x, tagged<Base, Tags...> & y) //
149 noexcept(is_nothrow_swappable<Base>::value)
150 {
151 x.swap(y);
152 }
153 } // namespace _tagged_
154#endif
155
156 template<typename F, typename S>
157 using tagged_pair RANGES_DEPRECATED("ranges::tagged_pair is deprecated.") =
158 tagged<std::pair<detail::tag_elem<F>, detail::tag_elem<S>>, detail::tag_spec<F>,
159 detail::tag_spec<S>>;
160
161 template<typename Tag1, typename Tag2, typename T1, typename T2,
162 typename R = tagged_pair<Tag1(bind_element_t<T1>), Tag2(bind_element_t<T2>)>>
163 RANGES_DEPRECATED("ranges::make_tagged_pair is deprecated.")
164 constexpr R make_tagged_pair(T1 && t1, T2 && t2) noexcept(
165 std::is_nothrow_constructible<R, T1, T2>::value)
166 {
167 return {static_cast<T1 &&>(t1), static_cast<T2 &&>(t2)};
168 }
169} // namespace ranges
170
171#define RANGES_DEFINE_TAG_SPECIFIER(NAME) \
172 namespace tag \
173 { \
174 struct NAME \
175 { \
176 template<typename Untagged, std::size_t I, typename Next> \
177 class getter : public Next \
178 { \
179 protected: \
180 ~getter() = default; \
181 \
182 public: \
183 getter() = default; \
184 getter(getter &&) = default; \
185 getter(getter const &) = default; \
186 using Next::Next; \
187 getter & operator=(getter &&) = default; \
188 getter & operator=(getter const &) = default; \
189 constexpr meta::_t<std::tuple_element<I, Untagged>> & NAME() & \
190 noexcept(noexcept(detail::adl_get<I>(std::declval<Untagged &>()))) \
191 { \
192 return detail::adl_get<I>(static_cast<Untagged &>(*this)); \
193 } \
194 constexpr meta::_t<std::tuple_element<I, Untagged>> && NAME() && \
195 noexcept(noexcept(detail::adl_get<I>(std::declval<Untagged>()))) \
196 { \
197 return detail::adl_get<I>(static_cast<Untagged &&>(*this)); \
198 } \
199 constexpr meta::_t<std::tuple_element<I, Untagged>> const & NAME() \
200 const & noexcept( \
201 noexcept(detail::adl_get<I>(std::declval<Untagged const &>()))) \
202 { \
203 return detail::adl_get<I>(static_cast<Untagged const &>(*this)); \
204 } \
205 }; \
206 }; \
207 } \
208
209
210RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
211
212namespace std
213{
214 template<typename Untagged, typename... Tags>
215 struct tuple_size<::ranges::tagged<Untagged, Tags...>> : tuple_size<Untagged>
216 {};
217
218 template<size_t N, typename Untagged, typename... Tags>
219 struct tuple_element<N, ::ranges::tagged<Untagged, Tags...>>
220 : tuple_element<N, Untagged>
221 {};
222} // namespace std
223
224RANGES_DIAGNOSTIC_POP
225
226#include <range/v3/detail/epilogue.hpp>
227
228#endif
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition meta.hpp:168
typename T::type _t
Type alias for T::type.
Definition meta.hpp:141
_t< detail::back_< L > > back
Return the last element in meta::list L.
Definition meta.hpp:2103
_t< detail::front_< L > > front
Return the first element in meta::list L.
Definition meta.hpp:2070
Tiny meta-programming library.