All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
smallVector.h
Go to the documentation of this file.
1 //
2 // Copyright 2019 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef TF_SMALL_VECTOR_H
25 #define TF_SMALL_VECTOR_H
26 
29 
30 #include "pxr/pxr.h"
31 
32 #include <algorithm>
33 #include <cstddef>
34 #include <cstdint>
35 #include <cstdlib>
36 #include <iterator>
37 #include <limits>
38 #include <memory>
39 #include <new>
40 #include <type_traits>
41 
42 PXR_NAMESPACE_OPEN_SCOPE
43 
44 // Contains parts of the small vector implementation that do not depend on
45 // *all* of TfSmallVector's template parameters.
46 class TfSmallVectorBase
47 {
48 public:
49  using size_type = std::uint32_t;
50  using difference_type = std::int32_t;
51 
52  // Returns the local capacity that may be used without increasing the size
53  // of the TfSmallVector. TfSmallVector<T, N> will never use more local
54  // capacity than is specified by N but clients that wish to maximize local
55  // occupancy in a generic way can compute N using this function.
56  template <typename U>
57  static constexpr size_type ComputeSerendipitousLocalCapacity() {
58  return (alignof(U) <= alignof(_Data<U, 0>))
59  ? sizeof(_Data<U, 0>) / sizeof(U)
60  : 0;
61  }
62 
63 protected:
64  // Invoke std::uninitialized_copy that either moves or copies entries,
65  // depending on whether the type is move constructible or not.
66  template <typename Iterator>
67  static void _UninitializedMove(
68  Iterator first, Iterator last, Iterator dest) {
69  std::uninitialized_copy(
70  std::make_move_iterator(first),
71  std::make_move_iterator(last),
72  dest);
73  }
74 
75  // Invokes either the move or copy constructor (via placement new),
76  // depending on whether U is move constructible or not.
77  template <typename U>
78  static void _MoveConstruct(U *p, U *src) {
79  new (p) U(std::move(*src));
80  }
81 
82  // The data storage, which is a union of both the local storage, as well
83  // as a pointer, holding the address to the remote storage on the heap, if
84  // used.
85  template < typename U, size_type M >
86  union _Data {
87  public:
88 
89  U *GetLocalStorage() {
90  return reinterpret_cast<U *>(_local);
91  }
92 
93  const U *GetLocalStorage() const {
94  return reinterpret_cast<const U *>(_local);
95  }
96 
97  U *GetRemoteStorage() {
98  return _remote;
99  }
100 
101  const U *GetRemoteStorage() const {
102  return _remote;
103  }
104 
105  void SetRemoteStorage(U *p) {
106  _remote = p;
107  }
108 
109  private:
110 
111  alignas(U) char _local[sizeof(U)*M];
112  U* _remote;
113 
114  };
115 
116  // For N == 0 the _Data class has been specialized to elide the local
117  // storage completely. This way we don't have to rely on compiler-specific
118  // support for 0-sized arrays.
119  template < typename U >
120  union _Data<U, 0> {
121  public:
122 
123  U *GetLocalStorage() {
124  // XXX: Could assert here. Introduce dependency on tf/diagnostic.h?
125  return nullptr;
126  }
127 
128  const U *GetLocalStorage() const {
129  // XXX: Could assert here. Introduce dependency on tf/diagnostic.h?
130  return nullptr;
131  }
132 
133  U *GetRemoteStorage() {
134  return _remote;
135  }
136 
137  const U *GetRemoteStorage() const {
138  return _remote;
139  }
140 
141  void SetRemoteStorage(U *p) {
142  _remote = p;
143  }
144 
145  private:
146 
147  U* _remote;
148 
149  };
150 
151 };
152 
175 template < typename T, uint32_t N >
177  : public TfSmallVectorBase
178 {
179 public:
180 
188 
191 
192  typedef T value_type;
193  typedef T& reference;
194  typedef const T& const_reference;
195 
197 
200 
201  using iterator = T*;
202  using const_iterator = const T*;
203  typedef std::reverse_iterator<iterator> reverse_iterator;
204  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
205 
207 
210  TfSmallVector() : _size(0), _capacity(N) {}
211 
214  explicit TfSmallVector(size_type n) :
215  _capacity(N) {
216  _InitStorage(n);
217  value_type *d = data();
218  for (size_type i = 0; i < n; ++i) {
219  new (d + i) value_type();
220  }
221  }
222 
225  TfSmallVector(size_type n, const value_type &v) :
226  _capacity(N) {
227  _InitStorage(n);
228  std::uninitialized_fill_n(data(), n, v);
229  }
230 
233  enum DefaultInitTag { DefaultInit };
234  TfSmallVector(size_type n, DefaultInitTag) :
235  _capacity(N) {
236  _InitStorage(n);
237  value_type *d = data();
238  for (size_type i = 0; i < n; ++i) {
239  new (d + i) value_type;
240  }
241  }
242 
245  TfSmallVector(const TfSmallVector &rhs) : _capacity(N) {
246  _InitStorage(rhs.size());
247  std::uninitialized_copy(rhs.begin(), rhs.end(), begin());
248  }
249 
252  TfSmallVector(TfSmallVector &&rhs) : _size(0), _capacity(N) {
253  // If rhs can not be stored locally, take rhs's remote storage and
254  // reset rhs to empty.
255  if (rhs.size() > N) {
256  _data.SetRemoteStorage(rhs._data.GetRemoteStorage());
257  std::swap(_capacity, rhs._capacity);
258  }
259 
260  // If rhs is stored locally, it's faster to simply move the entries
261  // into this vector's storage, destruct the entries at rhs, and swap
262  // sizes. Note that capacities will be the same in this case, so no
263  // need to swap those.
264  else {
265  _UninitializedMove(rhs.begin(), rhs.end(), begin());
266  rhs._Destruct();
267  }
268  std::swap(_size, rhs._size);
269  }
270 
271  template<typename _ForwardIterator>
272  using _EnableIfForwardIterator =
273  typename std::enable_if<
274  std::is_convertible<
275  typename std::iterator_traits<
276  _ForwardIterator>::iterator_category,
277  std::forward_iterator_tag
278  >::value
279  >::type;
280 
283  template<typename ForwardIterator,
284  typename = _EnableIfForwardIterator<ForwardIterator>>
285  TfSmallVector(ForwardIterator first, ForwardIterator last) : _capacity(N)
286  {
287  _InitStorage(std::distance(first, last));
288  std::uninitialized_copy(first, last, begin());
289  }
290 
294  _Destruct();
295  _FreeStorage();
296  }
297 
301  if (this != &rhs) {
302  assign(rhs.begin(), rhs.end());
303  }
304  return *this;
305  }
306 
310  if (this != &rhs) {
311  swap(rhs);
312  }
313  return *this;
314  }
315 
318  void swap(TfSmallVector &rhs) {
319  using std::swap;
320 
321  // Both this vector and rhs are stored locally.
322  if (_IsLocal() && rhs._IsLocal()) {
323  TfSmallVector<T, N> *small = size() < rhs.size() ? this : &rhs;
324  TfSmallVector<T, N> *large = size() < rhs.size() ? &rhs : this;
325 
326  // Swap all the entries up to the size of the smaller vector.
327  std::swap_ranges(small->begin(), small->end(), large->begin());
328 
329  // Move the tail end of the entries, and destruct them at the
330  // source vector.
331  for (size_type i = small->size(); i < large->size(); ++i) {
332  _MoveConstruct(small->data() + i, &(*large)[i]);
333  (*large)[i].~value_type();
334  }
335 
336  // Swap sizes. Capacities are already equal in this case.
337  swap(small->_size, large->_size);
338  }
339 
340  // Both this vector and rhs are stored remotely. Simply swap the
341  // pointers, as well as size and capacity.
342  else if (!_IsLocal() && !rhs._IsLocal()) {
343  value_type *tmp = _data.GetRemoteStorage();
344  _data.SetRemoteStorage(rhs._data.GetRemoteStorage());
345  rhs._data.SetRemoteStorage(tmp);
346 
347  swap(_size, rhs._size);
348  swap(_capacity, rhs._capacity);
349  }
350 
351  // Either this vector or rhs is stored remotely, whereas the other
352  // one is stored locally.
353  else {
354  TfSmallVector<T, N> *remote = _IsLocal() ? &rhs : this;
355  TfSmallVector<T, N> *local = _IsLocal() ? this : &rhs;
356 
357  // Get a pointer to the remote storage. We'll be overwriting the
358  // pointer value below, so gotta retain it first.
359  value_type *remoteStorage = remote->_GetStorage();
360 
361  // Move all the entries from the vector with the local storage, to
362  // the other vector's local storage. This will overwrite the pointer
363  // to the other vectors remote storage. Note that we will have to
364  // also destruct the elements at the source's local storage. The
365  // source will become the one with the remote storage, so those
366  // entries will be essentially freed.
367  for (size_type i = 0; i < local->size(); ++i) {
368  _MoveConstruct(
369  remote->_data.GetLocalStorage() + i, &(*local)[i]);
370  (*local)[i].~value_type();
371  }
372 
373  // Swap the remote storage into the vector which previously had the
374  // local storage. It's been properly cleaned up now.
375  local->_data.SetRemoteStorage(remoteStorage);
376 
377  // Swap sizes and capacities. Easy peasy.
378  swap(remote->_size, local->_size);
379  swap(remote->_capacity, local->_capacity);
380  }
381 
382  }
383 
386  iterator insert(const_iterator it, value_type &&v) {
387  return _Insert(it, std::move(v));
388  }
389 
392  iterator insert(const_iterator it, const value_type &v) {
393  return _Insert(it, v);
394  }
395 
398  iterator erase(const_iterator it) {
399  return erase(it, it + 1);
400  }
401 
404  iterator erase(const_iterator it, const_iterator last) {
405  value_type *p = const_cast<value_type *>(&*it);
406  value_type *q = const_cast<value_type *>(&*last);
407 
408  // If we're not removing anything, bail out.
409  if (p == q) {
410  return iterator(p);
411  }
412 
413  const size_type num = std::distance(p, q);
414 
415  // Move entries starting at last, down a few slots to starting a it.
416  value_type *e = data() + size();
417  std::move(q, e, p);
418 
419  // Destruct all the freed up slots at the end of the vector.
420  for (value_type *i = (e - num); i != e; ++i) {
421  i->~value_type();
422  }
423 
424  // Bump down the size.
425  _size -= num;
426 
427  // Return an iterator to the next entry.
428  return iterator(p);
429  }
430 
433  void reserve(size_type newCapacity) {
434  // Only reserve storage if the new capacity would grow past the local
435  // storage, or the currently allocated storage. We'll grow to
436  // accommodate exactly newCapacity entries.
437  if (newCapacity > capacity()) {
438  _GrowStorage(newCapacity);
439  }
440  }
441 
444  void resize(size_type newSize, const value_type &v = value_type()) {
445  // If the new size is smaller than the current size, let go of some
446  // entries at the tail.
447  if (newSize < size()) {
448  erase(const_iterator(data() + newSize),
449  const_iterator(data() + size()));
450  }
451 
452  // Otherwise, lets grow and fill: Reserve some storage, fill the tail
453  // end with copies of v, and update the new size.
454  else if (newSize > size()) {
455  reserve(newSize);
456  std::uninitialized_fill(data() + size(), data() + newSize, v);
457  _size = newSize;
458  }
459  }
460 
464  void clear() {
465  _Destruct();
466  _size = 0;
467  }
468 
472  template<typename ForwardIterator,
473  typename = _EnableIfForwardIterator<ForwardIterator>>
474  void assign(ForwardIterator first, ForwardIterator last) {
475  clear();
476  const size_type newSize = std::distance(first, last);
477  reserve(newSize);
478  std::uninitialized_copy(first, last, begin());
479  _size = newSize;
480  }
481 
484  template < typename... Args >
485  void emplace_back(Args&&... args) {
486  if (size() == capacity()) {
487  _GrowStorage(_NextCapacity());
488  }
489  new (data() + size()) value_type(std::forward<Args>(args)...);
490  _size += 1;
491  }
492 
495  void push_back(const value_type &v) {
496  emplace_back(v);
497  }
498 
501  void push_back(value_type &&v) {
502  emplace_back(std::move(v));
503  }
504 
508  template <typename ForwardIterator>
509  void insert(iterator pos, ForwardIterator first, ForwardIterator last)
510  {
511  static_assert(
512  std::is_convertible<
513  typename std::iterator_traits<ForwardIterator>::iterator_category,
514  std::forward_iterator_tag>::value,
515  "Input Iterators not supported.");
516 
517  // Check for the insert-at-end special case as the very first thing so
518  // that we give the compiler the best possible opportunity to
519  // eliminate the general case code.
520  const bool insertAtEnd = pos == end();
521 
522  const long numNewElems = std::distance(first, last);
523  const size_type neededCapacity = size() + numNewElems;
524  const size_type nextCapacity =
525  std::max(_NextCapacity(), neededCapacity);
526 
527  // Insertions at the end would be handled correctly by the code below
528  // without this special case. However, insert(end(), f, l) is an
529  // extremely common operation so we provide this fast path both to
530  // avoid unneeded work and to make it easier for the compiler to
531  // eliminate dead code when pos == end().
532  if (insertAtEnd) {
533  // The reallocation here is not a simple reserve. We want to grow
534  // the storage only when there are too many new elements but the
535  // desired size is based on the growth factor.
536  if (neededCapacity > capacity()) {
537  _GrowStorage(nextCapacity);
538  }
539  std::uninitialized_copy(first, last, end());
540  _size += numNewElems;
541  return;
542  }
543 
544  if (neededCapacity > capacity()) {
545  // Because we need to realloc, we can do the insertion by copying
546  // each range, [begin(), pos), [first, last), [pos, end()), into
547  // the new storage.
548 
549  const size_type posI = std::distance(begin(), pos);
550  value_type *newStorage = _Allocate(nextCapacity);
551 
552  iterator newPrefixBegin = iterator(newStorage);
553  iterator newPos = newPrefixBegin + posI;
554  iterator newSuffixBegin = newPos + numNewElems;
555  _UninitializedMove(begin(), pos, newPrefixBegin);
556  std::uninitialized_copy(first, last, newPos);
557  _UninitializedMove(pos, end(), newSuffixBegin);
558 
559  // Destroy old data and set up this new buffer.
560  _Destruct();
561  _FreeStorage();
562  _data.SetRemoteStorage(newStorage);
563  _capacity = nextCapacity;
564  }
565  else {
566  // Insert in-place requires handling four ranges.
567  //
568  // For both the range-to-move [pos, end()) and the range-to-insert
569  // [first, last), there are two subranges: the subrange to copy
570  // and the subrange to uinitialized_copy. Note that only three of
571  // these ranges may be non-empty: either there is a non-empty
572  // prefix of [pos, end()) that needs to be copied over existing
573  // elements or there is a non-empty suffix of [first, last) that
574  // needs to be placed in uninitialized storage.
575 
576  const long numMoveElems = std::distance(pos, end());
577  const long numUninitMoves = std::min(numNewElems, numMoveElems);
578  const long numInitMoves = numMoveElems - numUninitMoves;
579  const long numUninitNews = numNewElems - numUninitMoves;
580  const long numInitNews = numNewElems - numUninitNews;
581 
582  // Move our existing elements out of the way of new elements.
583  iterator umSrc = pos + numInitMoves;
584  iterator umDst = end() + numUninitNews;
585  _UninitializedMove(umSrc, end(), umDst);
586  std::copy_backward(pos, umSrc, umDst);
587 
588  // Copy new elements into place.
589  for (long i=0; i<numInitNews; ++i, ++first, ++pos) {
590  *pos = *first;
591  }
592  std::uninitialized_copy(first, last, end());
593  }
594 
595  _size += numNewElems;
596  }
597 
600  void pop_back() {
601  back().~value_type();
602  _size -= 1;
603  }
604 
607  size_type size() const {
608  return _size;
609  }
610 
613  static constexpr size_type max_size() {
614  return std::numeric_limits<size_type>::max();
615  }
616 
619  bool empty() const {
620  return size() == 0;
621  }
622 
628  size_type capacity() const {
629  return _capacity;
630  }
631 
636  static constexpr size_type internal_capacity() {
637  return N;
638  }
639 
642 
643  iterator begin() {
644  return iterator(_GetStorage());
645  }
646 
647  const_iterator begin() const {
648  return const_iterator(_GetStorage());
649  }
650 
651  const_iterator cbegin() const {
652  return begin();
653  }
654 
656 
659 
660  iterator end() {
661  return iterator(_GetStorage() + size());
662  }
663 
664  const_iterator end() const {
665  return const_iterator(_GetStorage() + size());
666  }
667 
668  const_iterator cend() const {
669  return end();
670  }
671 
673 
676 
677  reverse_iterator rbegin() {
678  return reverse_iterator(end());
679  }
680 
681  const_reverse_iterator rbegin() const {
682  return const_reverse_iterator(end());
683  }
684 
685  const_reverse_iterator crbegin() const {
686  return rbegin();
687  }
688 
690 
693 
694  reverse_iterator rend() {
695  return reverse_iterator(begin());
696  }
697 
698  const_reverse_iterator rend() const {
699  return const_reverse_iterator(begin());
700  }
701 
702  const_reverse_iterator crend() const {
703  return rend();
704  }
705 
707 
710  reference front() {
711  return *begin();
712  }
713 
716  const_reference front() const {
717  return *begin();
718  }
719 
722  reference back() {
723  return *(data() + size() - 1);
724  }
725 
728  const_reference back() const {
729  return *(data() + size() - 1);
730  }
731 
734  reference operator[](size_type i) {
735  return *(data() + i);
736  }
737 
740  const_reference operator[](size_type i) const {
741  return *(data() + i);
742  }
743 
746  value_type *data() {
747  return _GetStorage();
748  }
749 
752  const value_type *data() const {
753  return _GetStorage();
754  }
755 
758  bool operator==(const TfSmallVector &rhs) const {
759  return size() == rhs.size() && std::equal(begin(), end(), rhs.begin());
760  }
761 
764  bool operator!=(const TfSmallVector &rhs) const {
765  return !operator==(rhs);
766  }
767 
768 private:
769 
770  // Returns true if the local storage is used.
771  bool _IsLocal() const {
772  return _capacity <= N;
773  }
774 
775  // Return a pointer to the storage, which is either local or remote
776  // depending on the current capacity.
777  value_type *_GetStorage() {
778  return _IsLocal() ? _data.GetLocalStorage() : _data.GetRemoteStorage();
779  }
780 
781  // Return a const pointer to the storage, which is either local or remote
782  // depending on the current capacity.
783  const value_type *_GetStorage() const {
784  return _IsLocal() ? _data.GetLocalStorage() : _data.GetRemoteStorage();
785  }
786 
787  // Free the remotely allocated storage.
788  void _FreeStorage() {
789  if (!_IsLocal()) {
790  free(_data.GetRemoteStorage());
791  }
792  }
793 
794  // Destructs all the elements stored in this vector.
795  void _Destruct() {
796  value_type *b = data();
797  value_type *e = b + size();
798  for (value_type *p = b; p != e; ++p) {
799  p->~value_type();
800  }
801  }
802 
803  // Allocate a buffer on the heap.
804  static value_type *_Allocate(size_type size) {
805  return static_cast<value_type *>(malloc(sizeof(value_type) * size));
806  }
807 
808  // Initialize the vector with new storage, updating the capacity and size.
809  void _InitStorage(size_type size) {
810  if (size > capacity()) {
811  _data.SetRemoteStorage(_Allocate(size));
812  _capacity = size;
813  }
814  _size = size;
815  }
816 
817  // Grow the storage to be able to accommodate newCapacity entries. This
818  // always allocates remotes storage.
819  void _GrowStorage(const size_type newCapacity) {
820  value_type *newStorage = _Allocate(newCapacity);
821  _UninitializedMove(begin(), end(), iterator(newStorage));
822  _Destruct();
823  _FreeStorage();
824  _data.SetRemoteStorage(newStorage);
825  _capacity = newCapacity;
826  }
827 
828  // Returns the next capacity to use for vector growth. The growth factor
829  // here is 1.5. A constant 1 is added so that we do not have to special
830  // case initial capacities of 0 and 1.
831  size_type _NextCapacity() const {
832  const size_type cap = capacity();
833  return cap + (cap / 2) + 1;
834  }
835 
836  // Insert the value v at iterator it. We use this method that takes a
837  // universal reference to de-duplicate the logic required for the insert
838  // overloads, one taking an rvalue reference, and the other one taking a
839  // const reference. This way, we can take the most optimal code path (
840  // move, or copy without making redundant copies) based on whether v is
841  // a rvalue reference or const reference.
842  template < typename U >
843  iterator _Insert(const_iterator it, U &&v) {
844  // If the iterator points to the end, simply push back.
845  if (it == end()) {
846  push_back(std::forward<U>(v));
847  return end() - 1;
848  }
849 
850  // Grow the remote storage, if we need to. This invalidates iterators,
851  // so special care must be taken in order to return a new, valid
852  // iterator.
853  else if (size() == capacity()) {
854  const size_type newCapacity = _NextCapacity();
855  value_type *newStorage = _Allocate(newCapacity);
856 
857  value_type *i = const_cast<value_type *>(&*it);
858  value_type *d = newStorage;
859  value_type *b = data();
860  for (; b != i; ++d, ++b) {
861  *d = std::forward<U>(*b);
862  }
863 
864  value_type *current = d;
865  new (current) value_type(std::forward<U>(v));
866 
867  const value_type *e = data() + size();
868  for (++d; b != e; ++d, ++b) {
869  *d = std::forward<U>(*b);
870  }
871 
872  _Destruct();
873  _FreeStorage();
874 
875  _data.SetRemoteStorage(newStorage);
876  _capacity = newCapacity;
877  return iterator(current);
878  }
879 
880  // Our current capacity is big enough to allow us to simply shift
881  // elements up one slot and insert v at it.
882  else {
883  // Move all the elements after it up by one slot.
884  value_type *i = const_cast<value_type *>(&*it);
885  value_type *p = const_cast<value_type *>(&back());
886  new (data() + size()) value_type(std::forward<U>(*(p--)));
887  for (; p >= i; --p) {
888  *(p + 1) = std::forward<U>(*p);
889  }
890 
891  // Move v into the slot at the supplied iterator position.
892  i->~value_type();
893  new (i) value_type(std::forward<U>(v));
894 
895  // Bump up the size;
896  _size += 1;
897 
898  // Return an iterator to the newly inserted entry.
899  return iterator(i);
900  }
901  }
902 
903  // The vector storage, which is a union of the local storage and a pointer
904  // to the heap memory, if allocated.
905  _Data<value_type, N> _data;
906 
907  // The current size of the vector, i.e. how many entries it contains.
908  size_type _size;
909 
910  // The current capacity of the vector, i.e. how big the currently allocated
911  // storage space is.
912  size_type _capacity;
913 };
914 
916 
917 template < typename T, uint32_t N >
919 {
920  a.swap(b);
921 }
922 
924 
925 PXR_NAMESPACE_CLOSE_SCOPE
926 
927 #endif
void swap(ArAssetInfo &lhs, ArAssetInfo &rhs)
Definition: assetInfo.h:60
void push_back(value_type &&v)
Move an entry to the back of the vector.
Definition: smallVector.h:501
TfSmallVector(size_type n)
Construct a vector holding n value-initialized elements.
Definition: smallVector.h:214
void reserve(size_type newCapacity)
Reserve storage for newCapacity entries.
Definition: smallVector.h:433
reference operator[](size_type i)
Access the specified element.
Definition: smallVector.h:734
static constexpr size_type max_size()
Returns the maximum size of this vector.
Definition: smallVector.h:613
This is a small-vector class with local storage optimization, the local storage can be specified via ...
Definition: smallVector.h:176
value_type * data()
Direct access to the underlying array.
Definition: smallVector.h:746
void swap(TfSmallVector &rhs)
Swap two vector instances.
Definition: smallVector.h:318
void insert(iterator pos, ForwardIterator first, ForwardIterator last)
Copy the range denoted by [first, last) into this vector before pos.
Definition: smallVector.h:509
const value_type * data() const
Direct access to the underlying array.
Definition: smallVector.h:752
reference back()
Returns the last element in the vector.
Definition: smallVector.h:722
void assign(ForwardIterator first, ForwardIterator last)
Clears any previously held entries, and copies entries between [ first, last ) to this vector...
Definition: smallVector.h:474
iterator erase(const_iterator it)
Erase an entry at the given iterator.
Definition: smallVector.h:398
void emplace_back(Args &&...args)
Emplace an entry at the back of the vector.
Definition: smallVector.h:485
void resize(size_type newSize, const value_type &v=value_type())
Resize the vector to newSize and insert copies of .
Definition: smallVector.h:444
bool empty() const
Returns true if this vector is empty.
Definition: smallVector.h:619
void swap(UsdStageLoadRules &l, UsdStageLoadRules &r)
Swap the contents of rules l and r.
size_type size() const
Returns the current size of the vector.
Definition: smallVector.h:607
void pop_back()
Remove the entry at the back of the vector.
Definition: smallVector.h:600
~TfSmallVector()
Destructor.
Definition: smallVector.h:293
TfSmallVector(const TfSmallVector &rhs)
Copy constructor.
Definition: smallVector.h:245
void clear()
Clear the entries in the vector.
Definition: smallVector.h:464
bool operator!=(const TfSmallVector &rhs) const
Lexicographically compares the elements in the vectors for inequality.
Definition: smallVector.h:764
bool operator==(const TfSmallVector &rhs) const
Lexicographically compares the elements in the vectors for equality.
Definition: smallVector.h:758
TfSmallVector & operator=(TfSmallVector &&rhs)
Move assignment operator.
Definition: smallVector.h:309
void push_back(const value_type &v)
Copy an entry to the back of the vector,.
Definition: smallVector.h:495
iterator insert(const_iterator it, const value_type &v)
Insert an entry at the given iterator.
Definition: smallVector.h:392
static constexpr size_type internal_capacity()
Returns the local storage capacity.
Definition: smallVector.h:636
TfSmallVector(ForwardIterator first, ForwardIterator last)
Creates a new vector containing copies of the data between first and last.
Definition: smallVector.h:285
iterator erase(const_iterator it, const_iterator last)
Erase entries between [ first, last ) from the vector.
Definition: smallVector.h:404
TfSmallVector & operator=(const TfSmallVector &rhs)
Assignment operator.
Definition: smallVector.h:300
DefaultInitTag
Construct a vector holding n default-initialized elements.
Definition: smallVector.h:233
const_reference operator[](size_type i) const
Access the specified element.
Definition: smallVector.h:740
TfSmallVector()
}@
Definition: smallVector.h:210
TfSmallVector(TfSmallVector &&rhs)
Move constructor.
Definition: smallVector.h:252
TfSmallVector(size_type n, const value_type &v)
Construct a vector holding n copies of v.
Definition: smallVector.h:225
reference front()
Returns the first element in the vector.
Definition: smallVector.h:710
size_type capacity() const
Returns the current capacity of this vector.
Definition: smallVector.h:628
const_reference back() const
Returns the last elements in the vector.
Definition: smallVector.h:728
iterator insert(const_iterator it, value_type &&v)
Insert an rvalue-reference entry at the given iterator position.
Definition: smallVector.h:386
const_reference front() const
Returns the first element in the vector.
Definition: smallVector.h:716