7#ifndef PXR_BASE_TF_ITERATOR_H
8#define PXR_BASE_TF_ITERATOR_H
22PXR_NAMESPACE_OPEN_SCOPE
27struct Tf_ShouldIterateOverCopy : std::false_type {};
35template <
class T,
bool Reverse>
36struct Tf_IteratorInterface {
37 typedef typename T::iterator IteratorType;
38 static IteratorType Begin(T &c) {
return c.begin(); }
39 static IteratorType End(T &c) {
return c.end(); }
42template <
class T,
bool Reverse>
43struct Tf_IteratorInterface<const T, Reverse> {
44 typedef typename T::const_iterator IteratorType;
45 static IteratorType Begin(T
const &c) {
return c.begin(); }
46 static IteratorType End(T
const &c) {
return c.end(); }
50struct Tf_IteratorInterface<T, true> {
51 typedef typename T::reverse_iterator IteratorType;
52 static IteratorType Begin(T &c) {
return c.rbegin(); }
53 static IteratorType End(T &c) {
return c.rend(); }
57struct Tf_IteratorInterface<const T, true> {
58 typedef typename T::const_reverse_iterator IteratorType;
59 static IteratorType Begin(T
const &c) {
return c.rbegin(); }
60 static IteratorType End(T
const &c) {
return c.rend(); }
158template <
class T,
bool Reverse=false>
162 struct _IteratorPairAndCopy;
163 struct _IteratorPair;
167 typedef typename std::conditional<
168 Tf_ShouldIterateOverCopy<T>::value,
169 _IteratorPairAndCopy, _IteratorPair
175 typedef Tf_IteratorInterface<T, Reverse> IterInterface;
176 typedef typename IterInterface::IteratorType Iterator;
178 typedef typename std::iterator_traits<Iterator>::reference Reference;
193 Tf_ShouldIterateOverCopy<typename std::decay<T>::type>::value,
194 "TfIterator only allows rvalues that it has been told to copy "
195 "via Tf_ShouldIterateOverCopy");
211 return _data.current == _data.end;
219 return _data.current == iterator._data.current;
225 return !(*
this == iterator);
253 if (ARCH_UNLIKELY(!*
this))
255 return *_data.current;
261 if (ARCH_UNLIKELY(!*
this))
263 return *_data.current;
269 if (ARCH_UNLIKELY(!*
this))
271 return _data.current;
276 explicit operator bool()
const {
277 return !(_data.current == _data.end);
283 operator Iterator()
const {
284 return _data.current;
291 return _data.current;
306 struct _IteratorPair {
308 explicit _IteratorPair(T &c) {
311 current = IterInterface::Begin(c);
312 end = IterInterface::End(c);
314 _IteratorPair(Iterator
const &b, Iterator
const &e) :
315 current(b), end(e) {}
322 struct _IteratorPairAndCopy :
public _IteratorPair {
323 _IteratorPairAndCopy() {}
324 explicit _IteratorPairAndCopy(T
const &c) : _IteratorPair(), _copy(c) {
325 current = IterInterface::Begin(_copy);
326 end = IterInterface::End(_copy);
328 using _IteratorPair::current;
329 using _IteratorPair::end;
345 std::forward<T>(container));
350TfMakeReverseIterator(T&& container)
353 std::forward<T>(container));
373#define TF_FOR_ALL(iter, c) \
374 for (auto iter = TfMakeIterator(c); iter; ++iter)
382#define TF_REVERSE_FOR_ALL(iter, c) \
383 for (auto iter = TfMakeReverseIterator(c); iter; ++iter)
389template <
class T,
size_t N>
401template <
typename UnderlyingIterator>
402class Tf_ProxyReferenceReverseIterator :
403 private std::reverse_iterator<UnderlyingIterator> {
406 using ReverseIterator = std::reverse_iterator<UnderlyingIterator>;
407 const ReverseIterator& _reverse_iterator()
const {
return *
this; }
408 ReverseIterator& _reverse_iterator() {
return *
this; }
409 explicit Tf_ProxyReferenceReverseIterator(
const ReverseIterator& it)
410 : ReverseIterator(it) {}
411 explicit Tf_ProxyReferenceReverseIterator(ReverseIterator&& it)
412 : ReverseIterator(it) {}
414 using iterator_type =
typename ReverseIterator::iterator_type;
415 using iterator_category =
typename ReverseIterator::iterator_category;
416 using value_type =
typename ReverseIterator::value_type;
417 using reference =
typename ReverseIterator::reference;
418 using pointer =
typename ReverseIterator::pointer;
419 using difference_type =
typename ReverseIterator::difference_type;
421 static_assert(!std::is_reference<reference>::value,
422 "Tf_ProxyReferenceReverseIterator should only be used "
423 "when the underlying iterator's reference type is a "
424 "proxy (MyTypeRef) and not a true reference (MyType&)."
425 "Use std::reverse_iterator instead.");
426 static_assert(std::is_same<iterator_category,
427 std::random_access_iterator_tag>::value,
428 "Tf_ProxyReferenceReverseIterator must wrap a random "
431 Tf_ProxyReferenceReverseIterator() =
default;
432 explicit Tf_ProxyReferenceReverseIterator(UnderlyingIterator it) :
433 ReverseIterator(it) {
438 using ReverseIterator::base;
439 using ReverseIterator::operator*;
440 using ReverseIterator::operator[];
444 pointer operator->()
const {
return std::prev(base()).operator->(); }
448 Tf_ProxyReferenceReverseIterator& operator++() {
449 ++_reverse_iterator();
453 Tf_ProxyReferenceReverseIterator operator++(
int) {
454 Tf_ProxyReferenceReverseIterator result{_reverse_iterator()};
455 ++_reverse_iterator();
459 Tf_ProxyReferenceReverseIterator& operator--() {
460 --_reverse_iterator();
464 Tf_ProxyReferenceReverseIterator operator--(
int) {
465 Tf_ProxyReferenceReverseIterator result{_reverse_iterator()};
466 --_reverse_iterator();
470 Tf_ProxyReferenceReverseIterator operator+(difference_type increment)
const {
471 return Tf_ProxyReferenceReverseIterator(_reverse_iterator() + increment);
474 Tf_ProxyReferenceReverseIterator operator-(difference_type decrement)
const {
475 return Tf_ProxyReferenceReverseIterator(_reverse_iterator() - decrement);
478 template <
typename OtherIt>
479 difference_type operator-(
480 const Tf_ProxyReferenceReverseIterator<OtherIt>& other)
const {
481 return _reverse_iterator() - other._reverse_iterator();
484 Tf_ProxyReferenceReverseIterator& operator+=(difference_type increment) {
485 _reverse_iterator() += increment;
489 Tf_ProxyReferenceReverseIterator& operator-=(difference_type decrement) {
490 _reverse_iterator() -= decrement;
494 inline friend Tf_ProxyReferenceReverseIterator
495 operator+(
const difference_type increment,
496 const Tf_ProxyReferenceReverseIterator& iterator) {
497 return Tf_ProxyReferenceReverseIterator(
498 increment + iterator._reverse_iterator());
502 template <
typename OtherIt>
503 inline friend bool operator==(
const Tf_ProxyReferenceReverseIterator& lhs,
504 const Tf_ProxyReferenceReverseIterator<OtherIt>& rhs) {
505 return lhs._reverse_iterator() == rhs._reverse_iterator();
508 template <
typename OtherIt>
509 inline friend bool operator!=(
const Tf_ProxyReferenceReverseIterator& lhs,
510 const Tf_ProxyReferenceReverseIterator<OtherIt>& rhs) {
511 return lhs._reverse_iterator() != rhs._reverse_iterator();
514 template <
typename OtherIt>
515 inline friend bool operator<(
const Tf_ProxyReferenceReverseIterator& lhs,
516 const Tf_ProxyReferenceReverseIterator<OtherIt>& rhs) {
517 return lhs._reverse_iterator() < rhs._reverse_iterator();
520 template <
typename OtherIt>
521 inline friend bool operator>(
const Tf_ProxyReferenceReverseIterator& lhs,
522 const Tf_ProxyReferenceReverseIterator<OtherIt>& rhs) {
523 return lhs._reverse_iterator() > rhs._reverse_iterator();
526 template <
typename OtherIt>
527 inline friend bool operator<=(
const Tf_ProxyReferenceReverseIterator& lhs,
528 const Tf_ProxyReferenceReverseIterator<OtherIt>& rhs) {
529 return lhs._reverse_iterator() <= rhs._reverse_iterator();
532 template <
typename OtherIt>
533 inline friend bool operator>=(
const Tf_ProxyReferenceReverseIterator& lhs,
534 const Tf_ProxyReferenceReverseIterator<OtherIt>& rhs) {
535 return lhs._reverse_iterator() >= rhs._reverse_iterator();
539PXR_NAMESPACE_CLOSE_SCOPE
constexpr size_t TfArraySize(const T(&array)[N]) noexcept
Returns the number of elements in a statically sized array.
A simple iterator adapter for STL containers.
TfIterator operator++(int)
Post-increment operator.
Reference operator*() const
Returns the element referenced by this iterator.
Iterator & operator->()
Returns a pointer to the element referenced by this iterator.
bool operator!() const
Returns true if this iterator is exhausted.
TfIterator & operator++()
Pre-increment operator.
TfIterator(T &&container)
Allow rvalues only if the container type T should be copied by TfIterator.
TfIterator GetNext() const
Returns an iterator that is positioned at the next element in the sequence.
bool operator!=(const TfIterator &iterator) const
Returns false if (*this == iterator) returns true, returns true otherwise.
TfIterator(Iterator const &begin, Iterator const &end)
Constructs an iterator to traverse a subset of the elements in a container.
TfIterator()
Default constructor. This iterator is uninitialized.
TfIterator(T &container)
Constructs an iterator to traverse each element of the specified STL container object.
Reference operator*()
Returns the element referenced by this iterator.
bool operator==(const TfIterator &iterator) const
Returns true if this Iterator.has the same position in the sequence as the specified iterator.
const Iterator & base() const
Returns an STL iterator that has the same position as this iterator.
Stripped down version of diagnostic.h that doesn't define std::string.
TfIterator< typename std::remove_reference< T >::type > TfMakeIterator(T &&container)
Helper functions for creating TfIterator objects.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.