Horizon
reference_wrapper.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2013-present
5 //
6 // Use, modification and distribution is subject to the
7 // Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Project home: https://github.com/ericniebler/range-v3
12 //
13 #ifndef RANGES_V3_FUNCTIONAL_REFERENCE_WRAPPER_HPP
14 #define RANGES_V3_FUNCTIONAL_REFERENCE_WRAPPER_HPP
15 
16 #include <type_traits>
17 #include <utility>
18 
19 #include <meta/meta.hpp>
20 
21 #include <concepts/concepts.hpp>
22 
24 #include <range/v3/utility/addressof.hpp>
25 #include <range/v3/utility/static_const.hpp>
26 
27 #include <range/v3/detail/prologue.hpp>
28 
29 namespace ranges
30 {
33 
35  namespace detail
36  {
37  template<typename T>
38  struct reference_wrapper_
39  {
40  T * t_ = nullptr;
41  constexpr reference_wrapper_() = default;
42  constexpr reference_wrapper_(T & t) noexcept
43  : t_(detail::addressof(t))
44  {}
45  constexpr reference_wrapper_(T &&) = delete;
46  constexpr T & get() const noexcept
47  {
48  return *t_;
49  }
50  };
51  template<typename T>
52  struct reference_wrapper_<T &> : reference_wrapper_<T>
53  {
54  using reference_wrapper_<T>::reference_wrapper_;
55  };
56  template<typename T>
57  struct reference_wrapper_<T &&>
58  {
59  T * t_ = nullptr;
60  constexpr reference_wrapper_() = default;
61  constexpr reference_wrapper_(T && t) noexcept
62  : t_(detail::addressof(t))
63  {}
64  constexpr T && get() const noexcept
65  {
66  return static_cast<T &&>(*t_);
67  }
68  };
69  } // namespace detail
71 
72  // Can be used to store rvalue references in addition to lvalue references.
73  // Also, see: https://wg21.link/lwg2993
74  template<typename T>
75  struct reference_wrapper : private detail::reference_wrapper_<T>
76  {
77  private:
78  using base_ = detail::reference_wrapper_<T>;
79  using base_::t_;
80 
81  public:
83  using reference = meta::if_<std::is_reference<T>, T, T &>;
84 
85  constexpr reference_wrapper() = default;
86  template(typename U)(
87  requires (!same_as<uncvref_t<U>, reference_wrapper>) AND
88  constructible_from<base_, U>)
89  constexpr reference_wrapper(U && u) noexcept(
90  std::is_nothrow_constructible<base_, U>::value)
91  : detail::reference_wrapper_<T>{static_cast<U &&>(u)}
92  {}
93  constexpr reference get() const noexcept
94  {
95  return this->base_::get();
96  }
97  constexpr operator reference() const noexcept
98  {
99  return get();
100  }
101  template(typename...)(
102  requires (!std::is_rvalue_reference<T>::value)) //
103  constexpr operator std::reference_wrapper<type>() const noexcept
104  {
105  return {get()};
106  }
107  // clang-format off
108  template<typename ...Args>
109  constexpr auto CPP_auto_fun(operator())(Args &&...args) (const)
110  (
111  return invoke(static_cast<reference>(*t_), static_cast<Args &&>(args)...)
112  )
113  // clang-format on
114  };
115 
116  struct ref_fn
117  {
118  template(typename T)(
119  requires (!is_reference_wrapper_v<T>)) //
120  constexpr reference_wrapper<T> operator()(T & t) const
121  {
122  return {t};
123  }
125  template<typename T>
127  {
128  return t;
129  }
131  template<typename T>
132  constexpr reference_wrapper<T> operator()(std::reference_wrapper<T> t) const
133  {
134  return {t.get()};
135  }
136  };
137 
140  RANGES_INLINE_VARIABLE(ref_fn, ref)
141 
142  template<typename T>
143  using ref_t = decltype(ref(std::declval<T>()));
144 
146  {
147  template<typename T>
148  constexpr T && operator()(T && t) const noexcept
149  {
150  return static_cast<T &&>(t);
151  }
153  template<typename T>
154  constexpr typename reference_wrapper<T>::reference operator()(reference_wrapper<T> t) const
155  noexcept
156  {
157  return t.get();
158  }
160  template<typename T>
161  constexpr T & operator()(std::reference_wrapper<T> t) const noexcept
162  {
163  return t.get();
164  }
166  template<typename T>
167  constexpr T & operator()(ref_view<T> t) const noexcept
168  {
169  return t.base();
170  }
171  };
172 
175  RANGES_INLINE_VARIABLE(unwrap_reference_fn, unwrap_reference)
176 
177  template<typename T>
178  using unwrap_reference_t = decltype(unwrap_reference(std::declval<T>()));
180 } // namespace ranges
181 
182 #include <range/v3/detail/epilogue.hpp>
183 
184 #endif
decltype(unwrap_reference(std::declval< T >())) unwrap_reference_t
Definition: reference_wrapper.hpp:178
decltype(ref(std::declval< T >())) ref_t
Definition: reference_wrapper.hpp:143
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
typename T::type _t
Type alias for T::type.
Definition: meta.hpp:141
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition: meta.hpp:541
_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.
Definition: reference_wrapper.hpp:117
constexpr reference_wrapper< T > operator()(std::reference_wrapper< T > t) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: reference_wrapper.hpp:132
constexpr reference_wrapper< T > operator()(reference_wrapper< T > t) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: reference_wrapper.hpp:126
Definition: ref.hpp:41
Definition: reference_wrapper.hpp:76
Definition: reference_wrapper.hpp:146
constexpr reference_wrapper< T >::reference operator()(reference_wrapper< T > t) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: reference_wrapper.hpp:154