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