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 );
}