Как я могу сделать утверждения времени компиляции без С++ 11

На собеседовании меня попросили написать метафунг который определяет, был ли тип указателем. Это что я представил:

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

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

Затем меня попросили написать мета-утверждение, которое не получится во время компиляции, если моя функция is_pointer не является делать правильные вещи.

Когда я использовал static_assert, он прямо сказал мне, что Я могу использовать только стандарт С++ 98. Как я могу достичь этого?

Ответ 1

В вашем случае

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

решил бы проблему:

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

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

Ответ 2

Существуют разные подходы, один из которых пытается ввести неверный тип:

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

Это может использоваться в основном в любом контексте и отключит компилятор, если условие ложно, поскольку оно попытается ввести typedef недопустимый тип (массив отрицательного числа элементов). Его можно использовать в разных контекстах:

// 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);
   }
};

Ответ 3

Я бы использовал BOOST_STATIC_ASSERT. Вы можете посмотреть код: boost/static_assert.hpp.

Здесь очень упрощенная версия, просто чтобы дать вам идею:

#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__)

Его можно использовать во многих местах (см. документацию для примеров).

(реализация Boost более полная, например, sizeof и промежуточная структура, чтобы дать лучшее сообщение об ошибке и быть переносимым в широком диапазоне компиляторов.)