【问题标题】:template-based compile time assert with custom messages can only be compiled in some of the compilers带有自定义消息的基于模板的编译时断言只能在某些编译器中编译
【发布时间】:2013-07-25 12:08:36
【问题描述】:

这段代码演示了一个使用模板的编译时断言。 我发现它只能由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 &amp;&amp; "err msg" 这样的断言在运行时断言中被广泛使用为Add custom messages in assert?

问题是

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

【问题讨论】:

  • 你一定要使用std=c++98标准吗?
  • @YochaiTimmer 不,我只是想证明 g++ 即使使用该选项也可以编译代码
  • 对于非类型模板参数,只有整数参数是合法的。
  • @Eric 那你为什么不直接使用 static_assert (C++0x & C++11)
  • 我从未将这种方法用于静态断言(我使用了typedef char assert_XXX[(condition?1:-1)];),但您可以考虑更改宏以便将字符串传递给函数:COMPILE_TIME_ASSERT(condition,"Message") 将扩展为CompileTimeAssert&lt;(condition)&gt;::Check("Message") 修改签名后可能更容易被所有编译器消化

标签: c++ templates visual-c++ gcc icc


【解决方案1】:

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    相关资源
    最近更新 更多