c++11 - C++ metafunction to determine whether a type is callable -


is possible write c++(0x) metafunction determines whether type callable?

by callable type mean function type, function pointer type, function reference type (these detected boost::function_types::is_callable_builtin), lambda types, , class overloaded operator() (and maybe class implicit conversion operator 1 of these, that's not absolutely necessary).

edit: metafunction should detect presence of operator() signature, including templated operator(). believe difficult part.

edit: here use case:

template <typename predicate1, typename predicate2> struct and_predicate {     template <typename argt>     bool operator()(const argt& arg)     {         return predicate1(arg) && predicate2(arg);     }      predicate1 predicate1;     predicate2 predicate2; };  template <typename predicate1, typename predicate2> enable_if<ice_and<is_callable<predicate1>::value,                   is_callable<predicate2>::value>::value,           and_predicate<predicate1, predicate2>>::type operator&&(predicate1 predicate1, predicate2 predicate2) {     return and_predicate<predicate1, predicate2>{predicate1, predicate2}; } 

is_callable implement.

the presence of non-templated t::operator() given type t can detected by:

template<typename c> // detect regular operator() static char test(decltype(&c::operator()));  template<typename c> // worst match static char (&test(...))[2];  static const bool value = (sizeof( test<t>(0)  ) 

the presence of templated operator can detected by:

template<typename f, typename a> // detect 1-arg operator() static char test(int, decltype( (*(f*)0)( (*(a*)0) ) ) = 0);  template<typename f, typename a, typename b> // detect 2-arg operator() static char test(int, decltype( (*(f*)0)( (*(a*)0), (*(b*)0) ) ) = 0);  // ... detect n-arg operator()  template<typename f, typename ...args> // worst match static char (&test(...))[2];  static const bool value = (sizeof( test<t, int>(0)  ) == 1) ||                            (sizeof( test<t, int, int>(0)  ) == 1); // etc... 

however, these 2 not play nicely together, decltype(&c::operator()) produce error if c has templated function call operator. solution run sequence of checks against templated operator first, , check regular operator() if , if templated 1 can not found. done specializing non-templated check no-op if templated 1 found.

template<bool, typename t> struct has_regular_call_operator {   template<typename c> // detect regular operator()   static char test(decltype(&c::operator()));    template<typename c> // worst match   static char (&test(...))[2];    static const bool value = (sizeof( test<t>(0)  ) == 1); };  template<typename t> struct has_regular_call_operator<true,t> {   static const bool value = true; };  template<typename t> struct has_call_operator {   template<typename f, typename a> // detect 1-arg operator()   static char test(int, decltype( (*(f*)0)( (*(a*)0) ) ) = 0);    template<typename f, typename a, typename b> // detect 2-arg operator()   static char test(int, decltype( (*(f*)0)( (*(a*)0), (*(b*)0) ) ) = 0);    template<typename f, typename a, typename b, typename c> // detect 3-arg operator()   static char test(int, decltype( (*(f*)0)( (*(a*)0), (*(b*)0), (*(c*)0) ) ) = 0);    template<typename f, typename ...args> // worst match   static char (&test(...))[2];    static const bool onearg = (sizeof( test<t, int>(0)  ) == 1);   static const bool twoarg = (sizeof( test<t, int, int>(0)  ) == 1);   static const bool threearg = (sizeof( test<t, int, int, int>(0)  ) == 1);    static const bool hastemplatedoperator = onearg || twoarg || threearg;   static const bool value = has_regular_call_operator<hastemplatedoperator, t>::value; }; 

if arity one, discussed above, check should simpler. not see need additional type traits or library facilities work.


Comments

Popular posts from this blog

linux - Mailx and Gmail nss config dir -

c# - Is it possible to remove an existing registration from Autofac container builder? -

php - Mysql PK and FK char(36) vs int(10) -