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

Jak*_*ský 28 c++ optimization constexpr c++20

cppreference.com说:

实际上,如果值类型为TriviallyCopyable,则std :: copy的实现应避免多次分配,并使用大容量复制功能,例如std :: memmove

但是,该页面还指出,不采用执行策略的重载将constexpr自C ++ 20开始。该标准是否会禁止这些运行时优化(因为std::memmove不是constexpr),或者是否有一种方法可以优化constexpr运行时的功能?

Bar*_*rry 34

我们也可以吃蛋糕也可以吃。

让我们考虑copy复制chars 的最简单的专业化。在C ++ 17中,可能看起来像:

char* copy(char const* first, char const* last, char* d)
{
    memcpy(d, first, last - first);
    return d + (last - first);
}
Run Code Online (Sandbox Code Playgroud)

当然,我们不能仅仅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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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


注意:是if (std::is_constant_evaluated())从来没有 if constexpr (std::is_constant_evaluated())。后者等效于if constexpr (true) { ... }。gcc 10.1将对此错误用法发出警告。

  • @HenriMenke持续评估的问题不是memcpy的存在,而是它的use_。持续评估的所有规则都是“您无法运行此代码”,而不是“您无法在函数中使用它”。例如在constexpr int f(bool b){return b?抛出0:0; }`,`f(false)`很好。只有当我们到达时,“ throw”才会中断。 (6认同)