The output of chained views must be another view (i.e. a range). That way, you can keep chaining the result using more views.
The result of count
is not a range, so it doesn't make sense to have that operation in the chain. In the hypothetical case that you were able to, you wouldn't be able to chain the result of that operation to another view.
Viewing the situation from another angle, in range-v3 views are lazily evaluated. Counting the number of elements in a range is not a lazy operation, since it requires the entire range to be evaluated to get a result. It's a different kind of operation.
The same reasoning can be applied to the other "free-standing" algorithms, like ranges::copy
, ranges::sort
, ranges::min_element
, etc. Those should be seen as variants (or improvements) of the corresponding std
algorithms, but that also accept ranges as arguments, instead of pairs of iterators.
With that being said, some of the free-standing algorithms are also available as views, where it makes sense (like the set_intersection
, set_difference
and set_union
family of algorithms).
Edit: There are exceptions to this rule. Namely, the functions ranges::to_vector
and ranges::to_
, which "sink" the piped range into a std::vector
(or a container of your choosing).