首页 > 解决方案 > 为什么 C++23 string::resize_and_overwrite 将操作作为右值调用?

问题描述

为了提高写入数据的性能std::string,C++23专门resize_and_overwrite()std::string. 在[string.capacity]中,标准对其进行了如下描述:

template<class Operation>
constexpr void resize_and_overwrite(size_type n, Operation op);
  1. o = size()在调用resize_and_overwrite.

    ——k成为min(o, n)

    p是 a charT*,使得范围 [ p, p + n] 是有效的并且this->compare(0, k, p, k) == 0true调用之前。p + k[ , ]范围内的值p + n可能是不确定的[basic.indet]

    OP是表达式std::move(op)(p, n)

    r = OP.

[...]

  1. 效果:计算,用 [ , )OP替换 的内容,并使对范围 [ , ]的所有指针和引用无效。*thispp + rpp + n

但是我发现这个函数在调用它之前会std::move用来转换op成一个右值,这意味着我们不能传入一个只有左值重载的可调用对象operator()demo):

#include <string>

int main() {
  struct Op {
    int operator()(char*, int) &;
    int operator()(char*, int) && = delete;
  } op;
  std::string s;
  s.resize_and_overwrite(42, op); // ill-formed
}

这种行为似乎有点奇怪,但由于这种变化是在上一版论文中做出的,显然是故意的。

那么,这背后的考虑是什么?授权中是否有任何op必须作为右值调用的好处?

标签: c++stringc++23

解决方案


op在销毁之前只调用一次,因此将其作为右值调用允许对其进行任何&&重载以重用它可能拥有的任何资源。

可调用对象道德上是一个 xvalue - 它正在“过期”,因为它在调用后立即被销毁。如果您专门设计了您的可调用对象以仅支持作为左值调用,那么库很乐意通过阻止其工作来承担责任。


推荐阅读