4

此代码演示了使用模板的编译时断言。我发现它只能由 g++ (4.4.7) 使用以下 cmd 行编译。

$ g++ -std=c++98 a.cpp -o a

Nether icc (13.0.1) 和 visual c++ (14.00.50727.762 for 80x86) 都可以编译它。对于icc,它会生成这样的错误消息

$ icpc a.cpp -o a
a.cpp(13): error: non-integral operation not allowed in nontype template argument
      COMPILE_TIME_ASSERT(true && "err msg");
      ^

a.cpp(13): error: class "CompileTimeAssert<<error-constant>>" has no member "Check"
      COMPILE_TIME_ASSERT(true && "err msg");
      ^

compilation aborted for a.cpp (code 2)

但是我发现像在断言中添加自定义消息true && "err msg"一样在运行时断言中广泛使用的断言?

问题是

  1. 是否可以在不修改代码的情况下仅使用适当的编译选项来解决此问题?
  2. 如果不能,任何编译时断言的替代方法与自定义消息?

演示代码如下所示。

#include <iostream>

template<bool B> class CompileTimeAssert { };
template<> class CompileTimeAssert<true> {
 public:
  static inline void Check() { }
};

#define COMPILE_TIME_ASSERT(b) CompileTimeAssert<(b)>::Check()

int main()
{
    COMPILE_TIME_ASSERT(true && "err msg");
    std::cout<<(true && "err msg")<<std::endl;
    return 0;
}
4

1 回答 1

0

第一个问题的答案是“否”。您传递给模板的参数称为“非类型模板参数”。根据标准,这样的论点必须是:

常量表达式,具有外部链接的函数或对象的地址,或静态类成员的地址。

true && "err msg"严格来说,无法在编译时确定表达式。这就是为什么它可以用于运行时断言但不能用于编译时断言的原因。G++ 在这里演示了非标准行为。

作为对第二个问题的回答,我提出以下模式:

#define STATIC_ASSERT(e,m) extern char (*__static_assert_failed(void)) [ 1 - 2*!(e) ] 

__static_assert_failed这是一个指向返回字符数组的外部函数的指针。如果为 false 导致编译时错误,则数组的大小1 - 2*!(e)变为负数。e

于 2013-10-27T20:00:03.733 回答