|
Boost : |
From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2004-09-21 08:00:41
Terje Slettebø wrote:
> Even if we found a way to give a numerical code or something to each
> fundamental type (typical typeof-implementation), there's still enum, so we
> need some kind of is_enum-detection (which would likely require the Boost
> one).
//// Fast and portable enum detection
////
//// Notes:
//// - The test facility won't link.
//// - Thins usually done with boost libraries were emulated in a
//// very simplified form here, in order to test it with the
//// online version of the Comeau Compiler
//// Known to compile with:
//// - Comeau-online
//// - gcc 3.2.3 (mingw)
//// - bcc 5.4.6
//// - msvc 13.10.3077
// tags 'n tagging types
enum { no = 1, yes = 2 };
typedef char (& no_type )[no];
typedef char (& yes_type)[yes];
// is there a standard conversion sequence to int ?
struct int_conv_type { int_conv_type(int); };
no_type int_conv_tester (...);
yes_type int_conv_tester (int_conv_type);
// is this pointer void compatible ?
no_type vfnd_ptr_tester (const volatile char *);
no_type vfnd_ptr_tester (const volatile short *);
no_type vfnd_ptr_tester (const volatile int *);
no_type vfnd_ptr_tester (const volatile long *);
no_type vfnd_ptr_tester (const volatile double *);
no_type vfnd_ptr_tester (const volatile float *);
no_type vfnd_ptr_tester (const volatile bool *);
yes_type vfnd_ptr_tester (const volatile void *);
// strips the reference, adds a pointer
template <typename T> T* add_ptr(T&);
// converts a bool to yes_type / no_type
template <bool C> struct bool_to_yesno { typedef no_type type; };
template <> struct bool_to_yesno<true> { typedef yes_type type; };
// is enum metafunction
template <typename T>
struct is_enum
{
private:
typedef is_enum self_type;
static T & arg;
public:
// if T is standard-convertible to int and T* is not convertible to
// any fundamental type but void, T is an enum.
static const bool value
= ( (sizeof(int_conv_tester(arg)) == sizeof(yes_type))
&& (sizeof(vfnd_ptr_tester(add_ptr(arg))) == sizeof(yes_type)) );
typedef typename bool_to_yesno<self_type::value>::type type;
};
// void specializations
template <>
struct is_enum<void>
{
typedef no_type type;
static const bool value = false;
};
template <>
struct is_enum<void const>
{
typedef no_type type;
static const bool value = false;
};
template <>
struct is_enum<void volatile>
{
typedef no_type type;
static const bool value = false;
};
template <>
struct is_enum<void const volatile>
{
typedef no_type type;
static const bool value = false;
};
////////////////////////////////////
// Prove it works...
// Test types //
enum an_enum { a,b,c };
int i = 0;
struct X
{
void memb();
// try to confuse is_enum with user-defined
// implicit conversion
operator int();
operator const double*();
operator double();
};
union Y
{
void memb();
// try to confuse is_enum with user-defined
// implicit conversion
operator int();
operator const double*();
operator double();
};
void func();
X o;
Y u;
int & iref (i);
float f = 0.0f;
void* vptr = &i;
char carr[6] = "hello";
char * cstr = carr;
double * dptr = (double*) 0L;
// Compile time assertion facility //
// extract a yes_type / no_type pseudo-instance
// from the is_enum metafunction
template <typename T>
typename is_enum<T>::type func_wrapper(T);
// try to initialize a reference to char array with the tag's size with
// a yes_type / no_type tagging type as assertion
#define ASSERT(ord,expected,expr) \
char (& __assertion##ord##__) [ expected ] = func_wrapper( expr )
// Assert correctness //
ASSERT( 1, yes , a);
ASSERT( 2, no , i);
ASSERT( 3, no , o);
ASSERT( 4, no , & X::memb);
ASSERT( 5, no , * func);
ASSERT( 6, no , func);
ASSERT( 7, no , & func);
ASSERT( 8, no , iref);
ASSERT( 9, no , u);
ASSERT(10, no , vptr);
ASSERT(11, no , carr);
ASSERT(12, no , cstr);
ASSERT(13, no , f);
ASSERT(14, no , dptr);
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk