想象一下,你有这个通用的伪代码:
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的最佳代码,容易出错并且可能不太容易为编译器优化。
我的问题是:对于未来的 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 部分。可以在这个地址阅读草稿。
您认为可以在不引入严重问题的情况下引入此功能吗?
1使用 C++20 概念或 static_asserts 检查
2如果没有 C++17,情况会更糟