为什么 C++23 string::resize_and_overwrite 调用操作作为右值?
Why does C++23 string::resize_and_overwrite invoke operation as an rvalue?
为了提高向std::string
写入数据的性能,C++23特地引入了resize_and_overwrite()
for std::string
. In [string.capacity],标准是这样描述的:
template<class Operation>
constexpr void resize_and_overwrite(size_type n, Operation op);
Let
— o = size()
before the call to resize_and_overwrite
.
— k
be min(o, n)
.
— p
be a charT*
, such that the range [p
, p + n
] is valid and this->compare(0, k, p, k) == 0
is true
before the call. The values in
the range [p + k
, p + n
] may be indeterminate [basic.indet].
— OP
be the expresion std::move(op)(p, n)
.
— r = OP
.
[...]
- Effects: Evaluates
OP
, replaces the contents of *this
with [p
, p + r
), and invalidates all pointers and references to the range [p
, p + 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
}
这个行为看起来有点奇怪,但是由于这个改变是在
论文的last edition,明显是故意的
那么,这背后的考虑是什么? op
必须作为右值调用的强制要求有什么好处吗?
op
在被销毁之前只被调用一次,因此将其作为右值调用允许对其进行任何 &&
重载以重用它可能持有的任何资源。
可调用对象是道德上的一个xvalue——它是“过期的”,因为它在调用后立即被销毁。如果您专门将可调用对象设计为仅支持作为左值调用,那么库很乐意通过阻止它工作来提供帮助。
为了提高向std::string
写入数据的性能,C++23特地引入了resize_and_overwrite()
for std::string
. In [string.capacity],标准是这样描述的:
template<class Operation> constexpr void resize_and_overwrite(size_type n, Operation op);
Let
—
o = size()
before the call toresize_and_overwrite
.—
k
bemin(o, n)
.—
p
be acharT*
, such that the range [p
,p + n
] is valid andthis->compare(0, k, p, k) == 0
istrue
before the call. The values in the range [p + k
,p + n
] may be indeterminate [basic.indet].—
OP
be the expresionstd::move(op)(p, n)
.—
r = OP
.[...]
- Effects: Evaluates
OP
, replaces the contents of*this
with [p
,p + r
), and invalidates all pointers and references to the range [p
,p + 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
}
这个行为看起来有点奇怪,但是由于这个改变是在 论文的last edition,明显是故意的
那么,这背后的考虑是什么? op
必须作为右值调用的强制要求有什么好处吗?
op
在被销毁之前只被调用一次,因此将其作为右值调用允许对其进行任何 &&
重载以重用它可能持有的任何资源。
可调用对象是道德上的一个xvalue——它是“过期的”,因为它在调用后立即被销毁。如果您专门将可调用对象设计为仅支持作为左值调用,那么库很乐意通过阻止它工作来提供帮助。