// Copyright satoren // 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) #pragma once #include #include "kaguya/config.hpp" namespace kaguya { namespace util { ///! struct null_type {}; #define KAGUYA_PP_STRUCT_TDEF_REP(N) KAGUYA_PP_CAT(typename A, N) = null_type #define KAGUYA_PP_STRUCT_TEMPLATE_DEF_REPEAT(N) \ KAGUYA_PP_REPEAT_ARG(N, KAGUYA_PP_STRUCT_TDEF_REP) template struct TypeTuple {}; template struct TypeTupleSize; #define KAGUYA_TYPE_TUPLE_SIZE_DEF(N) \ template \ struct TypeTupleSize > { \ static const size_t value = N; \ }; KAGUYA_TYPE_TUPLE_SIZE_DEF(0) KAGUYA_PP_REPEAT_DEF(KAGUYA_FUNCTION_MAX_ARGS, KAGUYA_TYPE_TUPLE_SIZE_DEF) #undef KAGUYA_TYPE_TUPLE_SIZE_DEF template struct CFuntionType; #define KAGUYA_CFUNCTION_TYPE_DEF(N) \ template \ struct CFuntionType > { \ typedef Ret (*type)(KAGUYA_PP_TEMPLATE_ARG_REPEAT(N)); \ }; KAGUYA_CFUNCTION_TYPE_DEF(0) KAGUYA_PP_REPEAT_DEF(KAGUYA_FUNCTION_MAX_ARGS, KAGUYA_CFUNCTION_TYPE_DEF) #undef KAGUYA_CFUNCTION_TYPE_DEF template struct FunctionSignatureType { typedef Ret result_type; typedef TypeTuple argument_type_tuple; static const size_t argument_count = TypeTupleSize::value; typedef typename CFuntionType::type c_function_type; }; template struct FunctionSignature; #define KAGUYA_MEMBER_FUNCTION_SIGNATURE_DEF(N) \ template \ struct FunctionSignature { \ typedef FunctionSignatureType \ type; \ }; \ template \ struct FunctionSignature { \ typedef FunctionSignatureType< \ Ret, const T & KAGUYA_PP_TEMPLATE_ARG_REPEAT_CONCAT(N)> \ type; \ }; #define KAGUYA_FUNCTION_SIGNATURE_DEF(N) \ template \ struct FunctionSignature { \ typedef FunctionSignatureType \ type; \ }; \ template \ struct FunctionSignature { \ typedef FunctionSignatureType \ type; \ }; \ template \ struct FunctionSignature< \ standard::function > { \ typedef FunctionSignatureType \ type; \ }; KAGUYA_MEMBER_FUNCTION_SIGNATURE_DEF(0) KAGUYA_PP_REPEAT_DEF(KAGUYA_PP_DEC(KAGUYA_FUNCTION_MAX_ARGS), KAGUYA_MEMBER_FUNCTION_SIGNATURE_DEF) #undef KAGUYA_MEMBER_FUNCTION_SIGNATURE_DEF KAGUYA_FUNCTION_SIGNATURE_DEF(0) KAGUYA_PP_REPEAT_DEF(KAGUYA_FUNCTION_MAX_ARGS, KAGUYA_FUNCTION_SIGNATURE_DEF) #undef KAGUYA_FUNCTION_SIGNATURE_DEF template struct FunctionResultType { typedef typename FunctionSignature::type::result_type type; }; template struct TypeIndexGet {}; #define KAGUYA_TYPE_INDEX_GET_DEF(N) \ template \ struct TypeIndexGet< \ remain, TypeTuple, true> { \ typedef arg type; \ }; \ template \ struct TypeIndexGet< \ remain, TypeTuple, false> \ : TypeIndexGet > {}; // KAGUYA_TYPE_INDEX_GET_DEF(0); KAGUYA_PP_REPEAT_DEF(KAGUYA_PP_DEC(KAGUYA_FUNCTION_MAX_ARGS), KAGUYA_TYPE_INDEX_GET_DEF) #undef KAGUYA_TYPE_INDEX_GET_DEF template struct ArgumentType { typedef typename TypeIndexGet< N, typename FunctionSignature::type::argument_type_tuple>::type type; }; namespace detail { #define KAGUYA_INVOKE_HELPER_DEF(N) \ template \ typename FunctionResultType::type invoke_helper( \ typename FunctionResultType::type (T::*f)( \ KAGUYA_PP_TEMPLATE_ARG_REPEAT(N)), \ ThisType this_ KAGUYA_PP_ARG_DEF_REPEAT_CONCAT(N)) { \ return (this_.*f)(KAGUYA_PP_ARG_REPEAT(N)); \ } \ template \ typename FunctionResultType::type invoke_helper( \ typename FunctionResultType::type (T::*f)( \ KAGUYA_PP_TEMPLATE_ARG_REPEAT(N)) const, \ ThisType this_ KAGUYA_PP_ARG_DEF_REPEAT_CONCAT(N)) { \ return (this_.*f)(KAGUYA_PP_ARG_REPEAT(N)); \ } \ template \ typename FunctionResultType::type invoke_helper( \ F f KAGUYA_PP_ARG_DEF_REPEAT_CONCAT(N)) { \ return f(KAGUYA_PP_ARG_REPEAT(N)); \ } KAGUYA_INVOKE_HELPER_DEF(0) KAGUYA_PP_REPEAT_DEF(KAGUYA_FUNCTION_MAX_ARGS, KAGUYA_INVOKE_HELPER_DEF) #undef KAGUYA_INVOKE_HELPER_DEF } #define KAGUYA_INVOKE_DEF(N) \ template \ typename FunctionResultType::type invoke( \ F f KAGUYA_PP_ARG_DEF_REPEAT_CONCAT(N)) { \ return detail::invoke_helper( \ f KAGUYA_PP_ARG_REPEAT_CONCAT(N)); \ } KAGUYA_INVOKE_DEF(0) KAGUYA_PP_REPEAT_DEF(KAGUYA_FUNCTION_MAX_ARGS, KAGUYA_INVOKE_DEF) #undef KAGUYA_INVOKE_DEF #undef KAGUYA_PP_STRUCT_TDEF_REP #undef KAGUYA_PP_STRUCT_TEMPLATE_DEF_REPEAT } }