Boost logo

Boost :

From: John Maddock (John_Maddock_at_[hidden])
Date: 2000-02-24 06:58:29


I have a feeling that I'm going to regret bringing this up again - but here
goes anyway. I've been experimenting with compile time asserts and I think
I have an implementation that meets most of the requirements:

 Easy to use.
 Generates errors on the line of the assertion (for compilers tested so
far).
 Can be used at namespace, class, or function scope.
 Generates neither code nor data.

On the down side - it uses macros, and use at namespace scope can lead to
unexpected name conflicts if used in multiple headers (there are
workarounds though). I've also had problem with VC6 not recognising
sizeof(member_variable) as a compile time constant - but that's a bug in
sizeof not related to the assertion code (as far as I can tell).

Here are the typical error messages for the compilers I've tested so far:

VC6:
t2.cpp(320) : error C2027: use of undefined type 'ct_assert<0>'
        t2.cpp(332) : see reference to function template instantiation
'void __thiscall Bill<int,char>::f(int,int)' being compiled

g++ 2.95
t2.cpp: In method `void Bill<int,char>::f<int, int>(int, int)':
t2.cpp:332: instantiated from here
t2.cpp:320: `sizeof' applied to incomplete type `boost::ct_assert<false>'

C++ Builder:
Error E2450 t2.cpp 320: Undefined structure 'boost::ct_assert<0>' in
function f<int,int>(int,int)
Error E2109 t2.cpp 320: Not an allowed type in function f<int,int>(int,int)
Error E2450 t2.cpp 320: Undefined structure 'boost::ct_assert<0>' in
function f<int,int>(int,int)
Error E2109 t2.cpp 320: Not an allowed type in function f<int,int>(int,int)

Probably the name ct_assert sould be extended to something more obvious
like:
"compile_time_assert"
or
"condition_must_be_true"
or even:
"this_should_not_compile"

anyway here is the code, the test code is based on Steve Cleary's test
program:

namespace boost{

template <bool> struct ct_assert;

template <> struct ct_assert<true>{};

}

#define BOOST_CT_ASSERT( B ) enum { BOOST_JOIN(_boost_assert_enum_,
__LINE__) = sizeof(::boost::ct_assert<(B)>) }
//#define BOOST_CT_ASSERT(condition) struct { int : (condition) ? 0 : -1; }

#define BOOST_DO_JOIN( X, Y ) X ## Y
#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y )

// Namespace scope
BOOST_CT_ASSERT(sizeof(int) == 4);
BOOST_CT_ASSERT(sizeof(char) == 1);
//BOOST_CT_ASSERT(sizeof(int) == sizeof(char)); // will not compile

// Function (block) scope
void f()
{
  BOOST_CT_ASSERT(sizeof(int) == 4);
  BOOST_CT_ASSERT(sizeof(char) == 1);
  //BOOST_CT_ASSERT(sizeof(int) == sizeof(char)); // should not compile
}

struct Bob
{
  private: // can be in private, to avoid namespace pollution
    BOOST_CT_ASSERT(sizeof(int) == 4);
    BOOST_CT_ASSERT(sizeof(char) == 1);
// BOOST_CT_ASSERT(sizeof(int) == sizeof(char); // will not compile
  public:

  // Member function scope: provides access to member variables
  int x;
  char c;
  int f()
  {
#ifndef _MSC_VER // broken sizeof in VC6
    BOOST_CT_ASSERT(sizeof(x) == 4);
    BOOST_CT_ASSERT(sizeof(c) == 1);
#endif
    //BOOST_CT_ASSERT(sizeof(x) == sizeof(c)); // should not compile
    return x;
  }
};

// Template class scope
template <class Int, class Char>
struct Bill
{
  private: // can be in private, to avoid namespace pollution
    BOOST_CT_ASSERT(sizeof(Int) == 4);
    BOOST_CT_ASSERT(sizeof(Char) == 1);
// BOOST_CT_ASSERT(sizeof(Int) == sizeof(Char)); // should not compile
when instantiated
  public:

  // Template member function scope: provides access to member variables
  Int x;
  Char c;
  template <class Int2, class Char2>
  void f(Int2 y, Char2 d)
  {
    BOOST_CT_ASSERT(sizeof(Int) == sizeof(Int2));
    BOOST_CT_ASSERT(sizeof(Char) == sizeof(Char2));
    //BOOST_CT_ASSERT(sizeof(Int) == sizeof(Char)); // should not compile
when instantiated
  }
};

void test_Bill() // BOOST_CT_ASSERTs are not triggerred until instantiated
{
  Bill<int, char> z;
  //Bill<int, int> bad; // will not compile
  int i = 3;
  char ch = 'a';
  z.f(i, ch);
  //z.f(i, i); // should not compile
}

int main(){ return 0; }

- John.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk