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! ]