Compile time assertion

Friday, January 18th, 2008

Yesterday I finally found a use for compile time checking. I remembered reading this up in Andrei's book 'Modern C++ Design'. So I got down to implementing it in VS.NET 2005.

His code (code below) seemed to work well in theory, but knowing MS, that's as far it goes.

template<bool> struct CompileTimeChecker
{
     CompileTimeChecker(...);
};
template<> struct CompileTimeChecker<false> { };
#define STATIC_CHECK(expr, msg)
     {
          class ERROR_##msg {};
          (void)sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg())));
     }

Turns out that MS VS.Net had some complaints about the code above…

error C2066: cast to function type is illegalerror C2070: 'CompileTimeChecker (main::ERROR_ONE_NOT_EQUAL_TO_ONE (__cdecl *)(void))': illegal sizeof operand

At first I thought I’d take the easy way out and just throw an error using a #pragma. But then that would beat the very purpose of the code being compiler independent. After some 30 mins of trial and error, managed to get the same code (code below) working with a few minor modifications.

template<bool> struct CompileTimeChecker
{
     CompileTimeChecker(...){};
};

template<> struct CompileTimeChecker<false> { };

#define STATIC_CHECK(expr, msg)
{
     class ERROR_##msg {};
     ERROR_##msg y ;
     (void)sizeof(CompileTimeChecker<(expr) != 0>((y)));
}

Now calling something like…

STATIC_CHECK(sizeof(char)>sizeof(int), SIZEOF_CHAR_NOT_GT_SIZEOF_INT) ;

will result in a compile time error that looks something like this…

error C2440: '<function-style-cast>' : cannot convert from 'main::ERROR_SIZEOF_CHAR_NOT_GT_SIZEOF_INT' to 'CompileTimeChecker'> No constructor could take the source type, or constructor overload resolution was ambiguous

Until next time, happy coding!