#include <iostream>
struct true_type
{
enum {value = 1};
};
struct false_type
{
enum {value = 0};
};
template<typename T>
struct is_integer_impl : false_type {};
#define DECLARE_INTEGER(T) \
template<> \
struct is_integer_impl<T> : true_type {}
DECLARE_INTEGER(char);
DECLARE_INTEGER(unsigned char);
DECLARE_INTEGER(signed char);
DECLARE_INTEGER(unsigned short);
DECLARE_INTEGER(signed short);
DECLARE_INTEGER(unsigned int);
DECLARE_INTEGER(signed int);
DECLARE_INTEGER(unsigned long);
DECLARE_INTEGER(signed long);
template<typename T>
struct is_integer : is_integer_impl<T> {};
template<typename T>
struct is_class
{
typedef char yes;
typedef int no;
template<class U>
static yes doCheck(void (U::*)());
template<class U>
static no doCheck(...);
enum {value = (sizeof(doCheck<T>(0)) == sizeof(yes))};
};
template<typename T>
struct is_enum
{
enum {value = !is_integer<T>::value && !is_class<T>::value};
};
enum TestEnum
{
Item1,
Item2
};
struct TestStruct
{
};
union TestUnion
{
};
int main()
{
std::cout << is_integer<int>::value << std::endl;
std::cout << is_enum<int>::value << std::endl;
std::cout << is_class<int>::value << std::endl;
std::cout << std::endl;
std::cout << is_integer<TestStruct>::value << std::endl;
std::cout << is_enum<TestStruct>::value << std::endl;
std::cout << is_class<TestStruct>::value << std::endl;
std::cout << std::endl;
std::cout << is_integer<TestEnum>::value << std::endl;
std::cout << is_enum<TestEnum>::value << std::endl;
std::cout << is_class<TestEnum>::value << std::endl;
std::cout << std::endl;
std::cout << is_integer<TestUnion>::value << std::endl;
std::cout << is_enum<TestUnion>::value << std::endl;
std::cout << is_class<TestUnion>::value << std::endl;
return 0;
}