/* * This file is part of the "https://github.com/blackmatov/invoke.hpp" * MIT License * * Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #pragma once #include #include #include #include #define INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(...) \ noexcept(noexcept(__VA_ARGS__)) -> decltype (__VA_ARGS__) { return __VA_ARGS__; } // // void_t // namespace mgb { namespace impl { template struct make_void { using type = void; }; } // namespace impl template using void_t = typename impl::make_void::type; } // namespace mgb // // is_reference_wrapper // namespace mgb { namespace impl { template struct is_reference_wrapper_impl : std::false_type {}; template struct is_reference_wrapper_impl> : std::true_type {}; } // namespace impl template struct is_reference_wrapper : impl::is_reference_wrapper_impl::type> {}; } // namespace mgb // // invoke // namespace mgb { namespace impl { // // invoke_member_object_impl // template < typename Base, typename F, typename Derived, typename std::enable_if::type>::value, int>::type = 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::type>::value, int>::type = 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< !std::is_base_of::type>::value && !is_reference_wrapper::type>::value , int>::type = 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::type>::value, int>::type = 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::type>::value, int>::type = 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< !std::is_base_of::type>::value && !is_reference_wrapper::type>::value , int>::type = 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::type>::value, int>::type = 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::type>::value, int>::type = 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::type>::value, int>::type = 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 mgb { namespace impl { struct invoke_result_impl_tag {}; template struct invoke_result_impl {}; template struct invoke_result_impl< void_t(), std::declval()...))>, F, Args...> { using type = decltype(mgb::invoke(std::declval(), std::declval()...)); }; } // namespace impl template struct invoke_result : impl::invoke_result_impl {}; template using invoke_result_t = typename invoke_result::type; } // namespace mgb // // is_invocable // namespace mgb { namespace impl { struct is_invocable_r_impl_tag {}; template struct is_invocable_r_impl : std::false_type {}; template struct is_invocable_r_impl< void_t>, R, F, Args...> : std::conditional< std::is_void::value, std::true_type, std::is_convertible, R>>::type {}; } // namespace impl template struct is_invocable_r : impl::is_invocable_r_impl {}; template using is_invocable = is_invocable_r; } // namespace mgb // // apply // namespace mgb { namespace impl { template constexpr auto apply_impl(F&& f, Tuple&& args, std::index_sequence) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(mgb::invoke( std::forward(f), std::get(std::forward(args))...)) } template constexpr auto apply(F&& f, Tuple&& args) INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( impl::apply_impl(std::forward(f), std::forward(args), std::make_index_sequence::type>::value>())) } // namespace mgb #undef INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN