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 PXR_BASE_TF_SMALL_VECTOR_H
25 #define PXR_BASE_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  // Both this vector and rhs are stored locally.
320  if (_IsLocal() && rhs._IsLocal()) {
321  TfSmallVector *smaller = size() < rhs.size() ? this : &rhs;
322  TfSmallVector *larger = size() < rhs.size() ? &rhs : this;
323 
324  // Swap all the entries up to the size of the smaller vector.
325  std::swap_ranges(smaller->begin(), smaller->end(), larger->begin());
326 
327  // Move the tail end of the entries, and destruct them at the
328  // source vector.
329  for (size_type i = smaller->size(); i < larger->size(); ++i) {
330  _MoveConstruct(smaller->data() + i, &(*larger)[i]);
331  (*larger)[i].~value_type();
332  }
333 
334  // Swap sizes. Capacities are already equal in this case.
335  std::swap(smaller->_size, larger->_size);
336  }
337 
338  // Both this vector and rhs are stored remotely. Simply swap the
339  // pointers, as well as size and capacity.
340  else if (!_IsLocal() && !rhs._IsLocal()) {
341  value_type *tmp = _data.GetRemoteStorage();
342  _data.SetRemoteStorage(rhs._data.GetRemoteStorage());
343  rhs._data.SetRemoteStorage(tmp);
344 
345  std::swap(_size, rhs._size);
346  std::swap(_capacity, rhs._capacity);
347  }
348 
349  // Either this vector or rhs is stored remotely, whereas the other
350  // one is stored locally.
351  else {
352  TfSmallVector *remote = _IsLocal() ? &rhs : this;
353  TfSmallVector *local = _IsLocal() ? this : &rhs;
354 
355  // Get a pointer to the remote storage. We'll be overwriting the
356  // pointer value below, so gotta retain it first.
357  value_type *remoteStorage = remote->_GetStorage();
358 
359  // Move all the entries from the vector with the local storage, to
360  // the other vector's local storage. This will overwrite the pointer
361  // to the other vectors remote storage. Note that we will have to
362  // also destruct the elements at the source's local storage. The
363  // source will become the one with the remote storage, so those
364  // entries will be essentially freed.
365  for (size_type i = 0; i < local->size(); ++i) {
366  _MoveConstruct(
367  remote->_data.GetLocalStorage() + i, &(*local)[i]);
368  (*local)[i].~value_type();
369  }
370 
371  // Swap the remote storage into the vector which previously had the
372  // local storage. It's been properly cleaned up now.
373  local->_data.SetRemoteStorage(remoteStorage);
374 
375  // Swap sizes and capacities. Easy peasy.
376  std::swap(remote->_size, local->_size);
377  std::swap(remote->_capacity, local->_capacity);
378  }
379 
380  }
381 
384  iterator insert(const_iterator it, value_type &&v) {
385  return _Insert(it, std::move(v));
386  }
387 
390  iterator insert(const_iterator it, const value_type &v) {
391  return _Insert(it, v);
392  }
393 
396  iterator erase(const_iterator it) {
397  return erase(it, it + 1);
398  }
399 
402  iterator erase(const_iterator it, const_iterator last) {
403  value_type *p = const_cast<value_type *>(&*it);
404  value_type *q = const_cast<value_type *>(&*last);
405 
406  // If we're not removing anything, bail out.
407  if (p == q) {
408  return iterator(p);
409  }
410 
411  const size_type num = std::distance(p, q);
412 
413  // Move entries starting at last, down a few slots to starting a it.
414  value_type *e = data() + size();
415  std::move(q, e, p);
416 
417  // Destruct all the freed up slots at the end of the vector.
418  for (value_type *i = (e - num); i != e; ++i) {
419  i->~value_type();
420  }
421 
422  // Bump down the size.
423  _size -= num;
424 
425  // Return an iterator to the next entry.
426  return iterator(p);
427  }
428 
431  void reserve(size_type newCapacity) {
432  // Only reserve storage if the new capacity would grow past the local
433  // storage, or the currently allocated storage. We'll grow to
434  // accommodate exactly newCapacity entries.
435  if (newCapacity > capacity()) {
436  _GrowStorage(newCapacity);
437  }
438  }
439 
442  void resize(size_type newSize, const value_type &v = value_type()) {
443  // If the new size is smaller than the current size, let go of some
444  // entries at the tail.
445  if (newSize < size()) {
446  erase(const_iterator(data() + newSize),
447  const_iterator(data() + size()));
448  }
449 
450  // Otherwise, lets grow and fill: Reserve some storage, fill the tail
451  // end with copies of v, and update the new size.
452  else if (newSize > size()) {
453  reserve(newSize);
454  std::uninitialized_fill(data() + size(), data() + newSize, v);
455  _size = newSize;
456  }
457  }
458 
462  void clear() {
463  _Destruct();
464  _size = 0;
465  }
466 
470  template<typename ForwardIterator,
471  typename = _EnableIfForwardIterator<ForwardIterator>>
472  void assign(ForwardIterator first, ForwardIterator last) {
473  clear();
474  const size_type newSize = std::distance(first, last);
475  reserve(newSize);
476  std::uninitialized_copy(first, last, begin());
477  _size = newSize;
478  }
479 
482  template < typename... Args >
483  void emplace_back(Args&&... args) {
484  if (size() == capacity()) {
485  _GrowStorage(_NextCapacity());
486  }
487  new (data() + size()) value_type(std::forward<Args>(args)...);
488  _size += 1;
489  }
490 
493  void push_back(const value_type &v) {
494  emplace_back(v);
495  }
496 
499  void push_back(value_type &&v) {
500  emplace_back(std::move(v));
501  }
502 
506  template <typename ForwardIterator>
507  void insert(iterator pos, ForwardIterator first, ForwardIterator last)
508  {
509  static_assert(
510  std::is_convertible<
511  typename std::iterator_traits<ForwardIterator>::iterator_category,
512  std::forward_iterator_tag>::value,
513  "Input Iterators not supported.");
514 
515  // Check for the insert-at-end special case as the very first thing so
516  // that we give the compiler the best possible opportunity to
517  // eliminate the general case code.
518  const bool insertAtEnd = pos == end();
519 
520  const long numNewElems = std::distance(first, last);
521  const size_type neededCapacity = size() + numNewElems;
522  const size_type nextCapacity =
523  std::max(_NextCapacity(), neededCapacity);
524 
525  // Insertions at the end would be handled correctly by the code below
526  // without this special case. However, insert(end(), f, l) is an
527  // extremely common operation so we provide this fast path both to
528  // avoid unneeded work and to make it easier for the compiler to
529  // eliminate dead code when pos == end().
530  if (insertAtEnd) {
531  // The reallocation here is not a simple reserve. We want to grow
532  // the storage only when there are too many new elements but the
533  // desired size is based on the growth factor.
534  if (neededCapacity > capacity()) {
535  _GrowStorage(nextCapacity);
536  }
537  std::uninitialized_copy(first, last, end());
538  _size += numNewElems;
539  return;
540  }
541 
542  if (neededCapacity > capacity()) {
543  // Because we need to realloc, we can do the insertion by copying
544  // each range, [begin(), pos), [first, last), [pos, end()), into
545  // the new storage.
546 
547  const size_type posI = std::distance(begin(), pos);
548  value_type *newStorage = _Allocate(nextCapacity);
549 
550  iterator newPrefixBegin = iterator(newStorage);
551  iterator newPos = newPrefixBegin + posI;
552  iterator newSuffixBegin = newPos + numNewElems;
553  _UninitializedMove(begin(), pos, newPrefixBegin);
554  std::uninitialized_copy(first, last, newPos);
555  _UninitializedMove(pos, end(), newSuffixBegin);
556 
557  // Destroy old data and set up this new buffer.
558  _Destruct();
559  _FreeStorage();
560  _data.SetRemoteStorage(newStorage);
561  _capacity = nextCapacity;
562  }
563  else {
564  // Insert in-place requires handling four ranges.
565  //
566  // For both the range-to-move [pos, end()) and the range-to-insert
567  // [first, last), there are two subranges: the subrange to copy
568  // and the subrange to uinitialized_copy. Note that only three of
569  // these ranges may be non-empty: either there is a non-empty
570  // prefix of [pos, end()) that needs to be copied over existing
571  // elements or there is a non-empty suffix of [first, last) that
572  // needs to be placed in uninitialized storage.
573 
574  const long numMoveElems = std::distance(pos, end());
575  const long numUninitMoves = std::min(numNewElems, numMoveElems);
576  const long numInitMoves = numMoveElems - numUninitMoves;
577  const long numUninitNews = numNewElems - numUninitMoves;
578  const long numInitNews = numNewElems - numUninitNews;
579 
580  // Move our existing elements out of the way of new elements.
581  iterator umSrc = pos + numInitMoves;
582  iterator umDst = end() + numUninitNews;
583  _UninitializedMove(umSrc, end(), umDst);
584  std::copy_backward(pos, umSrc, umDst);
585 
586  // Copy new elements into place.
587  for (long i=0; i<numInitNews; ++i, ++first, ++pos) {
588  *pos = *first;
589  }
590  std::uninitialized_copy(first, last, end());
591  }
592 
593  _size += numNewElems;
594  }
595 
598  void pop_back() {
599  back().~value_type();
600  _size -= 1;
601  }
602 
605  size_type size() const {
606  return _size;
607  }
608 
611  static constexpr size_type max_size() {
612  return std::numeric_limits<size_type>::max();
613  }
614 
617  bool empty() const {
618  return size() == 0;
619  }
620 
626  size_type capacity() const {
627  return _capacity;
628  }
629 
634  static constexpr size_type internal_capacity() {
635  return N;
636  }
637 
640 
641  iterator begin() {
642  return iterator(_GetStorage());
643  }
644 
645  const_iterator begin() const {
646  return const_iterator(_GetStorage());
647  }
648 
649  const_iterator cbegin() const {
650  return begin();
651  }
652 
654 
657 
658  iterator end() {
659  return iterator(_GetStorage() + size());
660  }
661 
662  const_iterator end() const {
663  return const_iterator(_GetStorage() + size());
664  }
665 
666  const_iterator cend() const {
667  return end();
668  }
669 
671 
674 
675  reverse_iterator rbegin() {
676  return reverse_iterator(end());
677  }
678 
679  const_reverse_iterator rbegin() const {
680  return const_reverse_iterator(end());
681  }
682 
683  const_reverse_iterator crbegin() const {
684  return rbegin();
685  }
686 
688 
691 
692  reverse_iterator rend() {
693  return reverse_iterator(begin());
694  }
695 
696  const_reverse_iterator rend() const {
697  return const_reverse_iterator(begin());
698  }
699 
700  const_reverse_iterator crend() const {
701  return rend();
702  }
703 
705 
708  reference front() {
709  return *begin();
710  }
711 
714  const_reference front() const {
715  return *begin();
716  }
717 
720  reference back() {
721  return *(data() + size() - 1);
722  }
723 
726  const_reference back() const {
727  return *(data() + size() - 1);
728  }
729 
732  reference operator[](size_type i) {
733  return *(data() + i);
734  }
735 
738  const_reference operator[](size_type i) const {
739  return *(data() + i);
740  }
741 
744  value_type *data() {
745  return _GetStorage();
746  }
747 
750  const value_type *data() const {
751  return _GetStorage();
752  }
753 
756  bool operator==(const TfSmallVector &rhs) const {
757  return size() == rhs.size() && std::equal(begin(), end(), rhs.begin());
758  }
759 
762  bool operator!=(const TfSmallVector &rhs) const {
763  return !operator==(rhs);
764  }
765 
766 private:
767 
768  // Returns true if the local storage is used.
769  bool _IsLocal() const {
770  return _capacity <= N;
771  }
772 
773  // Return a pointer to the storage, which is either local or remote
774  // depending on the current capacity.
775  value_type *_GetStorage() {
776  return _IsLocal() ? _data.GetLocalStorage() : _data.GetRemoteStorage();
777  }
778 
779  // Return a const pointer to the storage, which is either local or remote
780  // depending on the current capacity.
781  const value_type *_GetStorage() const {
782  return _IsLocal() ? _data.GetLocalStorage() : _data.GetRemoteStorage();
783  }
784 
785  // Free the remotely allocated storage.
786  void _FreeStorage() {
787  if (!_IsLocal()) {
788  free(_data.GetRemoteStorage());
789  }
790  }
791 
792  // Destructs all the elements stored in this vector.
793  void _Destruct() {
794  value_type *b = data();
795  value_type *e = b + size();
796  for (value_type *p = b; p != e; ++p) {
797  p->~value_type();
798  }
799  }
800 
801  // Allocate a buffer on the heap.
802  static value_type *_Allocate(size_type size) {
803  return static_cast<value_type *>(malloc(sizeof(value_type) * size));
804  }
805 
806  // Initialize the vector with new storage, updating the capacity and size.
807  void _InitStorage(size_type size) {
808  if (size > capacity()) {
809  _data.SetRemoteStorage(_Allocate(size));
810  _capacity = size;
811  }
812  _size = size;
813  }
814 
815  // Grow the storage to be able to accommodate newCapacity entries. This
816  // always allocates remotes storage.
817  void _GrowStorage(const size_type newCapacity) {
818  value_type *newStorage = _Allocate(newCapacity);
819  _UninitializedMove(begin(), end(), iterator(newStorage));
820  _Destruct();
821  _FreeStorage();
822  _data.SetRemoteStorage(newStorage);
823  _capacity = newCapacity;
824  }
825 
826  // Returns the next capacity to use for vector growth. The growth factor
827  // here is 1.5. A constant 1 is added so that we do not have to special
828  // case initial capacities of 0 and 1.
829  size_type _NextCapacity() const {
830  const size_type cap = capacity();
831  return cap + (cap / 2) + 1;
832  }
833 
834  // Insert the value v at iterator it. We use this method that takes a
835  // universal reference to de-duplicate the logic required for the insert
836  // overloads, one taking an rvalue reference, and the other one taking a
837  // const reference. This way, we can take the most optimal code path (
838  // move, or copy without making redundant copies) based on whether v is
839  // a rvalue reference or const reference.
840  template < typename U >
841  iterator _Insert(const_iterator it, U &&v) {
842  // If the iterator points to the end, simply push back.
843  if (it == end()) {
844  push_back(std::forward<U>(v));
845  return end() - 1;
846  }
847 
848  // Grow the remote storage, if we need to. This invalidates iterators,
849  // so special care must be taken in order to return a new, valid
850  // iterator.
851  else if (size() == capacity()) {
852  const size_type newCapacity = _NextCapacity();
853  value_type *newStorage = _Allocate(newCapacity);
854 
855  value_type *i = const_cast<value_type *>(&*it);
856  value_type *d = newStorage;
857  value_type *b = data();
858  for (; b != i; ++d, ++b) {
859  *d = std::forward<U>(*b);
860  }
861 
862  value_type *current = d;
863  new (current) value_type(std::forward<U>(v));
864 
865  const value_type *e = data() + size();
866  for (++d; b != e; ++d, ++b) {
867  *d = std::forward<U>(*b);
868  }
869 
870  _Destruct();
871  _FreeStorage();
872 
873  _data.SetRemoteStorage(newStorage);
874  _capacity = newCapacity;
875  return iterator(current);
876  }
877 
878  // Our current capacity is big enough to allow us to simply shift
879  // elements up one slot and insert v at it.
880  else {
881  // Move all the elements after it up by one slot.
882  value_type *i = const_cast<value_type *>(&*it);
883  value_type *p = const_cast<value_type *>(&back());
884  new (data() + size()) value_type(std::forward<U>(*(p--)));
885  for (; p >= i; --p) {
886  *(p + 1) = std::forward<U>(*p);
887  }
888 
889  // Move v into the slot at the supplied iterator position.
890  i->~value_type();
891  new (i) value_type(std::forward<U>(v));
892 
893  // Bump up the size;
894  _size += 1;
895 
896  // Return an iterator to the newly inserted entry.
897  return iterator(i);
898  }
899  }
900 
901  // The vector storage, which is a union of the local storage and a pointer
902  // to the heap memory, if allocated.
903  _Data<value_type, N> _data;
904 
905  // The current size of the vector, i.e. how many entries it contains.
906  size_type _size;
907 
908  // The current capacity of the vector, i.e. how big the currently allocated
909  // storage space is.
910  size_type _capacity;
911 };
912 
914 
915 template < typename T, uint32_t N >
917 {
918  a.swap(b);
919 }
920 
922 
923 PXR_NAMESPACE_CLOSE_SCOPE
924 
925 #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:499
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:431
reference operator[](size_type i)
Access the specified element.
Definition: smallVector.h:732
static constexpr size_type max_size()
Returns the maximum size of this vector.
Definition: smallVector.h:611
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:744
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:507
const value_type * data() const
Direct access to the underlying array.
Definition: smallVector.h:750
reference back()
Returns the last element in the vector.
Definition: smallVector.h:720
void assign(ForwardIterator first, ForwardIterator last)
Clears any previously held entries, and copies entries between [ first, last ) to this vector...
Definition: smallVector.h:472
iterator erase(const_iterator it)
Erase an entry at the given iterator.
Definition: smallVector.h:396
void emplace_back(Args &&...args)
Emplace an entry at the back of the vector.
Definition: smallVector.h:483
void resize(size_type newSize, const value_type &v=value_type())
Resize the vector to newSize and insert copies of .
Definition: smallVector.h:442
bool empty() const
Returns true if this vector is empty.
Definition: smallVector.h:617
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:605
void pop_back()
Remove the entry at the back of the vector.
Definition: smallVector.h:598
~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:462
bool operator!=(const TfSmallVector &rhs) const
Lexicographically compares the elements in the vectors for inequality.
Definition: smallVector.h:762
bool operator==(const TfSmallVector &rhs) const
Lexicographically compares the elements in the vectors for equality.
Definition: smallVector.h:756
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:493
iterator insert(const_iterator it, const value_type &v)
Insert an entry at the given iterator.
Definition: smallVector.h:390
static constexpr size_type internal_capacity()
Returns the local storage capacity.
Definition: smallVector.h:634
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:402
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:738
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:708
size_type capacity() const
Returns the current capacity of this vector.
Definition: smallVector.h:626
const_reference back() const
Returns the last elements in the vector.
Definition: smallVector.h:726
iterator insert(const_iterator it, value_type &&v)
Insert an rvalue-reference entry at the given iterator position.
Definition: smallVector.h:384
const_reference front() const
Returns the first element in the vector.
Definition: smallVector.h:714