Re: determine if a type is a free function pointer
 
Kai-Uwe Bux wrote:
Barry wrote:
Kai-Uwe Bux wrote:
[many lines]
Good job,
boost.is_function seems to do hard coding to meet possible function
argument list length.
Makes me wonder whether there is a bug in my code. I wouldn't be surprised.
 
though is_function checks function not pointer to function.
with a wrapper this should also work with function check.
template <class T>
struct is_function
{
     static const bool value = is_function_pointer<T*>::value;
};
   SHOW_BOOL( is_function<int(int)>::value );
   SHOW_BOOL( is_function<int(int, int)>::value );
   SHOW_BOOL( is_function<int(*)(int)>::value );
   SHOW_BOOL( is_function<int(*)(int, int)>::value );
I actually think that the code needs some cleanup and that testing for being
a function is simpler than testing for being a function pointer. So, I
changed it the other way around. Here are the versions I added to my
library:
// is_class_type
// =============
  template < typename T >
  class is_class_type {
    typedef char (&yes) [1];
    typedef char (&no)  [2];
    template < typename S >
    static yes check ( int S::* );
    template < typename S >
    static no check ( ... );
  public:
    static bool const value = ( sizeof( check<T>( 0 ) ) == sizeof(yes) );
  }; // is_class_type
// is_pointer_type:
// ================
  struct unused_type {};
  template < typename T >
  struct is_pointer_type {
    
    static const bool value = false;
    
    typedef unused_type pointee_type;
    
  };
  
  template < typename T >
  struct is_pointer_type<T*> {
    
    static const bool value = true;
    
    typedef T pointee_type;
    
  };
  
// is_function_type
// ================
  template < typename T >
  class is_function_type {
    
    typedef char (&no)  [1];
    typedef char (&yes) [2];
    
    template < typename S >
    static
    yes check ( S * );
    
    template < typename S >
    static
    no check ( ... );
    
  public:
    
    static bool const value =
      ( ! is_class_type<T>::value )
      &&
      ( sizeof( check<T>( * (T*)(0) ) )== sizeof( yes ) );
    
  };
  
// is_function_pointer
// ===================
  
  template < typename T >
  struct is_function_pointer {
    
    static bool const value =
      ( is_pointer_type<T>::value
        &&
        is_function_type< typename is_pointer_type<T>::pointee_type >::value );
    
  };
Note that the template is_function_type<> does not need the
is_pointer_type<> template. That is why I think that is_function_type<> is
conceptually simpler than is_function_pointer<> and my reason to prefer
this implementation to the previous one.
Best
Kai-Uwe Bux
Hmm...are you positive that your implemention meets my requirement? 
There are 2 problems after I test run your typetraits implementation:
! is_pointer_type<int>::value = true
is_pointer_type<non_fct_ptr>::value = true
is_pointer_type<fct_ptr>::value = true
is_function_pointer<fct_ptr>::value = true
! is_function_pointer<non_fct_ptr>::value = true    <----------- wrong
! is_function_pointer<fct_ptr4>::value = false      <----------- wrong
// is_class_type
// =============
   template < typename T >
   class is_class_type {
     typedef char (&yes) [1];
     typedef char (&no)  [2];
     template < typename S >
     static yes check ( int S::* );
     template < typename S >
     static no check ( ... );
   public:
     static bool const value = ( sizeof( check<T>( 0 ) ) == sizeof(yes) );
   }; // is_class_type
// is_pointer_type:
// ================
   struct unused_type {};
   template < typename T >
   struct is_pointer_type {
     static const bool value = false;
     typedef unused_type pointee_type;
   };
   template < typename T >
   struct is_pointer_type<T*> {
     static const bool value = true;
     typedef T pointee_type;
   };
// is_function_type
// ================
   template < typename T >
   class is_function_type {
     typedef char (&no)  [1];
     typedef char (&yes) [2];
     template < typename S >
     static
     yes check ( S * );
     template < typename S >
     static
     no check ( ... );
   public:
     static bool const value =
       ( ! is_class_type<T>::value )
       &&
       ( sizeof( check<T>( * (T*)(0) ) )== sizeof( yes ) );
   };
// is_function_pointer
// ===================
   template < typename T >
   struct is_function_pointer {
     static bool const value =
       ( is_pointer_type<T>::value
         &&
         is_function_type< typename is_pointer_type<T>::pointee_type 
 >::value );
   };
typedef int (*fct_ptr) ( int, int );
typedef int * non_fct_ptr;
typedef void (*fct_ptr4)(int, int, int, int);
#include <iostream>
#include <iomanip>
#define SHOW_BOOL(expr) \
   std::cout << #expr << " = " << std::boolalpha << (expr) << '\n';
int main ( void ) {
   SHOW_BOOL( ! is_pointer_type<int>::value );
   SHOW_BOOL( is_pointer_type<non_fct_ptr>::value );
   SHOW_BOOL( is_pointer_type<fct_ptr>::value );
   SHOW_BOOL( is_function_pointer<fct_ptr>::value );
   SHOW_BOOL( ! is_function_pointer<non_fct_ptr>::value );
   SHOW_BOOL( ! is_function_pointer<fct_ptr4>::value );
}