Horizon
adl_get.hpp
1 // Range v3 library
2 //
3 // Copyright Casey Carter 2018
4 //
5 // Use, modification and distribution is subject to the
6 // Boost Software License, Version 1.0. (See accompanying
7 // file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 //
10 // Project home: https://github.com/ericniebler/range-v3
11 
12 #ifndef RANGES_V3_DETAIL_ADL_GET_HPP
13 #define RANGES_V3_DETAIL_ADL_GET_HPP
14 
15 #include <cstddef>
16 
17 #include <concepts/concepts.hpp>
18 
19 #include <range/v3/range_fwd.hpp>
20 
21 #include <range/v3/detail/prologue.hpp>
22 
23 namespace ranges
24 {
26  namespace detail
27  {
28  namespace _adl_get_
29  {
30  template<typename>
31  void get();
32 
33  template<std::size_t I, typename TupleLike>
34  constexpr auto adl_get(TupleLike && t) noexcept
35  -> decltype(get<I>(static_cast<TupleLike &&>(t)))
36  {
37  return get<I>(static_cast<TupleLike &&>(t));
38  }
39  template<typename T, typename TupleLike>
40  constexpr auto adl_get(TupleLike && t) noexcept
41  -> decltype(get<T>(static_cast<TupleLike &&>(t)))
42  {
43  return get<T>(static_cast<TupleLike &&>(t));
44  }
45  } // namespace _adl_get_
46  using _adl_get_::adl_get;
47  } // namespace detail
48 
49  namespace _tuple_wrapper_
50  {
51  template<typename TupleLike>
52  struct forward_tuple_interface : TupleLike
53  {
54  forward_tuple_interface() = default;
55  using TupleLike::TupleLike;
56 #if !defined(__clang__) || __clang_major__ > 3
57  CPP_member
58  constexpr CPP_ctor(forward_tuple_interface)(TupleLike && base)( //
59  noexcept(std::is_nothrow_move_constructible<TupleLike>::value) //
60  requires move_constructible<TupleLike>)
61  : TupleLike(static_cast<TupleLike &&>(base))
62  {}
63  CPP_member
64  constexpr CPP_ctor(forward_tuple_interface)(TupleLike const & base)( //
65  noexcept(std::is_nothrow_copy_constructible<TupleLike>::value) //
66  requires copy_constructible<TupleLike>)
67  : TupleLike(base)
68  {}
69 #else
70  // Clang 3.x have a problem with inheriting constructors
71  // that causes the declarations in the preceeding PP block to get
72  // instantiated too early.
73  template(typename B = TupleLike)(
74  requires move_constructible<B>)
75  constexpr forward_tuple_interface(TupleLike && base) noexcept(
76  std::is_nothrow_move_constructible<TupleLike>::value)
77  : TupleLike(static_cast<TupleLike &&>(base))
78  {}
79  template(typename B = TupleLike)(
80  requires copy_constructible<B>)
81  constexpr forward_tuple_interface(TupleLike const & base) noexcept(
82  std::is_nothrow_copy_constructible<TupleLike>::value)
83  : TupleLike(base)
84  {}
85 #endif
86 
87  // clang-format off
88  template<std::size_t I, typename U = TupleLike>
89  friend constexpr auto CPP_auto_fun(get)(
90  forward_tuple_interface<TupleLike> &wb)
91  (
92  return detail::adl_get<I>(static_cast<U &>(wb))
93  )
94  template<std::size_t I, typename U = TupleLike>
95  friend constexpr auto CPP_auto_fun(get)(
96  forward_tuple_interface<TupleLike> const &wb)
97  (
98  return detail::adl_get<I>(static_cast<U const &>(wb))
99  )
100  template<std::size_t I, typename U = TupleLike>
101  friend constexpr auto CPP_auto_fun(get)(
102  forward_tuple_interface<TupleLike> &&wb)
103  (
104  return detail::adl_get<I>(static_cast<U &&>(wb))
105  )
106  template<std::size_t I, typename U = TupleLike>
107  friend constexpr auto CPP_auto_fun(get)(
108  forward_tuple_interface<TupleLike> const &&wb)
109  (
110  return detail::adl_get<I>(static_cast<U const &&>(wb))
111  )
112  template<typename T, typename U = TupleLike>
113  friend constexpr auto CPP_auto_fun(get)(
114  forward_tuple_interface<TupleLike> &wb)
115  (
116  return detail::adl_get<T>(static_cast<U &>(wb))
117  )
118  template<typename T, typename U = TupleLike>
119  friend constexpr auto CPP_auto_fun(get)(
120  forward_tuple_interface<TupleLike> const &wb)
121  (
122  return detail::adl_get<T>(static_cast<U const &>(wb))
123  )
124  template<typename T, typename U = TupleLike>
125  friend constexpr auto CPP_auto_fun(get)(
126  forward_tuple_interface<TupleLike> &&wb)
127  (
128  return detail::adl_get<T>(static_cast<U &&>(wb))
129  )
130  template<typename T, typename U = TupleLike>
131  friend constexpr auto CPP_auto_fun(get)(
132  forward_tuple_interface<TupleLike> const &&wb)
133  (
134  return detail::adl_get<T>(static_cast<U const &&>(wb))
135  )
136  // clang-format on
137  };
138  } // namespace _tuple_wrapper_
140 } // namespace ranges
141 
142 #include <range/v3/detail/epilogue.hpp>
143 
144 #endif // RANGES_V3_DETAIL_ADL_GET_HPP