[range] Best way to count the elements in a filtered range?
I wonder what is the recommended way to count the elements in a filtered range. Let range be a random access range, and filter the result of filtered(predicate), auto filtered_range = range | filter; count_if( filtered_range, [](const&){ return true; }); // (& omitted in lambda) counts the elements in a filtered range. _If_ this is the best way to count the elements in a filtered range, what about defining Range boost::count(Range&& r); to count all element in the range? It could call size() if available and count_if otherwise. Bests, Gonzalo BG
On 19 June 2013 11:39, Gonzalo Brito Gadeschi
I wonder what is the recommended way to count the elements in a filtered range.
Let range be a random access range, and filter the result of filtered(predicate),
auto filtered_range = range | filter; count_if( filtered_range, [](const&){ return true; }); // (& omitted in lambda)
counts the elements in a filtered range.
_If_ this is the best way to count the elements in a filtered range, what about defining
Range boost::count(Range&& r);
to count all element in the range? It could call size() if available and count_if otherwise.
I'm not quite sure I'm understanding the question! Does
boost::count( filtered_range ); not do exactly what you want? Also, I don't understand why you'd like am rvalue ref version of count when the argument is const, but that might be my naivety about how to use rvalues. - Rob.
On 19 June 2013 11:52, Robert Jones wrote:
_If_ this is the best way to count the elements in a filtered range, what about defining
Range boost::count(Range&& r);
to count all element in the range? It could call size() if available and count_if otherwise.
I'm not quite sure I'm understanding the question! Does
boost::count( filtered_range );
not do exactly what you want? Also, I don't understand why you'd like am rvalue ref version of count when the argument is const, but that might be my naivety about how to use rvalues.
If Range is a template parameter then Range&& can also bind to lvalues, and Range will be deduced as an lvalue-reference type such as X&. The signature above would therefore return an rvalue when passed an rvalue, and return an lvalue when passed an lvalue. I'm not sure how it would return the number that it's supposed to be counting though, I'd have expected it to return the range's difference type, and in that case it might as well be count(const Range&), or count(const Range&, const Value&) like the existing range algorithm.
I'm not quite sure I'm understanding the question! Does boost::count( filtered_range ); not do exactly what you want?
boost::count takes a value (just like the STL), there is no version of boost::count that simply takes a range. Also, I don't understand why you'd like am rvalue ref version of count when
the argument is const
E.g. boost::cout( range | filter ); would bind to an rvalue.
Someone suggested to use boost::size in the other thread, but size does boost::end(rng) - boost::begin(rng) which is not the number of elements in the filtered range. On Wed, Jun 19, 2013 at 1:04 PM, Gonzalo Brito Gadeschi < g.brito@aia.rwth-aachen.de> wrote:
I'm not quite sure I'm understanding the question! Does
boost::count( filtered_range ); not do exactly what you want?
boost::count takes a value (just like the STL), there is no version of boost::count that simply takes a range.
Also, I don't understand why you'd like am rvalue ref version of count
when the argument is const
E.g.
boost::cout( range | filter );
would bind to an rvalue.
Hi Gonzalo, Gonzalo Brito Gadeschi wrote:
Someone suggested to use boost::size in the other thread, but size does
boost::end(rng) - boost::begin(rng)
which is not the number of elements in the filtered range.
Try boost::distance(rng | filtered(pred)). Size shouldn't even compile, since it requires random access, and a filtered range cannot be random access. HTH, Nate
Try boost::distance(rng | filtered(pred)).
Distance works as expected, thanks! On Wed, Jun 19, 2013 at 5:03 PM, Nathan Crookston < nathan.crookston@gmail.com> wrote:
Hi Gonzalo,
Gonzalo Brito Gadeschi wrote:
Someone suggested to use boost::size in the other thread, but size does
boost::end(rng) - boost::begin(rng)
which is not the number of elements in the filtered range.
Try boost::distance(rng | filtered(pred)). Size shouldn't even compile, since it requires random access, and a filtered range cannot be random access.
HTH, Nate
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Ok, it seems that both threads have been merged now. I think boost::size() is what you want.
size_t s = boost::size(range | filter);
boost::size attempts the following: boost::end(range) - boost::begin(range) There are multiple problems with this: - boost::filtered_iterators which are bidirectional at best (i.e. not random access, boost::size doesn't work). - boost::size has constant time complexity. As far as I know, it is impossible to find the number of elements in a filtered range in constant time. Thus it cannot be made to work. This _problems_ are intended behavior. size is associated with constant time and random access iterators, breaking that is not acceptable. On the other hand, boost::count has constant time complexity. That is, overloading it for a single range parameter would allow determining the elements in a range in linear time without breaking old semantics. This overload could be specialized to call boost::size when it make sense for extra performance (complexity is linear time, or better). On Wed, Jun 19, 2013 at 1:30 PM, Gonzalo Brito Gadeschi < g.brito@aia.rwth-aachen.de> wrote:
Someone suggested to use boost::size in the other thread, but size does
boost::end(rng) - boost::begin(rng)
which is not the number of elements in the filtered range.
On Wed, Jun 19, 2013 at 1:04 PM, Gonzalo Brito Gadeschi < g.brito@aia.rwth-aachen.de> wrote:
I'm not quite sure I'm understanding the question! Does
boost::count( filtered_range ); not do exactly what you want?
boost::count takes a value (just like the STL), there is no version of boost::count that simply takes a range.
Also, I don't understand why you'd like am rvalue ref version of count
when the argument is const
E.g.
boost::cout( range | filter );
would bind to an rvalue.
participants (4)
-
Gonzalo Brito Gadeschi
-
Jonathan Wakely
-
Nathan Crookston
-
Robert Jones