This is an archive of the discontinued LLVM Phabricator instance.

Update the llvm::enumerate utility class result_pair to use the 'iterator_traits<R>::reference' instead of 'ValueOfIter<R> &'.
ClosedPublic

Authored by rriddle on Jun 20 2019, 4:52 PM.

Details

Summary

Update the llvm::enumerate helper class result_pair<R> to use the 'iterator_traits<R>::reference' type as the result of 'value()' instead 'ValueOfRange<R> &'. This enables support for iterators that return value types, i.e. non reference. This is a common pattern for some classes of iterators, e.g. mapped_iterator.

Diff Detail

Event Timeline

rriddle created this revision.Jun 20 2019, 4:52 PM
This revision is now accepted and ready to land.Jun 20 2019, 4:56 PM
This revision was automatically updated to reflect the committed changes.

My understanding was/is that iterators can't return values instead of references (that such a thing doesn't meet the standard requirements for iterators) and that iterators basically have to have internal storage for things like this.

I think that requirement comes from the requirement that if "(*i).j" is valid" for some iterator 'i' then "i->j" must also be valid - and since op-> returns a pointer, then there must be storage.

So perhaps mapped_iterator should be fixed to be conforming?

My understanding is that input_iterators do not have to return a reference, and may return a value type or some other proxy object.

(Sorry if there is a specific website that should be linked)
See specification of LegacyInputIterator: https://en.cppreference.com/w/cpp/named_req/InputIterator
See example of iterator returning a value_type, std::istreambuf_iterator: https://en.cppreference.com/w/cpp/iterator/istreambuf_iterator

My understanding is that input_iterators do not have to return a reference, and may return a value type or some other proxy object.

(Sorry if there is a specific website that should be linked)
See specification of LegacyInputIterator: https://en.cppreference.com/w/cpp/named_req/InputIterator

This shows the issue I was mentioning - the third row of the table, that "i->m" must be equivalent to (*i).m. streambuf_iterator sidesteps it a bit perhaps because it never has a type for which "->" is valid (well, maybe it can - with a user CharT with members).

It suggests it can be implemented in other ways - with an opaque handle type rather than an actual pointer to the element type - but that's not the issue with mapped_iterator, for instance. So it still seems like mapped_iterator can/should be fixed here?

See example of iterator returning a value_type, std::istreambuf_iterator: https://en.cppreference.com/w/cpp/iterator/istreambuf_iterator

nlguillemot added inline comments.
llvm/include/llvm/ADT/STLExtras.h
1525

I think this doesn't match the previous behavior.

I think const value_reference is like T & const, not like const T &.

I wish I could suggest using a typedef like const_value_reference = (...)::const_reference and returning that, but iterator_traits doesn't have such a member typedef.

Found this due to a compile error in some downstream code.