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
}
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
It is a bad idea to infer the lifetime property of the elements from a generic range's value category. For example:
std::span<std::string>should not have its elements moved from, even if thespanis an rvalue; the value category of the span is completely irrelevant.ranges::transform_view<std::span<std::string>, some_function>rvalue, even though it is not aborrowed_range.boost::iterator_range<std::string*>, even though this legacy type has not declared itself to be aview;owning_view<boost::iterator_range<std::string*>>, even though it's a specialization ofowning_view.There's currently no concept or trait that would allow one to reliably detect when it's safe to do this. The best that can be done is to have the caller explicitly opt-in using something like
views::as_rvaluein C++23.