Boost logo

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