Design Improvements
Does a constraint incur runtime and space overhead? If it's checked at compile-time, you certainly don't want it to remain in the executable. Modern IDEs are clever enough to optimize away code that isn't needed in the executable. To help the compiler out, move the constraint into a separate static member function
constraints() (or any other name you like). Remember to declare this member
private so that other clients can't call it:
template <class T> struct POD_test
{
POD_test(){constraints();} //forces compile-time
//evaluation
private:
static void constraints()
{
union{ T t;} u;
}
};
At Your Beck And Call
Notice that
constraints() actually does nothing; it only declares a
local union. Since the union isn't used, the compiler may elide the
constraints() call in the constructor, thereby avoiding its overhead.
"must be POD" is only one example of the numerous constraints you can enforce. Another common constraint is "must be T." Implementing this constraint is almost trivial:
//checks whether T1 is-a T2
template <class T1, class T2> struct is_a_T2
{
is_a_T2() {constraints();}
static void constraints()
{
T1 t1;
T2& ref=t1; //error if t1 is not a T2
}
};
This constraint may be useful for example in MFC-style frameworks where all classes must be derived from a common base class. Let's test it:
is_a_T2 <C3, S1> t1; //ok, C3 is-a S1
is_a_T2 <S1, S1> t2; //ok
is_a_T2 <S1, C3> t3; //error
is_a_T2 <std::string, S1> t4; //error
is_a_T2 <int, S1> t5; //error
Here's another constraint: "must be an integral type." This one is also easy and can be implemented in many ways. One technique uses the object as an array's index. Since C++ requires that indexes shall be integral types, using any other type will cause a compilation error. I leave the implementation as an exercise to the reader.