Как проверить, вернули ли range :: алгоритмы, например, find_if значение?

Например, если я хочу найти наименьший элемент коллекции, но только наименьший элемент даже, я хотел бы вызвать ranges::min_element с отфильтрованным диапазоном следующим образом:

using ranges::views::filter;
using ranges::min_element;
std::vector<int> vals{1,2,3,4,5};
auto minVal = min_element(vals | filter([](int next){return next % 2 == 0;}));

Как проверить, пуст ли возвращенный диапазон, и если нет, получить доступ к значению?

То же самое относится к другим алгоритмам диапазона, таким как ranges::find, ranges::find_if и т. Д.


person AndyG    schedule 15.10.2019    source источник


Ответы (1)


К сожалению, вы не можете передать временный диапазон в алгоритмы диапазонов.

Это потому, что по завершении они вернут итератор диапазонов (возможно, ranges::end(rng)). Если вы передадите временное значение, возвращенный итератор будет недопустимым; ссылаясь на временный. Библиотека диапазонов обнаруживает это и возвращает фиктивный дозорный, ranges::dangling вместо итератора.

Правильный способ сделать это - сначала составить отфильтрованный диапазон , а затем вызвать алгоритм.

std::vector<int> vals {1, 2, 3, 4, 5};
auto even_vals = vals | filter([](int val){return val % 2 == 0;});
auto minVal = min_element(even_vals);
if (minVal == even_vals.end())
    std::cout << "no values\n";
else
   std::cout << *minVal; // prints "2"

Демо

person AndyG    schedule 15.10.2019
comment
Это кажется ... так плохо. Излишне многословно, и это дает ощущение ... неразложимости, что является полной противоположностью того, какими должны быть диапазоны ... Тем не менее, +1 за хорошее объяснение. - person Fureeish; 30.10.2019
comment
В Haskell это намного проще ... - person Enlico; 29.01.2021
comment
@Enlico Иногда использование GC действительно может упростить задачу. - person Deduplicator; 29.01.2021
comment
Неизменяемость @Deduplicator также творит чудеса. - person eerorika; 29.01.2021