Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#8617 closed Bugs (fixed)

Surprising/wrong semantics of counting_range

Reported by: pbazant@… Owned by: Neil Groves
Milestone: To Be Determined Component: range
Version: Boost 1.53.0 Severity: Problem
Keywords: range Cc:

Description

I would expect

counting_range(begin(rng),end(rng));

to be equivalent to

counting_range(rng);

which does not seem to be the case. The code in the library looks like it constructs the range from the first and last _value_ of the rng:

template<class Range>

inline iterator_range<counting_iterator<BOOST_DEDUCED_TYPENAME range_value<Range>::type> > counting_range(Range& rng) {

typedef counting_iterator<BOOST_DEDUCED_TYPENAME range_value<Range>::type> counting_iterator_t; typedef iterator_range<counting_iterator_t> result_t; return boost::empty(rng)

? result_t() : result_t(

counting_iterator_t(*boost::begin(rng)), counting_iterator_t(*boost::prior(boost::end(rng))));

}

I want to be able to use the counting range in a range based for like this:

for(auto it : counting_range(rng | indexed(0))) { *it; it.index(); } I also vote for a way to use indexed adaptor in the range based for loop directly. The model for the new indexed adaptor could be something like enumerate() in Python. Much much nicer than using a counter variable.

Change History (5)

comment:1 by Nathan Ridge, 9 years ago

I confess I find it surprising that an overload of counting_range() that takes a range exists at all.

I agree that constructing a counting range from the first and last values of a range seems arbitrary, but constructing a counting range from the begin and end *iterator* of a range seems pointless (how would the resulting range be different from the original one?).

Neil, what use cases did you have in mind for this overload of counting_range()?

comment:2 by Neil Groves, 9 years ago

Status: newassigned

I believe this is just very wrong. I'll sort this out. I'm inclined to remove counting_range to avoid a surprising change of semantic and replace it with something that is less bonkers.

in reply to:  1 comment:3 by marc.glisse@…, 9 years ago

Replying to nathanridge:

I confess I find it surprising that an overload of counting_range() that takes a range exists at all.

I agree that constructing a counting range from the first and last values of a range seems arbitrary, but constructing a counting range from the begin and end *iterator* of a range seems pointless (how would the resulting range be different from the original one?).

It should be the reciprocal of adaptors::indirect. In a range for loop, there is an implicit iterator iter going from begin to end, and you get *iter for each element. With indirect, you get **iter. With counting_range (constructed from iterators, because the constructor from a range is too weird), you get iter (not dereferenced). It can be extremely useful and should be available in boost adaptors with the usual | syntax and a clearer name. This is a documented use of counting_iterator.

comment:4 by Neil Groves, 9 years ago

Resolution: fixed
Status: assignedclosed

The counting_range is now just a dumb wrapper for a range of counting_iterator with entirely consistent semantics to the underlying iterator. I agree that other counting type ranges and adapters are useful but that's not this ticket. This ticket is about the defect of the counting_range function that takes ranges.

The adaptor that has been mentioned may be useful, but I don't want to make it a counted adaptor. This is just too bonkers even for my code! I am happy to create something else for doing the opposite of indirecting (directing?!). I shall consider adding a directed adaptor.

in reply to:  4 comment:5 by Nathan Ridge, 9 years ago

Replying to neilgroves:

I am happy to create something else for doing the opposite of indirecting (directing?!). I shall consider adding a directed adaptor.

In P-Stade Oven it is called 'outdirected': http://p-stade.sourceforge.net/oven/doc/html/oven/range_adaptors.html#oven.range_adaptors.outdirected. (I'm not necessarily saying we should call it the same, just pointing out the "prior art".)

Note: See TracTickets for help on using tickets.