/// \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; #if !defined(__clang__) || __clang_major__ > 3 template constexpr CPP_ctor(reference_wrapper)(U && u)( // noexcept(std::is_nothrow_constructible::value) // requires(!defer::same_as, reference_wrapper>) && defer::constructible_from) : detail::reference_wrapper_{static_cast(u)} {} #else // BUGBUG clang-3.7 prefers a CPP_template here instead of a CPP_ctor CPP_template(typename U)( // requires(!defer::same_as, reference_wrapper>) && defer::constructible_from) // constexpr reference_wrapper(U && u) noexcept( std::is_nothrow_constructible::value) : detail::reference_wrapper_{static_cast(u)} {} #endif constexpr reference get() const noexcept { return this->base_::get(); } constexpr operator reference() const noexcept { return get(); } CPP_template(typename...)( // requires(!std::is_rvalue_reference::value)) // 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 : pipeable_base { template auto operator()(T & t) const -> CPP_ret(reference_wrapper)( // requires(!is_reference_wrapper_v)) { return {t}; } /// \overload template reference_wrapper operator()(reference_wrapper t) const { return t; } /// \overload template 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 T && operator()(T && t) const noexcept { return static_cast(t); } /// \overload template typename reference_wrapper::reference operator()(reference_wrapper t) const noexcept { return t.get(); } /// \overload template T & operator()(std::reference_wrapper t) const noexcept { return t.get(); } /// \overload template 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 #endif