#ifndef BOOST_TYPE_TRAITS_HPP #define BOOST_TYPE_TRAITS_HPP #include #include /************************************************************************** CONTENTS ~~~~~~~~ 1: Helper Macros for builtin compiler support. 2: Fundamental type operations: Usage: "class_name::type" performs indicated transformation on T. remove_volatile - remove top level volatile qualifier remove_const - remove top level const qualifier remove_cv - remove top level const/volatile qualifiers remove_reference - remove top level reference if present remove_bounds - remove top level array bound if present 3: Fundamental type properties Usage: "class_name::value" is true if indicated property is true, false otherwise is_fundamental_type - builtin required by standard is_builtin_type - all builtins including compiler specific extentions is_void - true if T is void is_class_type - T is a struct class or union is_empty - T is an empty struct or class is_same_type - T and U are same type is_const - T is const is_volatile - T is volatile is_reference - T is a reference is_pointer - T is a pointer is_member_pointer - T is a pointer to a member is_array - T is an array is_enum - T is an enum has_trivial_constructor- T has trivial default constructor has_trivial_copy - T has trivial copy constructor has_trivial_assign - T has trivial assignment operator has_trivial_destructor - T has trivial destructor is_POD - T is a POD type /**************************************************************************/ // // Helper macros for builitin compiler support. // If your compiler has builtin support for any of the following // traits concepts, then redefine the appropriate macros to pick // up on the compiler support: // // BOOST_IS_ENUM(T) should evaluate to true if T is an enumerator type, false otherwise. // BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if T() <==> memset // BOOST_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy // BOOST_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy // BOOST_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect #define BOOST_IS_ENUM(T) false #define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) false #define BOOST_HAS_TRIVIAL_COPY(T) false #define BOOST_HAS_TRIVIAL_ASSIGN(T) false #define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) false /**************************************************************************/ namespace boost{ // // start with fundamental type operations: namespace _Jm{ // // implementation helper: // template struct cv_traits_imp{}; template struct cv_traits_imp { static const bool is_const = false; static const bool is_volatile = false; typedef T non_const_type; typedef T non_volatile_type; typedef T unqualified_type; static const char* what() { return ""; } }; template struct cv_traits_imp { static const bool is_const = true; static const bool is_volatile = false; typedef T non_const_type; typedef const T non_volatile_type; typedef T unqualified_type; static const char* what() { return "const"; } }; template struct cv_traits_imp { static const bool is_const = false; static const bool is_volatile = true; typedef volatile T non_const_type; typedef T non_volatile_type; typedef T unqualified_type; static const char* what() { return "volatile"; } }; template struct cv_traits_imp { static const bool is_const = true; static const bool is_volatile = true; typedef volatile T non_const_type; typedef const T non_volatile_type; typedef T unqualified_type; static const char* what() { return "const volatile"; } }; } // namespace _Jm // * convert a type T to a non-volatile type - remove_volatile template struct remove_volatile { typedef typename _Jm::cv_traits_imp::non_volatile_type type; }; template struct remove_volatile{ typedef T& type; }; // * convert a type T to non-const type - remove_const template struct remove_const { typedef typename _Jm::cv_traits_imp::non_const_type type; }; template struct remove_const{ typedef T& type; }; // convert a type T to a non-cv-qualified type - remove_cv template struct remove_cv { typedef typename _Jm::cv_traits_imp::unqualified_type type; }; template struct remove_cv{ typedef T& type; }; // * convert a type T to a non-reference if it is one - remove_reference template struct remove_reference{ typedef T type; }; template struct remove_reference{ typedef T type; }; // are these well formed??? //template struct remove_reference{ typedef T type; }; //template struct remove_reference{ typedef T type; }; //template struct remove_reference{ typedef T type; }; // * convert an array type to underlying non-array type - remove_bounds template struct remove_bounds{ typedef T type; }; template struct remove_bounds{ typedef T type; }; /**************************************************************************/ // // fundamental property classes: //* is a type T declared const - is_const template struct is_const { static const bool value = _Jm::cv_traits_imp::is_const; }; //* is a type T declared volatile - is_volatile template struct is_volatile { static const bool value = _Jm::cv_traits_imp::is_volatile; }; //* is a type T the same as type U - is_same_type template struct is_same_type { static const bool value = false; }; template struct is_same_type { static const bool value = true; }; //* is a type T a fundamental type described in the standard - is_fundamental_type template struct is_fundamental_type{ static const bool value = false; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; template <> struct is_fundamental_type{ static const bool value = true; }; //* is a type T void - is_void template struct is_void{ static const bool value = false; }; template <> struct is_void{ static const bool value = true; }; //* is a type T a built in type - is_builtin_type // specialise for compiler defined extentions: template struct is_builtin_type{ static const bool value = is_fundamental_type::value; }; #ifdef ULLONG_MAX template <> struct is_builtin_type{ static const bool value = true; }; template <> struct is_builtin_type{ static const bool value = true; }; #endif #if defined(__BORLANDC__) || defined(_MSC_VER) template <> struct is_builtin_type<__int64>{ static const bool value = true; }; template <> struct is_builtin_type{ static const bool value = true; }; #endif //* is a type T a reference type - is_reference template struct is_reference{ static const bool value = false; }; template struct is_reference{ static const bool value = true; }; //* is a type T a pointer type (including function pointers) - is_pointer template struct is_pointer{ static const bool value = false; }; template struct is_pointer{ static const bool value = true; }; template struct is_pointer{ static const bool value = true; }; template struct is_pointer{ static const bool value = true; }; template struct is_pointer{ static const bool value = true; }; template struct is_pointer{ static const bool value = true; }; #ifdef __BORLANDC__ // this doesn't work: //template struct is_pointer{ static const bool value = true; }; #endif //*? is a type T a regular function pointer - is_function_pointer // there appears to be no implemenation for this?? //* is a type T a member function pointer - is_member_pointer template struct is_member_pointer{ static const bool value = false; }; template struct is_member_pointer{ static const bool value = true; }; //* is a type T an array - is_array template struct is_array{ static const bool value = false; }; template struct is_array{ static const bool value = true; }; //*? is a type T an enum - is_enum template struct is_enum{ static const bool value = BOOST_IS_ENUM(T); }; //*? is a type T a composite type (class/struct/union) - is_class_type - can be implemented if is_enum can be (and vice-versa). template struct is_class_type { static const bool value = !(is_pointer::value || is_reference::value || is_array::type>::value || is_enum::type>::value || is_builtin_type::type>::value); }; //* is a type T an empty composite type - is_empty - only strictly implementable if we have is_class_type namespace _Jm{ template struct empty_helper{ static const bool value = false; }; template struct empty_helper { private: struct t : public T { int i[256]; }; struct t2 { int i[256]; }; public: static const bool value = (sizeof(t) == sizeof(t2)); }; } // namespace _jm template struct is_empty { static const bool value = _Jm::empty_helper::value>::value; }; namespace _Jm{ // // helper class for determining whether a type is a POD, // when this gets called cv-modifiers have already been stripped // from type T. // template struct POD_logic { static const bool value = is_builtin_type::value || is_pointer::value || is_reference::value || is_enum::value; }; template struct POD_logic { // recursion: static const bool value = POD_logic::value; }; } // namspace _Jm // SGI style type trait information: template struct has_trivial_constructor { static const bool value = _Jm::POD_logic::type>::value || BOOST_HAS_TRIVIAL_CONSTRUCTOR(T); }; template struct has_trivial_copy { static const bool value = _Jm::POD_logic::type>::value || BOOST_HAS_TRIVIAL_COPY(T); }; template struct has_trivial_assign { static const bool value = _Jm::POD_logic::type>::value || BOOST_HAS_TRIVIAL_ASSIGN(T); }; template struct has_trivial_destructor { static const bool value = _Jm::POD_logic::type>::value || BOOST_HAS_TRIVIAL_DESTRUCTOR(T); }; template struct is_POD { static const bool value = has_trivial_constructor::value && has_trivial_copy::value && has_trivial_assign::value && has_trivial_destructor::value; }; } // namespace boost /**************************************************************************/ // // undefine helper macro's: // #undef BOOST_IS_ENUM #undef BOOST_HAS_TRIVIAL_CONSTRUCTOR #undef BOOST_HAS_TRIVIAL_COPY #undef BOOST_HAS_TRIVIAL_ASSIGN #undef BOOST_HAS_TRIVIAL_DESTRUCTOR /**************************************************************************/ #endif // include guard #include #include using namespace boost; #ifdef __BORLANDC__ #pragma option -w-ccc -w-rch -w-eff #endif // // define tests here unsigned failures = 0; #define value_test(v, x) if(v == x) /*std::cout << "checking value of " << #x << "...OK" << std::endl*/;\ else{++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;} #define type_test(v, x) if(is_same_type::value) /*std::cout << "checking type of " << #x << "...OK" << std::endl*/;\ else{++failures; std::cout << "checking type of " << #x << "...failed (type was: " << typeid(x).name() << " expected: " << typeid(v).name() << ")" << std::endl;} struct UDT { UDT(); ~UDT(); UDT(const UDT&); UDT& operator=(const UDT&); int i; void f1(); int f2(); int f3(int); int f4(int, float); }; enum enum_UDT{ one, two, three }; struct empty_UDT{}; int main() { std::cout << "Checking type operations..." << std::endl << std::endl; type_test(int, remove_reference::type) type_test(const int, remove_reference::type) type_test(int, remove_reference::type) type_test(const int, remove_reference::type) //type_test(volatile int, remove_reference::type) //type_test(int, remove_reference::type) //type_test(int, remove_reference::type) type_test(int, remove_const::type) type_test(volatile int, remove_const::type) type_test(volatile int, remove_const::type) type_test(int, remove_const::type) type_test(int*, remove_const::type) type_test(int, remove_volatile::type) type_test(const int, remove_volatile::type) type_test(const int, remove_volatile::type) type_test(int, remove_volatile::type) type_test(int*, remove_volatile::type) type_test(int, remove_cv::type) type_test(int, remove_cv::type) type_test(int, remove_cv::type) type_test(int, remove_cv::type) type_test(int*, remove_cv::type) type_test(int*, remove_cv::type) type_test(int*, remove_cv::type) type_test(int, remove_bounds::type) type_test(int*, remove_bounds::type) type_test(int, remove_bounds::type) type_test(int[3], remove_bounds::type) std::cout << std::endl << "Checking type properties..." << std::endl << std::endl; value_test(false, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_fundamental_type::value) value_test(true, is_void::value) value_test(false, is_void::value) value_test(false, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) #ifdef ULLONG_MAX value_test(true, is_builtin_type::value) value_test(true, is_builtin_type::value) #endif #if defined(__BORLANDC__) || defined(_MSC_VER) value_test(true, is_builtin_type<__int64>::value) value_test(true, is_builtin_type::value) #endif value_test(false, is_reference::value) value_test(true, is_reference::value) value_test(true, is_reference::value) value_test(true, is_reference::value) value_test(false, is_pointer::value) value_test(false, is_pointer::value) value_test(true, is_pointer::value) value_test(true, is_pointer::value) value_test(true, is_pointer::value) value_test(true, is_pointer::value) typedef void(*f1)(); typedef int(*f2)(int); typedef int(*f3)(int, bool); typedef void (UDT::*mf1)(); typedef int (UDT::*mf2)(); typedef int (UDT::*mf3)(int); typedef int (UDT::*mf4)(int, float); value_test(true, is_pointer::value) value_test(true, is_pointer::value) value_test(true, is_pointer::value) value_test(true, is_pointer::value) value_test(true, is_pointer::value) value_test(true, is_pointer::value) value_test(true, is_pointer::value) #ifdef __BORLANDC__ typedef void (__closure *cf1)(); typedef int (__closure *cf2)(); typedef int (__closure *cf3)(int); typedef int (__closure *cf4)(int, float); value_test(true, is_pointer::value) value_test(true, is_pointer::value) value_test(true, is_pointer::value) value_test(true, is_pointer::value) #endif value_test(false, is_member_pointer::value) value_test(false, is_member_pointer::value) value_test(false, is_member_pointer::value) value_test(true, is_member_pointer::value) value_test(true, is_member_pointer::value) value_test(true, is_member_pointer::value) value_test(true, is_member_pointer::value) value_test(false, is_array::value) value_test(false, is_array::value) value_test(true, is_array::value) value_test(true, is_array::value) value_test(true, is_array::value) value_test(false, is_enum::value) value_test(true, is_enum::value) // this will fail value_test(false, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_class_type::value) // this will fail value_test(true, is_class_type::value) value_test(true, is_class_type::value) value_test(true, is_class_type::value) value_test(true, is_class_type::value) value_test(true, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_class_type::value) value_test(false, is_empty::value) value_test(false, is_empty::value) value_test(false, is_empty::value) value_test(false, is_empty::value) value_test(false, is_empty::value) value_test(false, is_empty::value) value_test(false, is_empty::value) value_test(false, is_empty::value) value_test(true, is_empty::value) // this may fail on some compilers //value_test(false, is_empty::value) // !!! this doesn't compile value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) value_test(false, has_trivial_constructor::value) value_test(true, has_trivial_constructor::value) // this will fail value_test(true, has_trivial_constructor::value) // this will fail value_test(true, has_trivial_copy::value) value_test(true, has_trivial_copy::value) value_test(true, has_trivial_copy::value) value_test(true, has_trivial_copy::value) value_test(true, has_trivial_copy::value) value_test(false, has_trivial_copy::value) value_test(true, has_trivial_copy::value) value_test(true, has_trivial_copy::value) value_test(true, has_trivial_copy::value) value_test(true, has_trivial_copy::value) value_test(true, has_trivial_copy::value) value_test(true, has_trivial_copy::value) value_test(false, has_trivial_copy::value) value_test(true, has_trivial_copy::value) // this will fail value_test(true, has_trivial_copy::value) // this will fail value_test(true, has_trivial_assign::value) value_test(true, has_trivial_assign::value) value_test(true, has_trivial_assign::value) value_test(true, has_trivial_assign::value) value_test(true, has_trivial_assign::value) value_test(false, has_trivial_assign::value) value_test(true, has_trivial_assign::value) value_test(true, has_trivial_assign::value) value_test(true, has_trivial_assign::value) value_test(true, has_trivial_assign::value) value_test(true, has_trivial_assign::value) value_test(true, has_trivial_assign::value) value_test(false, has_trivial_assign::value) value_test(true, has_trivial_assign::value) // this will fail value_test(true, has_trivial_assign::value) // this will fail value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) value_test(false, has_trivial_destructor::value) value_test(true, has_trivial_destructor::value) // this will fail value_test(true, has_trivial_destructor::value) // this will fail value_test(true, is_POD::value) value_test(true, is_POD::value) value_test(true, is_POD::value) value_test(true, is_POD::value) value_test(true, is_POD::value) value_test(false, is_POD::value) value_test(true, is_POD::value) value_test(true, is_POD::value) value_test(true, is_POD::value) value_test(true, is_POD::value) value_test(true, is_POD::value) value_test(true, is_POD::value) value_test(false, is_POD::value) value_test(true, is_POD::value) // this will fail value_test(true, is_POD::value) // this will fail std::cout << std::endl << "Tests completed (" << failures << " failures)... press any key to exit"; std::cin.get(); }