我能否禁用静态断言?

3

我的代码中散布着一些相当昂贵的static_assert调用。尽管它们很有价值,但它们经常是多余的,并且会显著地影响编译时间和内存使用。

我能否禁用它们?


1
是的。通过移除它们。 - Rapptz
1
你确定这些 static_assert 调用是导致所有开销的原因吗? - Brian Bi
@Brian 并非全部,但其中许多包含了对元函数的复杂运用,这些函数对于所有构建都是必要的。 - quant
1
禁用static_assert的唯一方法是将其从将要编译的代码中删除,例如通过使用预处理器。它们不会以任何方式对编译后的代码做出贡献。 - Deduplicator
@Rapptz 我倾向于等待直到我收到完美的答案或者我有信心得出的答案是最好的,考虑到问题。除了极少数情况,我总是最终标记答案(请查看我的历史记录)。你认为这是不好的做法吗? - quant
显示剩余2条评论
2个回答

7

将它们包裹在标准的NDEBUG宏中。

#ifndef NDEBUG
static_assert(...);
#endif

那么对于发布版本,您可以像常规的assert一样禁用它们。虽然我确实看不出这样做的目的。

如果您不喜欢在宏中封装调用,可以定义一个为您执行此操作的宏:

#ifndef STATIC_ASSERT
#ifndef NDEBUG
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__)
#else
#define STATIC_ASSERT(...) static_assert(true, "")
#endif // NDEBUG
#endif // STATIC_ASSERT

使用方法与常规的static_assert类似。请注意,如果您的程序定义了一个关键字并包含一个标准库头文件,则定义static_assert宏是未定义的行为


我并不特别喜欢这个解决方案,但我想它能胜任工作。 - quant
@quant 由于它们是编译时方面的,这是唯一的方法。要么这样做,要么彻底删除它们。 - Rapptz
我真的不建议将静态检查(static_assert)与运行时检查耦合在一起。如果你想移除其中一个,很可能你并不想禁用其他的检查。 - Deduplicator
@Deduplicator 它可以被编译过程中定义的任何宏所替换。我只是因为熟悉而使用了 NDEBUG - Rapptz
2
在命名空间范围或类体中,替换do { } while(0)不能用于static_assert - reima
显示剩余2条评论

1
  1. 你可以将它们分别包装在自己的 #ifdef 中:

    #ifndef NO_STATIC_ASSERT
    static_assert(...);
    #endif
    
  2. 或者,您可以定义自己的 STATIC_ASSERT

    #ifndef NO_STATIC_ASSERT
        #define STATIC_ASSERT(...) /**/
    #else
      #define STATIC_ASSERT(...) static_assert(__VA_ARGS__)
    #endif
    
    • 实际上,#define static_assert(...) 也可以使用,但这是未定义行为。
  3. 或者,您可以手动删除它们。
那样做可以消除它们对编译性能的影响(它们从来没有对运行时性能产生任何影响)。

整洁,我没有想到那个第二个。谢谢 :) - quant
1
定义自己的 static_assert 宏是未定义行为。 - Rapptz
3
如果TU或头文件包含标准库头文件(这很可能发生),那么通过预处理器定义关键字是未定义的行为。请参见此处链接 - Rapptz
1
@Deduplicator 是的。Johannes的评论似乎支持了我的说法,我信任他。尽管这是一场历史悠久而冗长的辩论。 - Rapptz
@Deduplicator 这里是最新的草案 链接。但我不想再延长这个讨论了。如果你想要讨论,请前往Lounge - Rapptz
@Rapptz:不用了,我找了所有其他的引用,但那一个足矣。 - Deduplicator

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接