c++ 基于范围的for循环不能检测它是否在右值上循环,这有什么技术原因吗?

vcirk6k6  于 2023-01-15  发布在  其他
关注(0)|答案(1)|浏览(97)

这个问题的原因是我见过这样的代码:

auto fun(std::vector<Foo>&& v) {
    std::vector<Bar> w;
    for (auto&& e : v /* not an rvalue, but keep reading */) {
        w.push_back(std::move(e));
    }
    // do stuff with w
}

其被静态分析工具标记为错误,因为转发参考X1 M0 N1 X是X1 M1 N1 XD而不是X1 M2 N1 XD。
另一方面,v肯定会绑定到纯右值或x值(客户端知道或者希望fun作为临时变量),因为它的类型是一个右值引用。是的,我看到函数体没有以任何方式声明v不能在for循环之后使用,但那只会让我觉得我应该改变

  • for (auto&& e : v)for (auto&& e : std::move(v))
  • auto&&E&&,假设沿着using E = std::decay_t<decltype(v)>::value_type;的线。

据我所知,第一点并没有达到我所期望的效果,事实上,std::move似乎对for没有影响,反过来,e一直从左值初始化(至少在operator[]返回v类型的引用的常见情况下是这样),而第二个点只会导致编译错误。
作为附加参考,注解¹this answer读取(参考范围-for循环)
无法检测是否正在对临时值(或其他右值)进行迭代
这似乎证明了我做不到。
但是,看看range-for循环是如何去糖的,当 * range-expression * 是右值时,将range-declaration` = *__begin;`更改为range-declaration= std::move(*__begin);会有什么错误?

vtwuwzda

vtwuwzda1#

容器是右值并不意味着它所包含的内容是

// note: in real code this could be T&& and have no idea it's a std::span
void foo(std::span<X>&& s){
    // explicitly std::move should be required
    // because the code may want to use `s` later
    for(auto&& v : std::move(s)){
        // if the for loop forward the value category of <range-expression> to items
        // then decltype(v) is X&&, and this wrongly move-out the data
        X t = std::forward<decltype(v)>(v); 
    }
}

int main(){
    X x[2];
    foo(x);
}

该决定应由

相关问题