5

For example, if I want to find the smallest element of a collection, but only the smallest even element, I'd like to call ranges::min_element with a filtered range like so:

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;}));

How do I check if the returned range is empty, and if not, access the value?

The same applies to other range algorithms like ranges::find, ranges::find_if, etc.

AndyG
  • 39,700
  • 8
  • 109
  • 143

1 Answers1

8

Unfortunately you cannot pass a temporary range into ranges algorithms.

This is because they will return a ranges iterator (possibly ranges::end(rng)) upon completion. If you pass a temporary, the returned iterator would be invalid; referencing a temporary. The ranges library detects this and returns a dummy sentinel, ranges::dangling instead of an iterator.

The proper way to do this is to first compose your filtered range then call the algorithm.

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"

Demo

AndyG
  • 39,700
  • 8
  • 109
  • 143