Why can't I use operator * ? errors generated by gcc 14.
#include <algorithm>
#include <ranges>
using namespace std;
int main() {
auto rng = views::iota(0, 3);
const auto [a, b] = * ranges::min_element(views::cartesian_product(rng, rng));
return 0;
}
prog.cc: In function 'int main()':
prog.cc:7:29: error: no match for 'operator*' (operand type is 'std::ranges::borrowed_iterator_t<std::ranges::cartesian_product_view<std::ranges::iota_view<int, int>, std::ranges::iota_view<int, int> > >')
7 | const auto [a, b] = * ranges::min_element(views::cartesian_product(rng, rng));
|
std::ranges::min_element
"borrows" an iterator from the given range. In case of an rvalue std::cartesian_product
(and any similar view), this would dangle in most circumstances since the lifetime of the std::cartesian_product
would end after the iterator would be returned, so std::ranges::dangling
is returned. See this related question: Why do std range algorithms return std::ranges::dangling for rvalue arguments instead of... well, just working?
This would be safe in this case since the elements would be copied from before the cartesian_product
rvalue's lifetime ends, but it prevents accidentally writing something like this:
auto it = std::ranges::min_element(std::views::cartesian_product(rng, rng));
const auto [a, b] = *it; // `it` is dangling, would be UB
The fix is to make it an lvalue:
auto c = std::views::cartesian_product(rng, rng);
const auto [a, b] = *std::ranges::min_element(c);