Reputation: 581
Using g++ with -std=C++20
or later, the following compiles (assuming vec is a vector of appropriate type):
auto isEven = [](auto i) { return i % 2 == 0; }
auto filtered = vec | std::views::filter(isEven);
auto minEven = std::ranges::min_element(filtered);
but the following does not (wrong number of arguments to std::ranges::__min_element_fn
):
auto isEven = [](auto i) { return i % 2 == 0; }
auto minEven = vec | std::views::filter(isEven) | std::ranges::min_element();
What is the rationale here? How do I know which of the spiffy range-related facilities can be incorporated in a pipe? (The latter is what I intuitively wrote; conceptually it would seem to be the "new ranges way" to do this.)
Upvotes: 3
Views: 674
Reputation: 473407
In C++20, things are simple. All views can be piped. No algorithms can be piped. If it is in the views
namespace, then it can be piped, and any view can be piped against a range. That is, if at least one of the operands of |
comes from the views
namespace, and the other operand is a range, then it can be piped. Otherwise it cannot.
Another way to remember it is that pipes create ranges. min_element
doesn't create a range; it just finds a particular element of a range. Its result is not a range, so it's not something that can be piped.
Later versions have decided to just pipe or not pipe things based on whatever seems most expedient at the time. There is no rhyme or reason, it's just whatever proposals are fed in and accepted. ranges::to
gets to be piped because the author of it proposed it with piping and the committee accepted it as such. No version of the proposal attempted to rationalize why a pipeable object was in the ranges
namespace. That's just how it was proposed.
Trying to be consistent on what can and cannot be piped is clearly not a goal of the committee here. Maybe general range algorithms will be pipeable in the future. Maybe not.
Upvotes: 6