std::forword 如何在折叠表达式的上下文中工作

问题描述 投票:0回答:1

在C++标准库中,std::apply的实现如下:

constexpr decltype(auto) _Apply_impl(_Callable&& _Obj, _Tuple&& _Tpl, index_sequence<_Indices...>) noexcept(
    noexcept(_STD invoke(_STD forward<_Callable>(_Obj), _STD get<_Indices>(_STD forward<_Tuple>(_Tpl))...))) {
    return _STD invoke(_STD forward<_Callable>(_Obj), _STD get<_Indices>(_STD forward<_Tuple>(_Tpl))...);
}

在表达式

_STD get<_Indices>(_STD forward<_Tuple>(_Tpl))...
中,
std::get
被调用的次数与元组的长度相同。但是,每次调用
std::get
时,都会相应调用
std::forward.
转发右值时,
std::forward
相当于
std::move
,这意味着对
std::move
对象多次调用
_Tpl
。这似乎可能是无效的。有人可以帮助解释我的担忧吗?非常感谢。

我尝试搜索各种资源,但找不到我正在寻找的答案。从定义开始也没有说服我。

c++ templates reference rvalue stdmove
1个回答
0
投票

意味着对 _Tpl 对象多次调用 std::move。这似乎可能无效。

是的,元组上有多个对

std::move
的调用。但这本身并不是无效的。

通常,将带有

std::move
的对象传递给函数是对该函数的承诺,即调用者在调用后不会依赖该对象的状态,但在某些情况下,函数向调用者做出更强的承诺.

例如

std::unique_ptr
承诺在调用其移动构造函数或移动赋值后,传递的对象将处于空状态。

对于

std::get
来说,更准确地知道它会做什么:除了返回对元组中所请求元素的引用之外,它不会执行任何操作。并且根据元组是作为右值还是左值传递,在与元素的类型组合时,它还会根据需要返回左值或右值引用。

因此,

std::get
实际上不会修改元组的状态,并且包扩展(顺便说一句,这不是折叠表达式。)将产生一个对元组每个元素的引用的列表,可能作为左值或右值,但同一个对象永远不会有两个右值。因此,当将引用传递给被调用的函数时,不存在与通用 double-
std::move
s 等效的问题。

© www.soinside.com 2019 - 2024. All rights reserved.