如何设置一个评估static_assert的前提条件?

Ped*_*tti 2 c++ templates static-assert

我有这个函数用于零覆盖的东西,它使用static_assert检查给定的东西的类型是否是POD类型:

template <bool safeMode = true, typename generic>
void overwriteWithZeros( generic *variableAddress )
{
    if (safeMode) static_assert(std::is_pod<generic>::value, "Only POD types can be properly overwriten");

    const size_t size = sizeof(generic);
    unsigned char *variableData = (unsigned char*)(variableAddress);

    for (size_t i = 0; i < size; i++)
        variableData[i] = 0;
}
Run Code Online (Sandbox Code Playgroud)

我在这里打电话:

int main()
{
    being *creature = new being(100, "a guinea pig"); // being is not a POD type

    overwriteWithZeros<false>(creature);
    // totally unrelated stuff...
}
Run Code Online (Sandbox Code Playgroud)

因为它safeMode是一个编译时的值,我不知道为什么它会发生它是真的或者它是假的,static_assert总是"发生",给我当时预期的错误,因为being它不是POD类型,就像if在static_assert之前一样根本不在那里.

那么,我在这里做错了什么?

既然你确认了我的怀疑(if本身是在运行时评估的,尽管safeMode它是编译时的值,static_assert在编译时进行评估),我将主要问题改为:

我能做些什么来实现我在这里尝试的东西呢?

Jac*_*ack 6

问题是static_assert在编译时进行评估,这意味着当编译器找到它时,它会对其进行评估,而不管它在哪里(除非它被宏排除#ifdef).要解决此问题,您应该将启用标志作为评估本身的一部分:

static_assert(!safeMode || std::is_pod<generic>::value, "Only POD types can be properly overwriten");
Run Code Online (Sandbox Code Playgroud)

这是允许的,因为它safeMode是一个编译时间值(作为模板参数).

在这两种情况下static_assert都会进行评估,但safeMode == false总是会评估true.