/******************************************************************************* * This file is part of the "https://github.com/blackmatov/invoke.hpp" * For conditions of distribution and use, see copyright notice in LICENSE.md * Copyright (C) 2018 Matvey Cherevko ******************************************************************************/ #pragma once #include #include #include #include #define INVOKE_HPP_NOEXCEPT_RETURN(...) \ noexcept(noexcept(__VA_ARGS__)) { return __VA_ARGS__; } #define INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(...) \ noexcept(noexcept(__VA_ARGS__)) -> decltype (__VA_ARGS__) { return __VA_ARGS__; } // // void_t // namespace invoke_hpp { namespace impl { template < typename... Args > struct make_void { using type = void; }; } template < typename... Args > using void_t = typename impl::make_void::type; } // // is_reference_wrapper // namespace invoke_hpp { namespace impl { template < typename T > struct is_reference_wrapper_impl : std::false_type {}; template < typename U > struct is_reference_wrapper_impl> : std::true_type {}; } template < typename T > struct is_reference_wrapper : impl::is_reference_wrapper_impl> {}; } // // invoke // namespace invoke_hpp { namespace impl { // // invoke_member_object_impl // template < typename Base, typename F, typename Derived, typename std::enable_if_t>::value, int> = 0 > constexpr auto invoke_member_object_impl(F Base::* f, Derived&& ref) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( std::forward(ref).*f) template < typename Base, typename F, typename RefWrap, typename std::enable_if_t>::value, int> = 0 > constexpr auto invoke_member_object_impl(F Base::* f, RefWrap&& ref) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( ref.get().*f) template < typename Base, typename F, typename Pointer, typename std::enable_if_t< !std::is_base_of>::value && !is_reference_wrapper>::value , int> = 0 > constexpr auto invoke_member_object_impl(F Base::* f, Pointer&& ptr) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( (*std::forward(ptr)).*f) // // invoke_member_function_impl // template < typename Base, typename F, typename Derived, typename... Args, typename std::enable_if_t>::value, int> = 0 > constexpr auto invoke_member_function_impl(F Base::* f, Derived&& ref, Args&&... args) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( (std::forward(ref).*f)(std::forward(args)...)) template < typename Base, typename F, typename RefWrap, typename... Args, typename std::enable_if_t>::value, int> = 0 > constexpr auto invoke_member_function_impl(F Base::* f, RefWrap&& ref, Args&&... args) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( (ref.get().*f)(std::forward(args)...)) template < typename Base, typename F, typename Pointer, typename... Args, typename std::enable_if_t< !std::is_base_of>::value && !is_reference_wrapper>::value , int> = 0 > constexpr auto invoke_member_function_impl(F Base::* f, Pointer&& ptr, Args&&... args) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( ((*std::forward(ptr)).*f)(std::forward(args)...)) } template < typename F, typename... Args, typename std::enable_if_t>::value, int> = 0 > constexpr auto invoke(F&& f, Args&&... args) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( std::forward(f)(std::forward(args)...)) template < typename F, typename T, typename std::enable_if_t>::value, int> = 0 > constexpr auto invoke(F&& f, T&& t) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( impl::invoke_member_object_impl(std::forward(f), std::forward(t))) template < typename F, typename... Args, typename std::enable_if_t>::value, int> = 0 > constexpr auto invoke(F&& f, Args&&... args) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( impl::invoke_member_function_impl(std::forward(f), std::forward(args)...)) } // // invoke_result // namespace invoke_hpp { namespace impl { struct invoke_result_impl_tag {}; template < typename Void, typename F, typename... Args > struct invoke_result_impl {}; template < typename F, typename... Args > struct invoke_result_impl(), std::declval()...))>, F, Args...> { using type = decltype(invoke_hpp::invoke(std::declval(), std::declval()...)); }; } template < typename F, typename... Args > struct invoke_result : impl::invoke_result_impl {}; template < typename F, typename... Args > using invoke_result_t = typename invoke_result::type; } // // is_invocable // namespace invoke_hpp { namespace impl { struct is_invocable_r_impl_tag {}; template < typename Void, typename R, typename F, typename... Args > struct is_invocable_r_impl : std::false_type {}; template < typename R, typename F, typename... Args > struct is_invocable_r_impl>, R, F, Args...> : std::conditional_t< std::is_void::value, std::true_type, std::is_convertible, R>> {}; } template < typename R, typename F, typename... Args > struct is_invocable_r : impl::is_invocable_r_impl {}; template < typename F, typename... Args > using is_invocable = is_invocable_r; } // // apply // namespace invoke_hpp { namespace impl { template < typename F, typename Tuple, std::size_t... I > constexpr decltype(auto) apply_impl(F&& f, Tuple&& args, std::index_sequence) INVOKE_HPP_NOEXCEPT_RETURN( invoke_hpp::invoke( std::forward(f), std::get(std::forward(args))...)) } template < typename F, typename Tuple > constexpr decltype(auto) apply(F&& f, Tuple&& args) INVOKE_HPP_NOEXCEPT_RETURN( impl::apply_impl( std::forward(f), std::forward(args), std::make_index_sequence>::value>())) } #undef INVOKE_HPP_NOEXCEPT_RETURN #undef INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN