skip to content

Pre-C++11 Static Assertions Without Boost

Update: This is now part of my assertion library.

In the implementation of my cross platform C++ assertion library I used a self-contained implementation of a STATIC_ASSERT macro usable in pre-c++11 projects that can’t or don’t want to rely on Boost.

I originally wrote it as an answer to a question on Stackoverflow.


STATIC_ASSERT(expression, message);

When the static assertion test fails, a compiler error message that somehow contains the “STATIC_ASSERTION_FAILED_AT_LINE_xxx_message” string is generated.

The only restriction is that message has to be a valid C++ identifier: you need to separate words with e.g. underscores and it cannot start with a digit.


bool want_pony = true;
STATIC_ASSERT(!want_pony, no_you_cant_have_a_pony);

Which will produce a compiler error containing:


Without much surprise, I once again learnt the technique from Andrei Alexandrescu and I iterated to make sure it’s usable anywhere in a C++ file: in a namespace, in a class definition or in a function.

#define JOIN(lhs, rhs)    JOIN_1(lhs, rhs)
#define JOIN_1(lhs, rhs)  JOIN_2(lhs, rhs)
#define JOIN_2(lhs, rhs)  lhs##rhs

#define STATIC_ASSERT(expression, message)\
  struct JOIN(__static_assertion_at_line_, __LINE__)\
    impl::StaticAssertion<static_cast<bool>((expression))> JOIN(JOIN(JOIN(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), _), message);\
  typedef impl::StaticAssertionTest<sizeof(JOIN(__static_assertion_at_line_, __LINE__))> JOIN(__static_assertion_test_at_line_, __LINE__)

// note that we wrap the non existing type inside a struct to avoid warning
// messages about unused variables when static assertions are used at function
// scope
// the use of sizeof makes sure the assertion error is not ignored by SFINAE

namespace impl {

  template <bool>
  struct StaticAssertion;

  template <>
  struct StaticAssertion<true>
  }; // StaticAssertion<true>

  template<int i>
  struct StaticAssertionTest
  }; // StaticAssertionTest<int>

} // namespace impl