Constexpr & jassert

I’m currently writing this in my constexpr functions:

if (!std::is_constant_evaluated) jassertfalse;

Would it make sense to have that built in to the jassert macros?

I’m not sure this makes sense, because that error condition is now not being checked if the function is executed at compile-time…

Also, if you are literally writing that, it looks like a typo that is missing the parentheses for actual invocation of is_constant_evaluated().

Written like that, I believe it tests whether is_constant_evaluated is a null function pointer.

1 Like

Thanks for the feedback! Good point @yfede, that was indeed a typo.

@benvining I should have included more context…

I made an object that contains some values and wanted to access those values from the [ ] operator of the object. So I wrote this function:

constexpr float& MyObject::operator[](int index)
{
    auto max_index{ size - 1 };
    if (index > max_index)
    {
        jassertfalse;
        return vals[max_index];
    }
    if (index < 0)
    {
        jassertfalse;
        return vals[0];
    }
    
    return vals[index];
}

Then, I wanted to test that it was catching invalid indices it, so I did something like:

static_assert(myObject[-1] == expectedValue);

At which point, the IDE tells me it cannot call juce::logAssertion in a constexpr function.

In order to let my static test complete, I wrapped the jassertfalse in if (!std::is_constant_evaluated()). This way (I think!) I get my jassertfalse at runtime and I get my static_assert at compile time.

So, the function now looks like this:

constexpr float& MyObject::operator[](int index)
{
    auto max_index{ size - 1 };
    if (index > max_index)
    {
        if (!std::is_constant_evaluated()) {
            jassertfalse;
        }
        return vals[max_index];
    }
    if (index < 0)
    {
        if (!std::is_constant_evaluated()) {
            jassertfalse;
        }
        return vals[0];
    }
    
    return vals[index];
}

Since jassertfalse is a macro, I was wondering it might make sense to include that if (!std::is_constant_evaluated()) as part of the macro definition.

…but please let me know if I’m doing it all wrong…

This will make the code compile and allow the static assert, but now the runtime & compile-time versions of the function have different behavior: when called at compile time, you get no warnings and it will just silently return the value at the max index.

Maybe this is OK for your use case, but it’s definitely a subtle behavior difference to be aware of.

Thanks, Ben.

1 Like