/* * Copyright (c) 2017-2023 zhllxt * * author : zhllxt * email : 37792738@qq.com * * Distributed under 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) * * refrenced from : https://github.com/qicosmos/rest_rpc/blob/master/include/meta_util.hpp */ #ifndef __ASIO2_FUNCTION_TRAITS_HPP__ #define __ASIO2_FUNCTION_TRAITS_HPP__ #if defined(_MSC_VER) && (_MSC_VER >= 1200) #pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include namespace asio2::detail { template struct lambda_dummy_t { }; template struct lambda_dummy_t { template inline R operator()(const Args&...) { if /**/ constexpr (std::is_same_v>>) { return; } else if constexpr (std::is_reference_v>) { static typename std::remove_reference_t s; return s; } else { return R{}; } } }; /* * 1. function type ==> Ret(Args...) * 2. function pointer ==> Ret(*)(Args...) * 3. function reference ==> Ret(&)(Args...) * 4. pointer to non-static member function ==> Ret(T::*)(Args...) * 5. function object and functor ==> &T::operator() * 6. function with generic operator call ==> template &T::operator() */ template struct function_traits { static constexpr bool is_callable = false; }; template struct function_traits { public: static constexpr std::size_t argc = sizeof...(Args); static constexpr bool is_callable = true; typedef Ret function_type(Args...); typedef Ret return_type; using stl_function_type = std::function; using stl_lambda_type = lambda_dummy_t; typedef Ret(*pointer)(Args...); using class_type = void; template struct args { static_assert(I < argc, "index is out of range, index must less than sizeof Args"); using type = typename std::tuple_element>::type; }; typedef std::tuple tuple_type; typedef std::tuple>...> pod_tuple_type; }; template struct function_traits { public: static constexpr std::size_t argc = sizeof...(Args); static constexpr bool is_callable = true; typedef Ret function_type(Args...); typedef Ret return_type; using stl_function_type = std::function; using stl_lambda_type = lambda_dummy_t; typedef Ret(*pointer)(Args...); using class_type = Class; template struct args { static_assert(I < argc, "index is out of range, index must less than sizeof Args"); using type = typename std::tuple_element>::type; }; typedef std::tuple tuple_type; typedef std::tuple>...> pod_tuple_type; }; // regular function pointer template struct function_traits : function_traits {}; // non-static member function pointer template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; // non-static member function pointer -- noexcept versions for (C++17 and later) template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; template struct function_traits : function_traits {}; // functor lambda template struct function_traits> : function_traits {}; // std::function template struct function_traits> : function_traits {}; template typename function_traits::stl_function_type to_function(F&& lambda) { return static_cast::stl_function_type>(std::forward(lambda)); } template typename function_traits::pointer to_function_pointer(const F& lambda) noexcept { return static_cast::pointer>(lambda); } template< class F > inline constexpr bool is_callable_v = function_traits>::is_callable; template struct is_template_callable : std::false_type {}; template struct is_template_callable&>() ((std::declval())...)), char>, Args...> : std::true_type {}; template inline constexpr bool is_template_callable_v = is_template_callable::value; } #endif // !__ASIO2_FUNCTION_TRAITS_HPP__