Search code examples
c++templatesstatic-assert

How to set a pre-condition to the evaluation of a static_assert?


I have this function for zero-overwriting things which uses static_assert to check if the given thing's type is a POD type:

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

which I call here:

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

    overwriteWithZeros<false>(creature);
    // totally unrelated stuff...
}

And since safeMode is a compile time value, I don't know why it happens that being it true or being it false, static_assert always "happens", giving me the then expected error for being being not a POD type, as if this if before the static_assert simply wasn't there.

So, what am I doing wrong here?

Since you confirmed my suspicions (if itself is evaluated at run time despite of safeMode being a compile time value or not, while static_assert is evaluated at compile time), I changed the main question to:

What could I do to achieve what I'm trying here, so?


Solution

  • The problem is that static_assert is evaluated at compile time, this means that when the compiler finds it, then it evaluates it, regardless of where it is (unless it's excluded with a macro like #ifdef). To solve this problem you should make the enable flag part of the evaluation itself:

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

    This is allowed because safeMode is a compile time value (being a template argument).

    In both situations the static_assert will be evaluated but with safeMode == false it will always evaluate to true.