Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 10:26:40

0001 /// \file
0002 // Range v3 library
0003 //
0004 //  Copyright Eric Niebler 2013-present
0005 //
0006 //  Use, modification and distribution is subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Project home: https://github.com/ericniebler/range-v3
0012 //
0013 #ifndef RANGES_V3_FUNCTIONAL_REFERENCE_WRAPPER_HPP
0014 #define RANGES_V3_FUNCTIONAL_REFERENCE_WRAPPER_HPP
0015 
0016 #include <type_traits>
0017 #include <utility>
0018 
0019 #include <meta/meta.hpp>
0020 
0021 #include <concepts/concepts.hpp>
0022 
0023 #include <range/v3/functional/invoke.hpp>
0024 #include <range/v3/utility/addressof.hpp>
0025 #include <range/v3/utility/static_const.hpp>
0026 
0027 #include <range/v3/detail/prologue.hpp>
0028 
0029 namespace ranges
0030 {
0031     /// \addtogroup group-functional
0032     /// @{
0033 
0034     /// \cond
0035     namespace detail
0036     {
0037         template<typename T>
0038         struct reference_wrapper_
0039         {
0040             T * t_ = nullptr;
0041             constexpr reference_wrapper_() = default;
0042             constexpr reference_wrapper_(T & t) noexcept
0043               : t_(detail::addressof(t))
0044             {}
0045             constexpr reference_wrapper_(T &&) = delete;
0046             constexpr T & get() const noexcept
0047             {
0048                 return *t_;
0049             }
0050         };
0051         template<typename T>
0052         struct reference_wrapper_<T &> : reference_wrapper_<T>
0053         {
0054             using reference_wrapper_<T>::reference_wrapper_;
0055         };
0056         template<typename T>
0057         struct reference_wrapper_<T &&>
0058         {
0059             T * t_ = nullptr;
0060             constexpr reference_wrapper_() = default;
0061             constexpr reference_wrapper_(T && t) noexcept
0062               : t_(detail::addressof(t))
0063             {}
0064             constexpr T && get() const noexcept
0065             {
0066                 return static_cast<T &&>(*t_);
0067             }
0068         };
0069     } // namespace detail
0070     /// \endcond
0071 
0072     // Can be used to store rvalue references in addition to lvalue references.
0073     // Also, see: https://wg21.link/lwg2993
0074     template<typename T>
0075     struct reference_wrapper : private detail::reference_wrapper_<T>
0076     {
0077     private:
0078         using base_ = detail::reference_wrapper_<T>;
0079         using base_::t_;
0080 
0081     public:
0082         using type = meta::_t<std::remove_reference<T>>;
0083         using reference = meta::if_<std::is_reference<T>, T, T &>;
0084 
0085         constexpr reference_wrapper() = default;
0086         template(typename U)(
0087             requires (!same_as<uncvref_t<U>, reference_wrapper>) AND
0088                 constructible_from<base_, U>)
0089         constexpr reference_wrapper(U && u) noexcept(
0090             std::is_nothrow_constructible<base_, U>::value)
0091           : detail::reference_wrapper_<T>{static_cast<U &&>(u)}
0092         {}
0093         constexpr reference get() const noexcept
0094         {
0095             return this->base_::get();
0096         }
0097         constexpr operator reference() const noexcept
0098         {
0099             return get();
0100         }
0101         template(typename...)(
0102             requires (!std::is_rvalue_reference<T>::value)) //
0103         constexpr operator std::reference_wrapper<type>() const noexcept
0104         {
0105             return {get()};
0106         }
0107         // clang-format off
0108         template<typename ...Args>
0109         constexpr auto CPP_auto_fun(operator())(Args &&...args) (const)
0110         (
0111             return invoke(static_cast<reference>(*t_), static_cast<Args &&>(args)...)
0112         )
0113         // clang-format on
0114     };
0115 
0116     struct ref_fn
0117     {
0118         template(typename T)(
0119             requires (!is_reference_wrapper_v<T>)) //
0120         constexpr reference_wrapper<T> operator()(T & t) const
0121         {
0122             return {t};
0123         }
0124         /// \overload
0125         template<typename T>
0126         constexpr reference_wrapper<T> operator()(reference_wrapper<T> t) const
0127         {
0128             return t;
0129         }
0130         /// \overload
0131         template<typename T>
0132         constexpr reference_wrapper<T> operator()(std::reference_wrapper<T> t) const
0133         {
0134             return {t.get()};
0135         }
0136     };
0137 
0138     /// \ingroup group-functional
0139     /// \sa `ref_fn`
0140     RANGES_INLINE_VARIABLE(ref_fn, ref)
0141 
0142     template<typename T>
0143     using ref_t = decltype(ref(std::declval<T>()));
0144 
0145     struct unwrap_reference_fn
0146     {
0147         template<typename T>
0148         constexpr T && operator()(T && t) const noexcept
0149         {
0150             return static_cast<T &&>(t);
0151         }
0152         /// \overload
0153         template<typename T>
0154         constexpr typename reference_wrapper<T>::reference operator()(reference_wrapper<T> t) const
0155             noexcept
0156         {
0157             return t.get();
0158         }
0159         /// \overload
0160         template<typename T>
0161         constexpr T & operator()(std::reference_wrapper<T> t) const noexcept
0162         {
0163             return t.get();
0164         }
0165         /// \overload
0166         template<typename T>
0167         constexpr T & operator()(ref_view<T> t) const noexcept
0168         {
0169             return t.base();
0170         }
0171     };
0172 
0173     /// \ingroup group-functional
0174     /// \sa `unwrap_reference_fn`
0175     RANGES_INLINE_VARIABLE(unwrap_reference_fn, unwrap_reference)
0176 
0177     template<typename T>
0178     using unwrap_reference_t = decltype(unwrap_reference(std::declval<T>()));
0179     /// @}
0180 } // namespace ranges
0181 
0182 #include <range/v3/detail/epilogue.hpp>
0183 
0184 #endif