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.