Почему я не могу использовать оператор *? ошибки, сгенерированные 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 «заимствует» итератор из заданного диапазона. В случае rvalue std::cartesian_product (и любого подобного представления) в большинстве случаев оно будет висеть, поскольку время жизни std::cartesian_product закончится после возвращения итератора, поэтому возвращается std::ranges::dangling . См. этот связанный вопрос: Почему алгоритмы диапазона std возвращают std::ranges::dangling для аргументов rvalue вместо... ну, просто работают?
В данном случае это было бы безопасно, поскольку элементы будут скопированы до того, как закончится время жизни cartesian_product rvalue, но это предотвращает случайное написание чего-то вроде этого:
auto it = std::ranges::min_element(std::views::cartesian_product(rng, rng));
const auto [a, b] = *it; // `it` is dangling, would be UB
Исправление состоит в том, чтобы сделать его lvalue:
auto c = std::views::cartesian_product(rng, rng);
const auto [a, b] = *std::ranges::min_element(c);
Или использовать
std::ranges::min, поскольку это то, что действительно нужно ОП.