如何在没有C ++ 11的情况下进行编译时断言

时间:2013-07-23 17:25:20

标签: c++ templates

在求职面试中,我被要求写一个元函数 确定一个类型是否是一个指针。这是 我提出的内容:

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

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

然后我被要求写一个meta-assert,那将失败 在编译期间,如果我的is_pointer函数不是 做正确的事。

当我使用static_assert时,他明确告诉我 我可能只使用C ++ 98标准。我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:9)

有不同的方法,一种常见的方法,试图键入一个无效的类型:

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

这可以在大多数任何上下文中使用,如果条件为false,它将使编译器跳闸,因为它会尝试键入一个无效类型(负数元素数组)。它可以在不同的环境中使用:

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

答案 1 :(得分:5)

在你的情况下

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 :(得分: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和中间结构,以提供更好的错误消息并可在各种编译器上移植。)