Useful with StaticReflection and StaticPolymorphism. The type has_function receives information about the function signature and stores this in a typedef. Function names are provided in a derived type. SubstitutionFailureIsNotAnError (SFINAE) performs the magic.
The following implementation supports up to 8 parameters - this may be extended as required.
namespace framework {
namespace meta
{
template <
typename T, typename R,
typename A0 = unspecified,
typename A1 = unspecified,
typename A2 = unspecified,
typename A3 = unspecified,
typename A4 = unspecified,
typename A5 = unspecified,
typename A6 = unspecified>
struct has_function
{
// 0-7 arg member function signature
template <
typename U,
typename if_<is_same<A6, unspecified>::value,
typename if_<is_same<A5, unspecified>::value,
typename if_<is_same<A4, unspecified>::value,
typename if_<is_same<A3, unspecified>::value,
typename if_<is_same<A2, unspecified>::value,
typename if_<is_same<A1, unspecified>::value,
typename if_<is_same<A0, unspecified>::value,
/* 0 parameter(s) */ R(U::*)(),
/* 1 parameter(s) */ R(U::*)(A0)>::value,
/* 2 parameter(s) */ R(U::*)(A0, A1)>::value,
/* 3 parameter(s) */ R(U::*)(A0, A1, A2)>::value,
/* 4 parameter(s) */ R(U::*)(A0, A1, A2, A3)>::value,
/* 5 parameter(s) */ R(U::*)(A0, A1, A2, A3, A4)>::value,
/* 6 parameter(s) */ R(U::*)(A0, A1, A2, A3, A4, A5)>::value,
/* 7 parameter(s) */ R(U::*)(A0, A1, A2, A3, A4, A5, A6)>::value
>
struct signature;
},;
#define FW_HAS_FUNCTION(name)\
template < \
typename T,\
typename R,\
typename A0 = framework::meta::unspecified,\
typename A1 = framework::meta::unspecified,\
typename A2 = framework::meta::unspecified,\
typename A3 = framework::meta::unspecified,\
typename A4 = framework::meta::unspecified,\
typename A5 = framework::meta::unspecified,\
typename A6 = framework::meta::unspecified \
>\
struct has_function_##name : framework::meta::has_function<T,R,A0,A1,A2,A3,A4,A5,A6>\
{\
template <typename U> static framework::meta::no check(...);\
template <typename U> static framework::meta::yes check(signature<U, &U:: name >*);\
enum { value = sizeof(check<T>(0)) == sizeof(framework::meta::yes) },;\
},;
}, // namespace meta
}, // namespace framework
For an example, see StaticReflection.
See CeePlusPlusIdioms, TemplateMetaprogrammingTechniques, TemplateMetafunctionIdentity, TemplateMetafunctionAnd, TemplateMetafunctionIf.
CategoryCppTemplates CategoryMetaprogramming CategoryCpp