/// \file // Range v3 library // // Copyright Eric Niebler 2013-present // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_FUNCTIONAL_REFERENCE_WRAPPER_HPP #define RANGES_V3_FUNCTIONAL_REFERENCE_WRAPPER_HPP #include #include #include #include #include #include #include #include namespace ranges { /// \addtogroup group-functional /// @{ /// \cond namespace detail { template struct reference_wrapper_ { T * t_ = nullptr; constexpr reference_wrapper_() = default; constexpr reference_wrapper_(T & t) noexcept : t_(detail::addressof(t)) {} constexpr reference_wrapper_(T &&) = delete; constexpr T & get() const noexcept { return *t_; } }; template struct reference_wrapper_ : reference_wrapper_ { using reference_wrapper_::reference_wrapper_; }; template struct reference_wrapper_ { T * t_ = nullptr; constexpr reference_wrapper_() = default; constexpr reference_wrapper_(T && t) noexcept : t_(detail::addressof(t)) {} constexpr T && get() const noexcept { return static_cast(*t_); } }; } // namespace detail /// \endcond // Can be used to store rvalue references in addition to lvalue references. // Also, see: https://wg21.link/lwg2993 template struct reference_wrapper : private detail::reference_wrapper_ { private: using base_ = detail::reference_wrapper_; using base_::t_; public: using type = meta::_t>; using reference = meta::if_, T, T &>; constexpr reference_wrapper() = default; template(typename U)( requires (!same_as, reference_wrapper>) AND constructible_from) constexpr reference_wrapper(U && u) noexcept( std::is_nothrow_constructible::value) : detail::reference_wrapper_{static_cast(u)} {} constexpr reference get() const noexcept { return this->base_::get(); } constexpr operator reference() const noexcept { return get(); } template(typename...)( requires (!std::is_rvalue_reference::value)) // constexpr operator std::reference_wrapper() const noexcept { return {get()}; } // clang-format off template constexpr auto CPP_auto_fun(operator())(Args &&...args) (const) ( return invoke(static_cast(*t_), static_cast(args)...) ) // clang-format on }; struct ref_fn { template(typename T)( requires (!is_reference_wrapper_v)) // constexpr reference_wrapper operator()(T & t) const { return {t}; } /// \overload template constexpr reference_wrapper operator()(reference_wrapper t) const { return t; } /// \overload template constexpr reference_wrapper operator()(std::reference_wrapper t) const { return {t.get()}; } }; /// \ingroup group-functional /// \sa `ref_fn` RANGES_INLINE_VARIABLE(ref_fn, ref) template using ref_t = decltype(ref(std::declval())); struct unwrap_reference_fn { template constexpr T && operator()(T && t) const noexcept { return static_cast(t); } /// \overload template constexpr typename reference_wrapper::reference operator()(reference_wrapper t) const noexcept { return t.get(); } /// \overload template constexpr T & operator()(std::reference_wrapper t) const noexcept { return t.get(); } /// \overload template constexpr T & operator()(ref_view t) const noexcept { return t.base(); } }; /// \ingroup group-functional /// \sa `unwrap_reference_fn` RANGES_INLINE_VARIABLE(unwrap_reference_fn, unwrap_reference) template using unwrap_reference_t = decltype(unwrap_reference(std::declval())); /// @} } // namespace ranges #include #endif