Consider this C++23 example:
#include <ranges>
#include <print>
#include <vector>
namespace r = std::ranges;
namespace rv = std::ranges::views;
std::vector<int> consecutive_triple(int n) {
return { n, n + 1, n + 2 };
}
int main() {
std::vector<int> numbers = { 0, 10, 20, 30, 40 };
auto more_numbers = numbers |
rv::transform(consecutive_triple) | rv::join;
// -- Does this help? ...
//auto more_numbers = numbers |
// rv::transform(consecutive_triple) | rv::join |
// r::to<std::vector>();
for (auto v : more_numbers) {
std::print("{} ", v);
}
std::println("");
return 0;
}
Each call to consecutive_triple returns a temporary std::vector<int>, so the inner ranges in the transform view are pure rvalues. When join tries to iterate them, the vectors no longer exist.
I believe this relies on undefined behavior, since the subranges’ lifetimes end before join can safely traverse them.
Questions:
Does the C++23 standard guarantee this is invalid / undefined?
Is there any standard-conforming way to write this without explicitly making a container that stores the intermediate vectors before joining them?
Each call to consecutive_triple returns a temporary std::vector<int>, so the inner ranges in the transform view are pure rvalues. When join tries to iterate them, the vectors no longer exist.
Their copies are stored in the join_view's internal data member non-propagating-cache (thanks to P2328), so there are no lifetime issues. The copies are only destroyed when iterating to the next inner range.
In other words, join_view specifically comes with cache_latest-like functionality for pure rvalue inner ranges, as this is a common use case worth supporting.
It should be noted that P2328 allows join_view to support even non-moveable ones, for example:
struct Nonmovable {
int* begin();
int* end();
Nonmovable() = default;
Nonmovable(Nonmovable&&) = delete;
};
auto r = std::views::iota(0, 5)
| std::views::transform([](int) -> Nonmovable { return {}; })
| std::views::join; // ok
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With