My intention is this: get the rvalue link (i.e. the link to the object I want to use), delete some of its resources and then return the other resources.
This is normal, but probably better:
completely remove resource placeholders or
replace remote resources with other objects or
tells the caller which resources have been deleted.
Because if you do not do any of them, the user can use one of the moved elements that you cannot use. Since relocated objects (at least in the STL) have a valid but undefined state, using these cannibalised objects will have undefined results.
You do not want this.
Is this the right way to achieve what I want?
Seems good
Should I use std :: forward? I believe not, as this is not a universal link
No, not worth it. Your reasoning is correct.
FYI: "indicating to users whose resources have been deleted" has a model in the standard library. Take a look at std::remove_if - it actually moves the "deleted" elements to the end of the sequence and returns an iterator with end marks of the remaining elements and the beginning of the "deleted" ones.
In this case, I could approach the problem.
goal: do something with all the lines lexically larger than the "ccc" in the vector, leaving the rest in the vector in the original order
template<class T> void do_something_with(T t) { std::cout << "did something with " << t << std::endl; } template<class ForwardIt, class UnaryPredicate> ForwardIt rotate_if(ForwardIt first, ForwardIt last, UnaryPredicate p) { while(first != last) { auto n = std::next(first); if (p(*first)) { if (n != last) { std::rotate(first, n, last); first = n; last = std::prev(last); } else { last = first; break; } } first = n; } return last; } template<class T, class Pred, class Model> std::vector<T> do_something_if(std::vector<T>&& in, Pred pred, Model&& model) { auto result = std::move(in); auto ibreak = rotate_if(std::begin(result), std::end(result), [&](auto& v) { auto match = pred(v, model); return match; }); for (auto i = ibreak ; i != std::end(result) ; ++i) { do_something_with(std::move(*i)); } result.erase(ibreak, std::end(result)); return result; } void test() { std::vector<std::string> words = { "yyy", "aaa", "zzz", "bbb", }; auto filtered = do_something_if(std::move(words), std::greater<>(), "ccc"); std::cout << "remaining items:\n"; for (auto& w : filtered) { std::cout << w << std::endl; } }
expected output:
did something with zzz did something with yyy remaining items: aaa bbb
In most cases, there will be more effective solutions, but this will avoid memory allocation.