#ifndef CONSTRAINTS_H #define CONSTRAINTS_H /////////////////////////////////////////////////////////////// // constraints.h - compile time type tests // // // // Jim Fawcett, CSE687 - Object Oriented Design, Spring 2005 // /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// // Constraints were described in detail in: // // "Imperfect C++", Matthew Wilson, Addison-Wesley, 2005 // /////////////////////////////////////////////////////////////// /* * Constraints are template classes that: * 1. provide a private constraints() function that is never * called. Its purpose is to fail compilation if the * constraint is violated. * 2. provide destructors that define a function pointer to * to the constraints function, to ensure that it is * compiled. * 3. provide macros that provide a pseudo function call syntax * * There are examples of constraints used in the POD_veener from * the veneers project. */ ///////////////////////////////////////////////// // Is_Derived ///////////////////////////////////////////////// template struct Is_Derived { /////////////////////////////////////////////// // define function pointer to make sure // that function is compiled, and so checked ~Is_Derived() { void(*p)(D*, B*) = constraints; } private: /////////////////////////////////////////////// // won't compile unless D derives from B static void constraints(D* pD, B* pB) { pB = pD; } }; ///////////////////////////////////////////////// // macro to provide pseudo function #define Is_Derived(D,B) Is_Derived() // ///////////////////////////////////////////////// // Is_Pointer ///////////////////////////////////////////////// template struct Is_Pointer { ~Is_Pointer() { void(*p)() = constraints; } private: /////////////////////////////////////////////// // won't compile unless P is a pointer type static void constraints() { T t; *t; } }; #define Is_Pointer(T) Is_Pointer() ///////////////////////////////////////////////// // Is_POD ///////////////////////////////////////////////// template struct Is_POD { /////////////////////////////////////////////// // Only PODS can be members of unions ~Is_POD() { void(*p)() = constraints; } private: static void constraints() { union { T T_Is_Not_POD; }; } }; #define Is_POD(T) Is_POD() // ///////////////////////////////////////////////// // Is_Same_Size ///////////////////////////////////////////////// template struct Is_Same_Size { /////////////////////////////////////////////// // Will declare i[0] if not same size ~Is_Same_Size() { void(*p)() = constraints; } private: static void constraints() { const int U_Not_Same_Size_As_V = (sizeof(U) == sizeof(V)); int i[U_Not_Same_Size_As_V]; i[0]; } }; #define Is_Same_Size(U,V) Is_Same_Size() // ///////////////////////////////////////////////// // Is_Clonable ///////////////////////////////////////////////// template struct Is_Clonable { /////////////////////////////////////////////// // Will fail if no clone() function ~Is_Clonable() { void(*p)() = constraints; } private: static void constraints() { T().clone(); } }; #define Is_Clonable(T) Is_Clonable() ///////////////////////////////////////////////// // Run-Time comparison of the sizes of two types: template struct is_same_size { static const bool value = sizeof(A) == sizeof(B); }; #define is_same_size(U,V) is_same_size::value #endif