【发布时间】:2021-04-19 08:04:46
【问题描述】:
阅读Why does as_const forbid rvalue arguments? 我知道我们当然不能将右值引用转换为左值引用。
但为什么不将右值引用移动到一个值并返回它,即?
template<typename T>
const T as_const(T&& val) { return std::move(val); }
这应该也适用于 COW 容器,因为返回值是 const 并且来自它的迭代器不会导致它分离。
也许一些上帝会回答这个问题,但我想不出一个给定的场景,而且那里没有容易获得的 COW 容器 AFAIK。
更新:
考虑一下这个 COW 容器(忽略线程问题):
class mything {
std::shared_ptr<std::vector<int>> _contents;
auto begin() { if (_contents.use_count() > 1) { detach(); }
return _contents->begin(); }
auto begin() const { return _contents->begin(); }
void detach() {
_contents = std::make_shared<decltype(_contents)>(*_contents);
}
...
};
移动会很快,并且当在 range-for-loop 中使用时,返回的 const T 将选择 begin() 的 const 版本。
还有一些容器将自己标记为已修改,因此它们的更改可以通过网络发送或稍后同步到另一个副本(用于另一个线程),f.ex。在 OpenSG 中。
【问题讨论】:
-
我的猜测很简单,这不是函数的用途:它的意思是“将这个非常量引用变成一个常量”,而不是“确保我得到 something const 在所有情况下'。
-
const上的返回值(不是引用)基本上没有意义 -
@Caleth 不适用于写时复制容器,其非 const begin()/end() 函数会创建新副本(也称为分离),因为它们希望内容发生变化。
-
返回
std::move(val)为T在任何情况下都会复制val。此外,return std::move(...)是一种反模式,通常会禁止 NRVO。但是,即使 NRVO 在返回输入参数时也无济于事,总会涉及到复制。 -
好的,如果我们忽略非类 const T 的问题,您的版本仍然会返回一个新的 T 实例。左值引用重载返回对同一对象的引用会产生误导,而右值一 - 一个新对象。
标签: c++ c++17 rvalue-reference