/// \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 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 { template U & can_reference_(U &&); // clang-format off CPP_def ( template(typename T) concept dereferenceable_, requires (T &&t) ( detail::can_reference_(*static_cast(t)) ) ); // clang-format on 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_>; template using is_reference_wrapper_t RANGES_DEPRECATED( "is_reference_wrapper_t is deprecated.") = meta::_t>; struct invoke_fn { private: template constexpr static decltype(auto) CPP_fun(coerce)(T1 && t1, long)( // noexcept(noexcept(*static_cast(t1))) // requires detail::dereferenceable_) { return *static_cast(t1); } template constexpr static auto coerce(T1 && t1, int) noexcept -> CPP_ret(T1 &&)( // requires derived_from, T>) { return static_cast(t1); } template constexpr static decltype(auto) CPP_fun(coerce)(T1 && t1, int)( noexcept(true) // requires detail::is_reference_wrapper_v>) { return static_cast(t1).get(); } public: // clang-format off template constexpr auto CPP_auto_fun(operator())(F T::*f, T1&& t1, Args&&... args)(const) ( return (invoke_fn::coerce(static_cast(t1), 0).*f) (static_cast(args)...) ) template constexpr auto CPP_auto_fun(operator())(D T::*f, T1&& t1)(const) ( return invoke_fn::coerce(static_cast(t1), 0).*f ) template CPP_PP_IIF(RANGES_CONSTEXPR_INVOKE)(CPP_PP_EXPAND, CPP_PP_EAT)(constexpr) auto CPP_auto_fun(operator())(F&& f, Args&&... args)(const) ( return static_cast(f)(static_cast(args)...) ) // clang-format on }; 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 #endif // RANGES_V3_FUNCTIONAL_INVOKE_HPP