Horizon
tagged_pair.hpp
Go to the documentation of this file.
1 // 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 
23 #include <range/v3/range_fwd.hpp>
24 
25 #include <range/v3/detail/adl_get.hpp>
27 
28 #include <range/v3/detail/prologue.hpp>
29 
30 RANGES_DIAGNOSTIC_PUSH
31 RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
32 
33 namespace 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 
210 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
211 
212 namespace 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 
224 RANGES_DIAGNOSTIC_POP
225 
226 #include <range/v3/detail/epilogue.hpp>
227 
228 #endif
CPP_concept type
\concept type
Definition: concepts.hpp:838
template(typename ActionFn, typename Rng)(concept(invocable_action_closure_)(ActionFn
\concept invocable_action_closure_
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition: meta.hpp:163
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
_t< detail::is_< T, C > > is
is
Definition: meta.hpp:874
Tiny meta-programming library.