C++17 introduced the concept of ContiguousIterator http://en.cppreference.com/w/cpp/iterator.
However it doesn't seem that there are plans to have a contiguous_iterator_tag
(in the same way we now have random_access_iterator_tag
) reported by std::iterator_traits<It>::iterator_category
.
Why is contiguous_iterator_tag
missing?
Is there a conventional protocol to determine if an iterator is Contiguous? Or a compile time test?
In the past I mentioned that for containers if there is a .data()
member that converts to a pointer to ::value
type and there is .size()
member convertible to pointer differences, then one should assume that the container is contiguous, but I can't pull an analogous feature of iterators.
One solution could be to have also a data
function for contiguous iterators.
Of course the Contiguous concept works if &(it[n]) == (&(*it)) + n
, for all n
, but this can't be checked at compile time.
EDIT: I found this video which puts this in the more broader context of C++ concepts. CppCon 2016: "Building and Extending the Iterator Hierarchy in a Modern, Multicore World" by Patrick Niedzielski. The solution uses concepts (Lite) but at the end the idea is that contiguous iterators should implement a pointer_from
function (same as my data(...)
function).
The conclusion is that concepts will help formalizing the theory, but they are not magic, in the sense that someone, somewhere will define new especially named functions over iterators that are contiguous.
The talk generalizes to segmented iterators (with corresponding functions segment
and local
), unfortunatelly it doesn't say anything about strided pointers.
The rationale is given in N4284, which is the adopted version of the contiguous iterators proposal:
This paper introduces the term "contiguous iterator" as a refinement of random-access iterator, without introducing a corresponding
contiguous_iterator_tag
, which was found to break code during the Issaquah discussions of Nevin Liber's paper N3884 "Contiguous Iterators: A Refinement of Random Access Iterators".
Some code was broken because it assumed that std::random_access_iterator
couldn't be refined, and had explicit checks against it. Basically it broke bad code that didn't rely on polymorphism to check for the categories of iterators, but it broke code nonetheless, so contiguous_iterator_tag
was removed from the proposal.
Also, there was an additional problem with std::reverse_iterator
-like classes: a reversed contiguous iterator can't be a contiguous iterator, but a regular random-access iterator. This problem could have been solved for std::reverse_iterator
, but more user-defined iterator wrappers that augment an iterator while copying its iterator category would have either lied or stopped working correctly (for example Boost iterator adaptors).
SInce my original answer above, std::contiguous_iterator_tag
was brought back in the Ranges TS and will be present in C++20. It avoids the issues mentioned above by not providing it through std::iterator_traits<T>::iterator_category
but through std::iterator_traits<T>::iterator_concept
so as to ne break any existing code.
The concepts ContiguousIterator
and ContiguousRange
. Those currently mainly differ from their RandomAccess
counterpart in that they check the iterator_concept
to known whether it's a random-access or a contiguous iterator. However, another proposal, Helpful pointers for ContiguousIterator
also proposes that contiguous iterators implement a to_address
function which returns the underlying pointer. I don't know whether this proposal is on track to get accepted or not.
来源:https://stackoverflow.com/questions/42851957/contiguous-iterator-detection