is_abstract_class implementation!

43 views
Skip to first unread message

Rani Sharoni

unread,
Jul 11, 2002, 5:40:43 PM7/11/02
to
Hello All:

Lately I noticed that EDG started to support (review status) issue
#337 (http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#337)
Which say that attempt to create array of abstract class type will
also cause the type deduction to fail. This is quite natural addition
to 14.8.2/2 (reason 1) and there are probably more cases to add.

With this new "failure" I (and maybe others) implemented the
is_abstract_class traits. I hope that some programmers will find it
helpful.

template<typename T>
struct is_abstract_class
{
private:
//
// remove other "non-arrayable" types
// references, void and function types
//
typedef typename select<is_reference<T>::result, int, T>::result T1;
typedef typename select<is_void<T1>::result, int, T1>::result T2;
typedef typename select<is_function<T2>::result, int, T2>::result T3;

typedef char (&yes)[1];
typedef char (&no) [2];

//
// Deduction fails if U is void, function type,
// reference type (14.8.2/2)or an abstract class type
// according to review status issue #337
// http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#337
//
template<typename U>
static no check(U (*)[1]);

template<typename U>
static yes check(...);

public:
static const bool result =
sizeof(check<T3>(0)) == sizeof(yes);
};


The boost like traits implementation - below.

The following simple test compiled fine using Comeau (EDG FE) online:

struct A { virtual ~A() = 0; };

typedef int Test[ is_abstract_class<A>::result];

struct B {};
typedef int Test[!is_abstract_class<B>::result];
typedef int Test[!is_abstract_class<int>::result];
typedef int Test[!is_abstract_class<int(char,double)>::result];
typedef int Test[!is_abstract_class<int&>::result];
typedef int Test[!is_abstract_class<void>::result];


Boost like traits (is_function is not trivial):

template<bool B, typename T1, typename T2>
struct select { typedef T1 result; };

template<typename T1, typename T2>
struct select<false, T1, T2> { typedef T2 result; };

template<typename T1, typename T2>
struct is_same_type { static const bool result = false; };

template<typename T>
struct is_same_type<T, T> { static const bool result = true; };

template<typename>
struct is_reference { static const bool result = false; };

template<typename T>
struct is_reference<T&> { static const bool result = true; };


template<typename T>
struct is_void
{
static const bool result =
is_same_type<T , void>::result ||
is_same_type<T , const void>::result ||
is_same_type<T , volatile void>::result ||
is_same_type<T , const volatile void>::result;
};


template<typename T>
struct is_function
{
private:
typedef typename select<is_reference<T>::result, int, T>::result T1;
typedef typename select<is_void<T1>::result, int , T1>::result T2;

template<typename U>
struct UserConvert { UserConvert(U); };

typedef char (&yes)[1];
typedef char (&no) [2];

//
// suggested by Peter Dimov
// function is the only basic type that implicitly
// comvertable (standard conversion) to pointer of its type
//
static yes check(UserConvert<T2*>);
static no check(...);

static T2& getT();

public:
static const bool result =
sizeof( check(getT()) ) == sizeof(yes);
};


Enjoy,
Rani

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Reply all
Reply to author
Forward
0 new messages