启用静态检查以进行持续评估

Enable static checks for constant evaluation

如果一个类型是用常量初始化的,我喜欢进行某种静态(编译时)检查。

下面是测试代码。 类型 C 只是一个测试,以查看 if/when 触发常量计算。

D型更像是我想做的真实例子:

  1. 运行时:如果 D 用错误的值初始化,该值可能会有所限制,或者应该触发运行时断言

  2. 编译时:如果 D 用错误的值初始化,编译应该会失败。

我找不到解决方案。

代码:

#include <cassert>
#include <type_traits>

inline void constant_assert() {}

struct C {
    constexpr C() {
        if (std::is_constant_evaluated()) {
            constant_assert();
        }
    }
};

struct D {
    constexpr D(const char v) {
        if (std::is_constant_evaluated()) {
            //static_assert(v < 10); // not callable
            if (v >= 10) {
                constant_assert();
            }
        }
        else {
            assert(v < 10);
        }
    }
};

int main() {
    C t0; // does not trigger the check
//    constexpr C t1; // triggers the check: ok

    D d{42}; // runtime assert, but should be compiletime error!
}

以上CE中的代码:https://godbolt.org/z/16GTx797q

你可以简单地这样做:

struct D {
  constexpr D(const char v) {
    assert(v < 10);
  }
};
  • 如果D在运行时赋值错误,将在运行时触发assert
  • 如果 D 在编译时被赋予了错误的值,那么它将发生 编译时错误 因为 assert 不满足。

Demo.

 D d{42}; // runtime assert, but should be compiletime error!

以你想要的方式,这是不可能的。你的方法很好——如果你的参数要被不断评估,做constexpr D d{42}。请参阅 is_constant_evaulated 的解释 - 我找到了 https://gist.github.com/Som1Lse/5309b114accc086d24b842fd803ba9d2


您可以使用 gcc 扩展 __builtin_constant_p 调用带有错误属性的函数(并且可能需要启用优化)。此方法通常由库实现在 C 中使用 - 请参阅 glibc.

中的 _FORTIFY_LEVEL
#include <cassert>
#include <type_traits>

__attribute__((__error__("Och nooo")))
void undefined_function();

struct D {
    constexpr D(const int v) {
        if (__builtin_constant_p(v)) {
            if (v >= 10)
                undefined_function();
        } else {
            assert(v < 10);
        }
    }
};

int main(int argc, char *argv[]) {
    D d1{42};
}