运行 时间的 C++20 constexpr std::copy 优化

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

cppreference.com 说:

In practice, implementations of std::copy avoid multiple assignments and use bulk copy functions such as std::memmove if the value type is TriviallyCopyable

但是,该页面还指出,自 C++20 起,不采用执行策略的重载将是 constexpr。标准会禁止这些 运行 时间的优化(因为 std::memmove 不是 constexpr)还是有办法优化 运行 时间的 constexpr 函数?

我们也可以吃蛋糕吃。

让我们考虑最简单的 copy 特化,即复制 char 的特化。在 C++17 中,它可能看起来像:

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

当然,我们不能就此打上 constexpr,因为 memcpy 不是一个 constexpr 函数,那是行不通的。但它只在不断评估期间不起作用。我们需要的是一种在运行时有条件地使用 memcpy 的方法。

我们在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);
    }
}

现在我们有了一个算法,它可以在运行时执行高效的操作,但在 constexpr 评估期间仍然有效。


注:是if (std::is_constant_evaluated())从不 if constexpr (std::is_constant_evaluated())。后者相当于if constexpr (true) { ... }。 gcc 10.1 将开始警告这种错误用法。