编译时断言?

Jas*_*n S 33 c++ compiler-construction

有没有办法可以断言两个常量表达式在编译时是相等的?

例如,我希望这会导致编译时错误

enum { foo=263, bar=264 };
SOME_EXPRESSION(foo,bar)
Run Code Online (Sandbox Code Playgroud)

但我希望这不会导致错误

enum { foo=263, bar=263 };
SOME_EXPRESSION(foo,bar)
Run Code Online (Sandbox Code Playgroud)

编辑:上面简化了.我的情况更像是

some_other_file_I_dont_control.h:

class X
{
public:
   enum { foo=263 };
}
Run Code Online (Sandbox Code Playgroud)

my_file.h:

enum { bar=something+somethingelse }; // bar should equal X::foo
SOME_EXPRESSION(X::foo, bar)
Run Code Online (Sandbox Code Playgroud)

Cha*_*had 35

是.您可以使用类型bool上的模板特化来执行此操作,如下所示:

// empty default template
template <bool b>
struct StaticAssert {};

// template specialized on true
template <>
struct StaticAssert<true>
{
    static void assert() {}
};

int f()
{
    StaticAssert<1==1>::assert();   // compiles fine, assert() member found
    StaticAssert<1==2>::assert();   // compile failure, no assert() member for StaticAssert<false>
}
Run Code Online (Sandbox Code Playgroud)

代码基本上来自内存,可能需要一些调整.

  • 您还可以使用`assert()`成员并使用默认构造函数:`StaticAssert <1 == 1>();` (3认同)
  • 在编译时评估(和生成)模板,因此必须使用编译器在编译时已知的值(`constexpr`) (2认同)
  • 这是我正在寻找的实现,谢谢。很干净。这是另一个参考:http://www.drdobbs.com/compile-time-assertions/184401873 和 Alexandrescu 的现代 C++ 设计书第 2.1 章。 (2认同)

Meh*_*dad 33

请参阅static_assert(仅限C++ 0x); 如果是旧版本,请参阅Boost'sStaticAssert.

  • @Jason:它是一个嵌入式系统并不重要(除非你的*编译器*在嵌入式系统上运行......我希望不是这样) - 断言是静态的,因此显然没有编译成最终的代码.:-)如果你愿意,从Boost库中提取这个部分. (7认同)
  • 我也没有Boost.这是一个没有这种奢侈品的嵌入式系统.我很幸运,我有C++,而不仅仅是简单的C. (2认同)

Dav*_*eas 22

对于静态断言的另一个版本,您可以通过添加更好的名称来赞美,您可以使用:

// name must be a valid identifier
#define STATIC_ASSERT( condition, name )\
    typedef char assert_failed_ ## name [ (condition) ? 1 : -1 ];
Run Code Online (Sandbox Code Playgroud)

用作:

STATIC_ASSERT( x == y, constants_must_be_same );
Run Code Online (Sandbox Code Playgroud)

编译器将触发类似于以下的错误:

size of array 'assert_failed_constants_must_be_same' is negative
Run Code Online (Sandbox Code Playgroud)

哪个看起来没有用,但是它会指向断言的确切行,过一会儿你将开始处理该错误消息,因为静态断言失败

  • 如果使用-Werror = unused-local-typedefs,则使用此STATIC_ASSERT将是一个问题。模板解决方案似乎是一个更好的选择。 (2认同)

小智 6

Windows的另一种可能性是C_ASSERT,如果包含Windows.h,则定义它.

  • 我不想被绑在Windows上 - 但你发布的链接显示它是如何实现的,而且非常简单,谢谢! (2认同)

epa*_*tel 5

还有使用switch (..)语句的技巧。虽然有点老式。case 条目 foo == bar 必须在编译时进行评估,如果它恰好为 false,则 switch 语句将导致错误。编译器也会将其减少为“无”。

{ 
  bool x=false; 
  switch (x) {
  case foo == bar:
    break;
  case false:
    // Compile time test that foo == bar
    break;
}
Run Code Online (Sandbox Code Playgroud)