#ifndef SYNTH_H #define SYNTH_H #include template class IsFundaT { public: enum Fundamenal { Yes = 0, No = 1}; }; // macro to specialize for fundamental types #define MK_FUNDA_TYPE(T) \ template<> class IsFundaT { \ public: \ enum Fundamenal { Yes = 1, No = 0 }; \ }; MK_FUNDA_TYPE(void) MK_FUNDA_TYPE(bool) MK_FUNDA_TYPE(char) MK_FUNDA_TYPE(signed char) MK_FUNDA_TYPE(unsigned char) MK_FUNDA_TYPE(wchar_t) MK_FUNDA_TYPE(signed short) MK_FUNDA_TYPE(unsigned short) MK_FUNDA_TYPE(signed int) MK_FUNDA_TYPE(unsigned int) MK_FUNDA_TYPE(signed long) MK_FUNDA_TYPE(unsigned long) #if LONGLONG_EXISTS MK_FUNDA_TYPE(signed long long) MK_FUNDA_TYPE(unsigned long long) #endif // LONGLONG_EXISTS MK_FUNDA_TYPE(float) MK_FUNDA_TYPE(double) MK_FUNDA_TYPE(long double) #undef MK_FUNDA_TYPE template void fundamental_test (T const& t) { if (IsFundaT::Yes) { std::cout << "T is fundamental type" << std::endl; } else { std::cout << "T is no fundamental type" << std::endl; } } template class CompoundT { // primary template public: enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 0, IsFuncT = 0, IsPtrMemT = 0 }; typedef T BaseT; typedef T BottomT; typedef CompoundT ClassT; }; template class CompoundT { // partial specialization for references public: enum { IsPtrT = 0, IsRefT = 1, IsArrayT = 0, IsFuncT = 0, IsPtrMemT = 0 }; typedef T BaseT; typedef typename CompoundT::BottomT BottomT; typedef CompoundT ClassT; }; template class CompoundT { // partial specialization for pointers public: enum { IsPtrT = 1, IsRefT = 0, IsArrayT = 0, IsFuncT = 0, IsPtrMemT = 0 }; typedef T BaseT; typedef typename CompoundT::BottomT BottomT; typedef CompoundT ClassT; }; template class CompoundT { // partial specialization for arrays public: enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 1, IsFuncT = 0, IsPtrMemT = 0 }; typedef T BaseT; typedef typename CompoundT::BottomT BottomT; typedef CompoundT ClassT; }; template class CompoundT { // partial specialization for empty arrays public: enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 1, IsFuncT = 0, IsPtrMemT = 0 }; typedef T BaseT; typedef typename CompoundT::BottomT BottomT; typedef CompoundT ClassT; }; template class CompoundT { // partial specialization for pointer-to-members public: enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 0, IsFuncT = 0, IsPtrMemT = 1 }; typedef T BaseT; typedef typename CompoundT::BottomT BottomT; typedef C ClassT; }; template class CompoundT { public: enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 0, IsFuncT = 1, IsPtrMemT = 0 }; typedef R BaseT(); typedef R BottomT(); typedef CompoundT ClassT; }; template class CompoundT { public: enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 0, IsFuncT = 1, IsPtrMemT = 0 }; typedef R BaseT(P1); typedef R BottomT(P1); typedef CompoundT ClassT; }; template class CompoundT { public: enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 0, IsFuncT = 1, IsPtrMemT = 0 }; typedef R BaseT(P1); typedef R BottomT(P1); typedef CompoundT ClassT; }; template class IsFunctionT { private: typedef char One; typedef struct { char a[2]; } Two; template static One test(...); template static Two test(U (*)[1]); public: enum { Yes = sizeof(IsFunctionT::test(0)) == 1 }; enum { No = !Yes }; }; template class IsFunctionT { public: enum { Yes = 0 }; enum { No = !Yes }; }; template<> class IsFunctionT { public: enum { Yes = 0 }; enum { No = !Yes }; }; template<> class IsFunctionT { public: enum { Yes = 0 }; enum { No = !Yes }; }; struct SizeOverOne { char c[2]; }; template::IsFuncT && !CompoundT::IsArrayT> class ConsumeUDC { public: operator T() const; }; template class ConsumeUDC { }; template class ConsumeUDC { }; char enum_check(bool); char enum_check(char); char enum_check(signed char); char enum_check(unsigned char); char enum_check(wchar_t); char enum_check(signed short); char enum_check(unsigned short); char enum_check(signed int); char enum_check(unsigned int); char enum_check(signed long); char enum_check(unsigned long); #if LONGLONG_EXISTS char enum_check(signed long long); char enum_check(unsigned long long); #endif // LONGLONG_EXISTS // avoid accidental conversions from float to int char enum_check(float); char enum_check(double); char enum_check(long double); SizeOverOne enum_check(...); // catch all template class IsEnumT { public: enum { Yes = IsFundaT::No && !CompoundT::IsRefT && !CompoundT::IsPtrT && !CompoundT::IsPtrMemT && sizeof(enum_check(ConsumeUDC()))==1 }; enum { No = !Yes }; }; template class IsClassT { public: enum { Yes = IsFundaT::No && IsEnumT::No && !CompoundT::IsPtrT && !CompoundT::IsRefT && !CompoundT::IsArrayT && !CompoundT::IsPtrMemT && !CompoundT::IsFuncT }; enum { No = !Yes }; }; template class TypeT { public: enum { IsFundaT = IsFundaT::Yes, IsPtrT = CompoundT::IsPtrT, IsRefT = CompoundT::IsRefT, IsArrayT = CompoundT::IsArrayT, IsFuncT = CompoundT::IsFuncT, IsPtrMemT = CompoundT::IsPtrMemT, IsEnumT = IsEnumT::Yes, IsClassT = IsClassT::Yes }; }; template void check() { if (TypeT::IsFundaT) { std::cout << " IsFundaT "; } if (TypeT::IsPtrT) { std::cout << " IsPtrT "; } if (TypeT::IsRefT) { std::cout << " IsRefT "; } if (TypeT::IsArrayT) { std::cout << " IsArrayT "; } if (TypeT::IsFuncT) { std::cout << " IsFuncT "; } if (TypeT::IsPtrMemT) { std::cout << " IsPtrMemT "; } if (TypeT::IsEnumT) { std::cout << " IsEnumT "; } if (TypeT::IsClassT) { std::cout << " IsClassT "; } std::cout << std::endl; } // check by passing type as function call argument template void checkT (T) { check(); // for pointer types check type of what they refer to if (TypeT::IsPtrT || TypeT::IsPtrMemT) { check::BaseT>(); } } void test_synth() { fundamental_test(Vector()); fundamental_test(int()); std::cout << "int:" << std::endl; check(); std::cout << "int&:" << std::endl; check(); std::cout << "char[42]:" << std::endl; check(); std::cout << "MyClass:" << std::endl; check>(); std::cout << "ptr to enum:" << std::endl; E* ptr = 0; checkT(ptr); std::cout << "42:" << std::endl; checkT(42); std::cout << "test_synth()():" << std::endl; checkT(test_synth); /* std::cout << "memptr to array:" << std::endl; char (MyClass::* memptr) [] = 0; checkT(memptr); */ } #endif // SYNTH_H