/// \file // Range v3 library // // Copyright Eric Niebler 2013-present // Copyright Casey Carter 2016 // // 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_INVOKE_HPP #define RANGES_V3_FUNCTIONAL_INVOKE_HPP #include #include #include #include #include #include #include RANGES_DIAGNOSTIC_PUSH RANGES_DIAGNOSTIC_IGNORE_CXX17_COMPAT RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS #ifndef RANGES_CONSTEXPR_INVOKE #ifdef RANGES_WORKAROUND_CLANG_23135 #define RANGES_CONSTEXPR_INVOKE 0 #else #define RANGES_CONSTEXPR_INVOKE 1 #endif #endif namespace ranges { /// \addtogroup group-functional /// @{ /// \cond namespace detail { RANGES_DIAGNOSTIC_PUSH RANGES_DIAGNOSTIC_IGNORE_VOID_PTR_DEREFERENCE template U & can_reference_(U &&); // clang-format off /// \concept dereferenceable_part_ /// \brief The \c dereferenceable_part_ concept template CPP_requires(dereferenceable_part_, requires(T && t) // ( detail::can_reference_(*(T &&) t) )); /// \concept dereferenceable_ /// \brief The \c dereferenceable_ concept template CPP_concept dereferenceable_ = // CPP_requires_ref(detail::dereferenceable_part_, T); // clang-format on RANGES_DIAGNOSTIC_POP template RANGES_INLINE_VAR constexpr bool is_reference_wrapper_v = meta::is::value || meta::is::value; } // namespace detail /// \endcond template RANGES_INLINE_VAR constexpr bool is_reference_wrapper_v = detail::is_reference_wrapper_v>; template using is_reference_wrapper = meta::bool_>; /// \cond template using is_reference_wrapper_t RANGES_DEPRECATED( "is_reference_wrapper_t is deprecated.") = meta::_t>; /// \endcond struct invoke_fn { private: template(typename, typename T1)( requires detail::dereferenceable_) static constexpr decltype(auto) coerce(T1 && t1, long) noexcept(noexcept(*static_cast(t1))) { return *static_cast(t1); } template(typename T, typename T1)( requires derived_from, T>) static constexpr T1 && coerce(T1 && t1, int) noexcept { return static_cast(t1); } template(typename, typename T1)( requires detail::is_reference_wrapper_v>) static constexpr decltype(auto) coerce(T1 && t1, int) noexcept { return static_cast(t1).get(); } public: template constexpr auto operator()(F T::*f, T1&& t1, Args&&... args) const noexcept(noexcept((invoke_fn::coerce((T1&&) t1, 0).*f)((Args&&) args...))) -> decltype((invoke_fn::coerce((T1&&) t1, 0).*f)((Args&&) args...)) { return (invoke_fn::coerce((T1&&) t1, 0).*f)((Args&&) args...); } template constexpr auto operator()(D T::*f, T1&& t1) const noexcept(noexcept(invoke_fn::coerce((T1&&) t1, 0).*f)) -> decltype(invoke_fn::coerce((T1&&) t1, 0).*f) { return invoke_fn::coerce((T1&&) t1, 0).*f; } template CPP_PP_IIF(RANGES_CONSTEXPR_INVOKE)(CPP_PP_EXPAND, CPP_PP_EAT)(constexpr) auto operator()(F&& f, Args&&... args) const noexcept(noexcept(((F&&) f)((Args&&) args...))) -> decltype(((F&&) f)((Args&&) args...)) { return ((F&&) f)((Args&&) args...); } }; RANGES_INLINE_VARIABLE(invoke_fn, invoke) #ifdef RANGES_WORKAROUND_MSVC_701385 /// \cond namespace detail { template struct _invoke_result_ {}; template struct _invoke_result_< meta::void_(), std::declval()...))>, Fun, Args...> { using type = decltype(invoke(std::declval(), std::declval()...)); }; } // namespace detail /// \endcond template using invoke_result = detail::_invoke_result_; template using invoke_result_t = meta::_t>; #else // RANGES_WORKAROUND_MSVC_701385 template using invoke_result_t = decltype(invoke(std::declval(), std::declval()...)); template struct invoke_result : meta::defer {}; #endif // RANGES_WORKAROUND_MSVC_701385 /// \cond namespace detail { template struct is_nothrow_invocable_impl_ { template static constexpr bool apply() noexcept { return false; } }; template<> struct is_nothrow_invocable_impl_ { template static constexpr bool apply() noexcept { return noexcept(invoke(std::declval(), std::declval()...)); } }; } // namespace detail /// \endcond template RANGES_INLINE_VAR constexpr bool is_invocable_v = meta::is_trait>::value; template RANGES_INLINE_VAR constexpr bool is_nothrow_invocable_v = detail::is_nothrow_invocable_impl_>::template apply< Fn, Args...>(); /// \cond template struct RANGES_DEPRECATED( "ranges::result_of is deprecated. " "Please use ranges::invoke_result") result_of {}; template struct RANGES_DEPRECATED( "ranges::result_of is deprecated. " "Please use ranges::invoke_result") result_of : meta::defer {}; /// \endcond namespace cpp20 { using ranges::invoke; using ranges::invoke_result; using ranges::invoke_result_t; using ranges::is_invocable_v; using ranges::is_nothrow_invocable_v; } // namespace cpp20 /// @} } // namespace ranges RANGES_DIAGNOSTIC_POP #include #endif // RANGES_V3_FUNCTIONAL_INVOKE_HPP