gpt4 book ai didi

c++ - 在通用 C++ 代码中移动基于范围的循环?

转载 作者:太空狗 更新时间:2023-10-29 23:43:36 26 4
gpt4 key购买 nike

假设您有这个通用的伪代码:

template<typename Iterable>
void f(Iterable&& iterable)
{
...
}

我们想要处理对可迭代对象的右值和左值引用1,其想法是该函数处理逐个元素执行操作的容器。

我们想将容器的引用规范转发给元素是合理的。换句话说,如果 iterable 是一个右值引用,该函数将不得不从容器中移动元素。

使用 C++17,我会做

auto [begin, end] = [&] {
if constexpr(std::is_lvalue_reference_v<Iterable>)
return std::array{std::begin(iterable),
std::end(iterable)};
else
return std::array{
std::make_move_iterator(std::begin(iterable)),
std::make_move_iterator(std::end(iterable))};
}();
std::for_each(begin, end, [&](auto&& element)
{
...
});

显然,这不是维护2 的最佳代码,容易出错并且可能不太容易针对编译器进行优化。

我的问题是:对于 future 的 C++ 标准,是否有可能引入转发基于范围的循环的概念?如果这样就好了

for(auto&& el : std::move(iterable))
{
...
}

可以将 el 作为右值引用处理。这样,这将是可能的:

template<typename Iterable>
void f(Iterable&& iterable)
{
for(auto&& el : std::forward<Iterable>(iterable))
{
/*
* el is forwarded as lvalue reference if Iterable is lvalue reference,
* as rvalue reference if Iterable is rvalue reference
*/
external_fun(std::forward<decltype(el)>(el));
}
}

我担心破坏代码的更改,但与此同时我无法考虑将右值引用作为基于范围的循环的参数传递的情况移动物体。

按照建议,我尝试写下我将如何更改标准的 6.5.4 部分。草稿可以阅读at this address .

您认为在不引入严重问题的情况下引入此功能是否可能?

1检查了 C++20 概念或 static_asserts
2如果没有 C++17,情况会更糟

最佳答案

这行不通。从根本上说,您可以迭代两种事物:拥有元素的事物和不拥有元素的事物。对于非拥有范围,范围的值(value)类别是无关紧要的。他们不拥有自己的元素,因此您无法安全地离开它们。基于范围的 for 循环必须适用于两种范围。

还有一些极端情况需要考虑(例如,代理迭代器)。基于范围的 for 循环基本上是语法糖,它只对被迭代的事物施加非常少的要求。好处是它可以迭代很多东西。代价是它没有太多聪明的余地。


如果您知道可迭代对象实际上拥有它的元素(因此移动是安全的),那么您所需要的只是一个根据其他事物的值类别转发某些事物的函数:

namespace detail {
template<class T, class U>
using forwarded_type = std::conditional_t<std::is_lvalue_reference<T>::value,
std::remove_reference_t<U>&,
std::remove_reference_t<U>&&>;
}
template<class T, class U>
detail::forwarded_type<T,U> forward_like(U&& u) {
return std::forward<detail::forwarded_type<T,U>>(std::forward<U>(u));
}

关于c++ - 在通用 C++ 代码中移动基于范围的循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46171843/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com