C++20 constexpr std::copy optimizations for run-time

We can have our cake and eat it to, too.

Let’s just consider the simplest specialization of copy, the one that copies chars. In C++17, that might look like:

char* copy(char const* first, char const* last, char* d)
{
    memcpy(d, first, last - first);
    return d + (last - first);
}

Of course, we can’t just slap constexpr on that because memcpy isn’t a constexpr function, that won’t work. But it only doesn’t work during constant evaluation. What we need is a way to conditionally use memcpy if we’re at runtime.

We have such a thing in C++20, std::is_constant_evaluated():

constexpr char* copy(char const* first, char const* last, char* d)
{
    if (std::is_constant_evaluated()) {
        while (first != last) {
            *d++ = *first++;
        }
        return d;       
    } else {
        memcpy(d, first, last - first);
        return d + (last - first);
    }
}

And now we have an algorithm that does the efficient thing at runtime but still works during constexpr evaluation time.


Note: It is if (std::is_constant_evaluated()), never if constexpr (std::is_constant_evaluated()). The later is equivalent to if constexpr (true) { ... }. gcc 10.1 will start warning on this erroneous usage.

Leave a Comment

tech