joz*_*yqk 5 c++ perfect-forwarding c++20 std-ranges
How can I combine the following two functions into one? Is there something similar to std::forward, but for ranges?
#include <ranges>
#include <vector>
#include <algorithm>
template<class RangeIn, class RangeOut>
void moveOrCopy(RangeIn& from, RangeOut& to)
{
std::ranges::copy(from, std::back_inserter(to));
}
template<class RangeIn, class RangeOut>
requires std::is_rvalue_reference_v<RangeIn&&>
void moveOrCopy(RangeIn&& from, RangeOut& to)
{
std::ranges::move(from, std::back_inserter(to));
}
void test()
{
std::vector<int> a, b;
moveOrCopy(a, b); // copy
moveOrCopy(std::move(a), b); // move
}
Run Code Online (Sandbox Code Playgroud)
There is std::ranges::forward_range, but that's related to forward_iterator, not perfect forwarding.
Handy tool with the above code: https://cppinsights.io/s/45c86608
Intuitive reference for C++ references: https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
If you have C++23, you can use std::ranges::transform with std::forward_like.
template<class RangeIn, class RangeOut>
void moveOrCopy2(RangeIn&& from, RangeOut& to)
{
std::ranges::transform(from, std::back_inserter(to), [](auto&& arg) -> decltype(auto) {
return std::forward_like<RangeIn>(arg);
});
}
Run Code Online (Sandbox Code Playgroud)
Demo: https://godbolt.org/z/P81of9qav
It is not overly clever but if constexpr can clean it up a little bit:
#include <ranges>
#include <vector>
#include <algorithm>
template<class RangeIn, class RangeOut>
void forward_range(RangeIn&& from, RangeOut& to)
{
if constexpr(std::is_rvalue_reference_v<RangeIn&&>)
std::ranges::move(from, std::back_inserter(to));
else
std::ranges::copy(from, std::back_inserter(to));
}
void test()
{
std::vector<int> a, b;
forward_range(a, b); // copy
forward_range(std::move(a), b); // move
}
Run Code Online (Sandbox Code Playgroud)
从通用范围的值类别推断元素的生命周期属性是一个坏主意。例如:
std::span<std::string>不应该将其元素移出,即使是span右值;跨度的值类别完全无关。ranges::transform_view<std::span<std::string>, some_function>右值也是如此,即使它不是borrowed_range.boost::iterator_range<std::string*>,即使这个遗留类型没有声明自己是 a view;owning_view<boost::iterator_range<std::string*>>,尽管它是 的专业化owning_view。目前还没有任何概念或特征可以让人们可靠地检测何时可以安全地执行此操作。最好的办法是让调用者使用views::as_rvalueC++23 中的类似方法显式选择加入。
| 归档时间: |
|
| 查看次数: |
237 次 |
| 最近记录: |