mel-
mel-

Reputation: 533

How can I make compile time assertions without C++11

In a job interview, I was asked to write a metafunction that determined whether a type was a pointer. This is what I presented:

template <typename T>
struct is_pointer
{ static const bool value = false; }

template <typename T>
struct is_pointer<T *>
{ static const bool value = true; }

Then I was asked to write a meta-assert, that will fail during compile time if my is_pointer function is not doing the right thing.

When I used static_assert, he explicitly told me that I may only use C++98 standard. How can I achieve this?

Upvotes: 10

Views: 795

Answers (3)

gx_
gx_

Reputation: 4760

I would use BOOST_STATIC_ASSERT. You can look at the code: boost/static_assert.hpp.

Here's a very simplified version, just to give you an idea:

#define JOIN(X, Y) DO_JOIN(X, Y)
#define DO_JOIN(X, Y) X ## Y

template<bool cond>
struct Static_assert_helper;  // incomplete type

template<>
struct Static_assert_helper<true> {
    typedef int Type;
};

#define STATIC_ASSERT(cond) \
    typedef Static_assert_helper<(cond)>::Type JOIN(Static_assert_typedef_, __LINE__)

It can be used in many places (see the documentation for examples).

(Boost's implementation is more complete, with e.g. a sizeof and an intermediate struct, to give a better error message and be portable on a wide range of compilers.)

Upvotes: 3

There are different approaches, a common one trying to typedef an invalid type:

#define static_assert(condition) \
        typedef char assert ## __LINE__ [((condition)?1:-1)]

This can be used in mostly any context and will trip the compiler if the condition is false, since it would try to typedef an invalid type (array of negative number of elements). It can be used in different contexts:

// namespace level:
static_assert(sizeof(int)==4);
struct type {
   // class level:
   static_assert(sizeof(int)==4);
   void f() {
       // function level
       static_assert(sizeof(int)==4);
   }
};

Upvotes: 9

nikolas
nikolas

Reputation: 8975

In your case

template <bool> struct assert;
template <> struct assert<true> {};

would have solved the problem:

assert<!is_pointer<char>::value>();     // valid
assert<is_pointer<char *>::value>();    // valid

assert<is_pointer<char>::value>();      // compilation error:
                                        // use of incomplete class

Upvotes: 5

Related Questions