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 <initializer_list>
37 #include <iterator>
38 #include <limits>
39 #include <memory>
40 #include <new>
41 #include <type_traits>
42 
43 PXR_NAMESPACE_OPEN_SCOPE
44 
45 // Contains parts of the small vector implementation that do not depend on
46 // *all* of TfSmallVector's template parameters.
47 class TfSmallVectorBase
48 {
49 public:
50  using size_type = std::uint32_t;
51  using difference_type = std::int32_t;
52 
53  // Returns the local capacity that may be used without increasing the size
54  // of the TfSmallVector. TfSmallVector<T, N> will never use more local
55  // capacity than is specified by N but clients that wish to maximize local
56  // occupancy in a generic way can compute N using this function.
57  template <typename U>
58  static constexpr size_type ComputeSerendipitousLocalCapacity() {
59  return (alignof(U) <= alignof(_Data<U, 0>))
60  ? sizeof(_Data<U, 0>) / sizeof(U)
61  : 0;
62  }
63 
64 protected:
65  // Invoke std::uninitialized_copy that either moves or copies entries,
66  // depending on whether the type is move constructible or not.
67  template <typename Iterator>
68  static Iterator _UninitializedMove(
69  Iterator first, Iterator last, Iterator dest) {
70  return std::uninitialized_copy(
71  std::make_move_iterator(first),
72  std::make_move_iterator(last),
73  dest);
74  }
75 
76  // Invokes either the move or copy constructor (via placement new),
77  // depending on whether U is move constructible or not.
78  template <typename U>
79  static void _MoveConstruct(U *p, U *src) {
80  new (p) U(std::move(*src));
81  }
82 
83  // The data storage, which is a union of both the local storage, as well
84  // as a pointer, holding the address to the remote storage on the heap, if
85  // used.
86  template < typename U, size_type M >
87  union _Data {
88  public:
89 
90  U *GetLocalStorage() {
91  return reinterpret_cast<U *>(_local);
92  }
93 
94  const U *GetLocalStorage() const {
95  return reinterpret_cast<const U *>(_local);
96  }
97 
98  U *GetRemoteStorage() {
99  return _remote;
100  }
101 
102  const U *GetRemoteStorage() const {
103  return _remote;
104  }
105 
106  void SetRemoteStorage(U *p) {
107  _remote = p;
108  }
109 
110  private:
111 
112  alignas(U) char _local[sizeof(U)*M];
113  U* _remote;
114 
115  };
116 
117  // For N == 0 the _Data class has been specialized to elide the local
118  // storage completely. This way we don't have to rely on compiler-specific
119  // support for 0-sized arrays.
120  template < typename U >
121  union _Data<U, 0> {
122  public:
123 
124  U *GetLocalStorage() {
125  // XXX: Could assert here. Introduce dependency on tf/diagnostic.h?
126  return nullptr;
127  }
128 
129  const U *GetLocalStorage() const {
130  // XXX: Could assert here. Introduce dependency on tf/diagnostic.h?
131  return nullptr;
132  }
133 
134  U *GetRemoteStorage() {
135  return _remote;
136  }
137 
138  const U *GetRemoteStorage() const {
139  return _remote;
140  }
141 
142  void SetRemoteStorage(U *p) {
143  _remote = p;
144  }
145 
146  private:
147 
148  U* _remote;
149 
150  };
151 
152 };
153 
176 template < typename T, uint32_t N >
178  : public TfSmallVectorBase
179 {
180 public:
181 
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 
272  TfSmallVector(std::initializer_list<T> values)
273  : TfSmallVector(values.begin(), values.end()) {
274  }
275 
276  template<typename _ForwardIterator>
277  using _EnableIfForwardIterator =
278  typename std::enable_if<
279  std::is_convertible<
280  typename std::iterator_traits<
281  _ForwardIterator>::iterator_category,
282  std::forward_iterator_tag
283  >::value
284  >::type;
285 
288  template<typename ForwardIterator,
289  typename = _EnableIfForwardIterator<ForwardIterator>>
290  TfSmallVector(ForwardIterator first, ForwardIterator last) : _capacity(N)
291  {
292  _InitStorage(std::distance(first, last));
293  std::uninitialized_copy(first, last, begin());
294  }
295 
299  _Destruct();
300  _FreeStorage();
301  }
302 
306  if (this != &rhs) {
307  assign(rhs.begin(), rhs.end());
308  }
309  return *this;
310  }
311 
315  if (this != &rhs) {
316  swap(rhs);
317  }
318  return *this;
319  }
320 
323  TfSmallVector &operator=(std::initializer_list<T> ilist) {
324  assign(ilist.begin(), ilist.end());
325  return *this;
326  }
327 
330  void swap(TfSmallVector &rhs) {
331  // Both this vector and rhs are stored locally.
332  if (_IsLocal() && rhs._IsLocal()) {
333  TfSmallVector *smaller = size() < rhs.size() ? this : &rhs;
334  TfSmallVector *larger = size() < rhs.size() ? &rhs : this;
335 
336  // Swap all the entries up to the size of the smaller vector.
337  std::swap_ranges(smaller->begin(), smaller->end(), larger->begin());
338 
339  // Move the tail end of the entries, and destruct them at the
340  // source vector.
341  for (size_type i = smaller->size(); i < larger->size(); ++i) {
342  _MoveConstruct(smaller->data() + i, &(*larger)[i]);
343  (*larger)[i].~value_type();
344  }
345 
346  // Swap sizes. Capacities are already equal in this case.
347  std::swap(smaller->_size, larger->_size);
348  }
349 
350  // Both this vector and rhs are stored remotely. Simply swap the
351  // pointers, as well as size and capacity.
352  else if (!_IsLocal() && !rhs._IsLocal()) {
353  value_type *tmp = _data.GetRemoteStorage();
354  _data.SetRemoteStorage(rhs._data.GetRemoteStorage());
355  rhs._data.SetRemoteStorage(tmp);
356 
357  std::swap(_size, rhs._size);
358  std::swap(_capacity, rhs._capacity);
359  }
360 
361  // Either this vector or rhs is stored remotely, whereas the other
362  // one is stored locally.
363  else {
364  TfSmallVector *remote = _IsLocal() ? &rhs : this;
365  TfSmallVector *local = _IsLocal() ? this : &rhs;
366 
367  // Get a pointer to the remote storage. We'll be overwriting the
368  // pointer value below, so gotta retain it first.
369  value_type *remoteStorage = remote->_GetStorage();
370 
371  // Move all the entries from the vector with the local storage, to
372  // the other vector's local storage. This will overwrite the pointer
373  // to the other vectors remote storage. Note that we will have to
374  // also destruct the elements at the source's local storage. The
375  // source will become the one with the remote storage, so those
376  // entries will be essentially freed.
377  for (size_type i = 0; i < local->size(); ++i) {
378  _MoveConstruct(
379  remote->_data.GetLocalStorage() + i, &(*local)[i]);
380  (*local)[i].~value_type();
381  }
382 
383  // Swap the remote storage into the vector which previously had the
384  // local storage. It's been properly cleaned up now.
385  local->_data.SetRemoteStorage(remoteStorage);
386 
387  // Swap sizes and capacities. Easy peasy.
388  std::swap(remote->_size, local->_size);
389  std::swap(remote->_capacity, local->_capacity);
390  }
391 
392  }
393 
396  iterator insert(const_iterator it, value_type &&v) {
397  return _Insert(it, std::move(v));
398  }
399 
402  iterator insert(const_iterator it, const value_type &v) {
403  return _Insert(it, v);
404  }
405 
408  iterator erase(const_iterator it) {
409  return erase(it, it + 1);
410  }
411 
414  iterator erase(const_iterator it, const_iterator last) {
415  value_type *p = const_cast<value_type *>(&*it);
416  value_type *q = const_cast<value_type *>(&*last);
417 
418  // If we're not removing anything, bail out.
419  if (p == q) {
420  return iterator(p);
421  }
422 
423  const size_type num = std::distance(p, q);
424 
425  // Move entries starting at last, down a few slots to starting a it.
426  value_type *e = data() + size();
427  std::move(q, e, p);
428 
429  // Destruct all the freed up slots at the end of the vector.
430  for (value_type *i = (e - num); i != e; ++i) {
431  i->~value_type();
432  }
433 
434  // Bump down the size.
435  _size -= num;
436 
437  // Return an iterator to the next entry.
438  return iterator(p);
439  }
440 
443  void reserve(size_type newCapacity) {
444  // Only reserve storage if the new capacity would grow past the local
445  // storage, or the currently allocated storage. We'll grow to
446  // accommodate exactly newCapacity entries.
447  if (newCapacity > capacity()) {
448  _GrowStorage(newCapacity);
449  }
450  }
451 
454  void resize(size_type newSize, const value_type &v = value_type()) {
455  // If the new size is smaller than the current size, let go of some
456  // entries at the tail.
457  if (newSize < size()) {
458  erase(const_iterator(data() + newSize),
459  const_iterator(data() + size()));
460  }
461 
462  // Otherwise, lets grow and fill: Reserve some storage, fill the tail
463  // end with copies of v, and update the new size.
464  else if (newSize > size()) {
465  reserve(newSize);
466  std::uninitialized_fill(data() + size(), data() + newSize, v);
467  _size = newSize;
468  }
469  }
470 
474  void clear() {
475  _Destruct();
476  _size = 0;
477  }
478 
482  template<typename ForwardIterator,
483  typename = _EnableIfForwardIterator<ForwardIterator>>
484  void assign(ForwardIterator first, ForwardIterator last) {
485  clear();
486  const size_type newSize = std::distance(first, last);
487  reserve(newSize);
488  std::uninitialized_copy(first, last, begin());
489  _size = newSize;
490  }
491 
494  void assign(std::initializer_list<T> ilist) {
495  assign(ilist.begin(), ilist.end());
496  }
497 
500  template < typename... Args >
501  void emplace_back(Args&&... args) {
502  if (size() == capacity()) {
503  _GrowStorage(_NextCapacity());
504  }
505  new (data() + size()) value_type(std::forward<Args>(args)...);
506  _size += 1;
507  }
508 
511  void push_back(const value_type &v) {
512  emplace_back(v);
513  }
514 
517  void push_back(value_type &&v) {
518  emplace_back(std::move(v));
519  }
520 
524  template <typename ForwardIterator>
525  void insert(iterator pos, ForwardIterator first, ForwardIterator last)
526  {
527  static_assert(
528  std::is_convertible<
529  typename std::iterator_traits<ForwardIterator>::iterator_category,
530  std::forward_iterator_tag>::value,
531  "Input Iterators not supported.");
532 
533  // Check for the insert-at-end special case as the very first thing so
534  // that we give the compiler the best possible opportunity to
535  // eliminate the general case code.
536  const bool insertAtEnd = pos == end();
537 
538  const long numNewElems = std::distance(first, last);
539  const size_type neededCapacity = size() + numNewElems;
540  const size_type nextCapacity =
541  std::max(_NextCapacity(), neededCapacity);
542 
543  // Insertions at the end would be handled correctly by the code below
544  // without this special case. However, insert(end(), f, l) is an
545  // extremely common operation so we provide this fast path both to
546  // avoid unneeded work and to make it easier for the compiler to
547  // eliminate dead code when pos == end().
548  if (insertAtEnd) {
549  // The reallocation here is not a simple reserve. We want to grow
550  // the storage only when there are too many new elements but the
551  // desired size is based on the growth factor.
552  if (neededCapacity > capacity()) {
553  _GrowStorage(nextCapacity);
554  }
555  std::uninitialized_copy(first, last, end());
556  _size += numNewElems;
557  return;
558  }
559 
560  if (neededCapacity > capacity()) {
561  // Because we need to realloc, we can do the insertion by copying
562  // each range, [begin(), pos), [first, last), [pos, end()), into
563  // the new storage.
564 
565  const size_type posI = std::distance(begin(), pos);
566  value_type *newStorage = _Allocate(nextCapacity);
567 
568  iterator newPrefixBegin = iterator(newStorage);
569  iterator newPos = newPrefixBegin + posI;
570  iterator newSuffixBegin = newPos + numNewElems;
571  _UninitializedMove(begin(), pos, newPrefixBegin);
572  std::uninitialized_copy(first, last, newPos);
573  _UninitializedMove(pos, end(), newSuffixBegin);
574 
575  // Destroy old data and set up this new buffer.
576  _Destruct();
577  _FreeStorage();
578  _data.SetRemoteStorage(newStorage);
579  _capacity = nextCapacity;
580  }
581  else {
582  // Insert in-place requires handling four ranges.
583  //
584  // For both the range-to-move [pos, end()) and the range-to-insert
585  // [first, last), there are two subranges: the subrange to copy
586  // and the subrange to uinitialized_copy. Note that only three of
587  // these ranges may be non-empty: either there is a non-empty
588  // prefix of [pos, end()) that needs to be copied over existing
589  // elements or there is a non-empty suffix of [first, last) that
590  // needs to be placed in uninitialized storage.
591 
592  const long numMoveElems = std::distance(pos, end());
593  const long numUninitMoves = std::min(numNewElems, numMoveElems);
594  const long numInitMoves = numMoveElems - numUninitMoves;
595  const long numUninitNews = numNewElems - numUninitMoves;
596  const long numInitNews = numNewElems - numUninitNews;
597 
598  // Move our existing elements out of the way of new elements.
599  iterator umSrc = pos + numInitMoves;
600  iterator umDst = end() + numUninitNews;
601  _UninitializedMove(umSrc, end(), umDst);
602  std::copy_backward(pos, umSrc, umDst);
603 
604  // Copy new elements into place.
605  for (long i=0; i<numInitNews; ++i, ++first, ++pos) {
606  *pos = *first;
607  }
608  std::uninitialized_copy(first, last, end());
609  }
610 
611  _size += numNewElems;
612  }
613 
616  void insert(iterator pos, std::initializer_list<T> ilist) {
617  insert(pos, ilist.begin(), ilist.end());
618  }
619 
622  void pop_back() {
623  back().~value_type();
624  _size -= 1;
625  }
626 
629  size_type size() const {
630  return _size;
631  }
632 
635  static constexpr size_type max_size() {
636  return std::numeric_limits<size_type>::max();
637  }
638 
641  bool empty() const {
642  return size() == 0;
643  }
644 
650  size_type capacity() const {
651  return _capacity;
652  }
653 
658  static constexpr size_type internal_capacity() {
659  return N;
660  }
661 
664 
665  iterator begin() {
666  return iterator(_GetStorage());
667  }
668 
669  const_iterator begin() const {
670  return const_iterator(_GetStorage());
671  }
672 
673  const_iterator cbegin() const {
674  return begin();
675  }
676 
678 
681 
682  iterator end() {
683  return iterator(_GetStorage() + size());
684  }
685 
686  const_iterator end() const {
687  return const_iterator(_GetStorage() + size());
688  }
689 
690  const_iterator cend() const {
691  return end();
692  }
693 
695 
698 
699  reverse_iterator rbegin() {
700  return reverse_iterator(end());
701  }
702 
703  const_reverse_iterator rbegin() const {
704  return const_reverse_iterator(end());
705  }
706 
707  const_reverse_iterator crbegin() const {
708  return rbegin();
709  }
710 
712 
715 
716  reverse_iterator rend() {
717  return reverse_iterator(begin());
718  }
719 
720  const_reverse_iterator rend() const {
721  return const_reverse_iterator(begin());
722  }
723 
724  const_reverse_iterator crend() const {
725  return rend();
726  }
727 
729 
732  reference front() {
733  return *begin();
734  }
735 
738  const_reference front() const {
739  return *begin();
740  }
741 
744  reference back() {
745  return *(data() + size() - 1);
746  }
747 
750  const_reference back() const {
751  return *(data() + size() - 1);
752  }
753 
756  reference operator[](size_type i) {
757  return *(data() + i);
758  }
759 
762  const_reference operator[](size_type i) const {
763  return *(data() + i);
764  }
765 
768  value_type *data() {
769  return _GetStorage();
770  }
771 
774  const value_type *data() const {
775  return _GetStorage();
776  }
777 
780  bool operator==(const TfSmallVector &rhs) const {
781  return size() == rhs.size() && std::equal(begin(), end(), rhs.begin());
782  }
783 
786  bool operator!=(const TfSmallVector &rhs) const {
787  return !operator==(rhs);
788  }
789 
790 private:
791 
792  // Returns true if the local storage is used.
793  bool _IsLocal() const {
794  return _capacity <= N;
795  }
796 
797  // Return a pointer to the storage, which is either local or remote
798  // depending on the current capacity.
799  value_type *_GetStorage() {
800  return _IsLocal() ? _data.GetLocalStorage() : _data.GetRemoteStorage();
801  }
802 
803  // Return a const pointer to the storage, which is either local or remote
804  // depending on the current capacity.
805  const value_type *_GetStorage() const {
806  return _IsLocal() ? _data.GetLocalStorage() : _data.GetRemoteStorage();
807  }
808 
809  // Free the remotely allocated storage.
810  void _FreeStorage() {
811  if (!_IsLocal()) {
812  free(_data.GetRemoteStorage());
813  }
814  }
815 
816  // Destructs all the elements stored in this vector.
817  void _Destruct() {
818  value_type *b = data();
819  value_type *e = b + size();
820  for (value_type *p = b; p != e; ++p) {
821  p->~value_type();
822  }
823  }
824 
825  // Allocate a buffer on the heap.
826  static value_type *_Allocate(size_type size) {
827  return static_cast<value_type *>(malloc(sizeof(value_type) * size));
828  }
829 
830  // Initialize the vector with new storage, updating the capacity and size.
831  void _InitStorage(size_type size) {
832  if (size > capacity()) {
833  _data.SetRemoteStorage(_Allocate(size));
834  _capacity = size;
835  }
836  _size = size;
837  }
838 
839  // Grow the storage to be able to accommodate newCapacity entries. This
840  // always allocates remotes storage.
841  void _GrowStorage(const size_type newCapacity) {
842  value_type *newStorage = _Allocate(newCapacity);
843  _UninitializedMove(begin(), end(), iterator(newStorage));
844  _Destruct();
845  _FreeStorage();
846  _data.SetRemoteStorage(newStorage);
847  _capacity = newCapacity;
848  }
849 
850  // Returns the next capacity to use for vector growth. The growth factor
851  // here is 1.5. A constant 1 is added so that we do not have to special
852  // case initial capacities of 0 and 1.
853  size_type _NextCapacity() const {
854  const size_type cap = capacity();
855  return cap + (cap / 2) + 1;
856  }
857 
858  // Insert the value v at iterator it. We use this method that takes a
859  // universal reference to de-duplicate the logic required for the insert
860  // overloads, one taking an rvalue reference, and the other one taking a
861  // const reference. This way, we can take the most optimal code path (
862  // move, or copy without making redundant copies) based on whether v is
863  // a rvalue reference or const reference.
864  template < typename U >
865  iterator _Insert(const_iterator it, U &&v) {
866  value_type *newEntry;
867 
868  // If the iterator points to the end, simply push back.
869  if (it == end()) {
870  push_back(std::forward<U>(v));
871  return end() - 1;
872  }
873 
874  // Grow the remote storage, if we need to. This invalidates iterators,
875  // so special care must be taken in order to return a new, valid
876  // iterator.
877  else if (size() == capacity()) {
878  const size_type newCapacity = _NextCapacity();
879  value_type *newStorage = _Allocate(newCapacity);
880 
881  value_type *i = const_cast<value_type *>(&*it);
882  value_type *curData = data();
883  newEntry = _UninitializedMove(curData, i, newStorage);
884 
885  new (newEntry) value_type(std::forward<U>(v));
886 
887  _UninitializedMove(i, curData + size(), newEntry + 1);
888 
889  _Destruct();
890  _FreeStorage();
891 
892  _data.SetRemoteStorage(newStorage);
893  _capacity = newCapacity;
894  }
895 
896  // Our current capacity is big enough to allow us to simply shift
897  // elements up one slot and insert v at it.
898  else {
899  // Move all the elements after it up by one slot.
900  newEntry = const_cast<value_type *>(&*it);
901  value_type *last = const_cast<value_type *>(&back());
902  new (data() + size()) value_type(std::move(*last));
903  std::move_backward(newEntry, last, last + 1);
904 
905  // Move v into the slot at the supplied iterator position.
906  newEntry->~value_type();
907  new (newEntry) value_type(std::forward<U>(v));
908  }
909 
910  // Bump size and return an iterator to the newly inserted entry.
911  ++_size;
912  return iterator(newEntry);
913  }
914 
915  // The vector storage, which is a union of the local storage and a pointer
916  // to the heap memory, if allocated.
917  _Data<value_type, N> _data;
918 
919  // The current size of the vector, i.e. how many entries it contains.
920  size_type _size;
921 
922  // The current capacity of the vector, i.e. how big the currently allocated
923  // storage space is.
924  size_type _capacity;
925 };
926 
928 
929 template < typename T, uint32_t N >
931 {
932  a.swap(b);
933 }
934 
936 
937 PXR_NAMESPACE_CLOSE_SCOPE
938 
939 #endif
void swap(ArAssetInfo &lhs, ArAssetInfo &rhs)
Definition: assetInfo.h:61
void push_back(value_type &&v)
Move an entry to the back of the vector.
Definition: smallVector.h:517
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:443
reference operator[](size_type i)
Access the specified element.
Definition: smallVector.h:756
static constexpr size_type max_size()
Returns the maximum size of this vector.
Definition: smallVector.h:635
This is a small-vector class with local storage optimization, the local storage can be specified via ...
Definition: smallVector.h:177
value_type * data()
Direct access to the underlying array.
Definition: smallVector.h:768
void swap(TfSmallVector &rhs)
Swap two vector instances.
Definition: smallVector.h:330
void insert(iterator pos, ForwardIterator first, ForwardIterator last)
Copy the range denoted by [first, last) into this vector before pos.
Definition: smallVector.h:525
const value_type * data() const
Direct access to the underlying array.
Definition: smallVector.h:774
reference back()
Returns the last element in the vector.
Definition: smallVector.h:744
void assign(ForwardIterator first, ForwardIterator last)
Clears any previously held entries, and copies entries between [ first, last ) to this vector...
Definition: smallVector.h:484
void assign(std::initializer_list< T > ilist)
Replace existing contents with the contents of ilist.
Definition: smallVector.h:494
iterator erase(const_iterator it)
Erase an entry at the given iterator.
Definition: smallVector.h:408
void emplace_back(Args &&...args)
Emplace an entry at the back of the vector.
Definition: smallVector.h:501
TfSmallVector & operator=(std::initializer_list< T > ilist)
Replace existing contents with the contents of ilist.
Definition: smallVector.h:323
void resize(size_type newSize, const value_type &v=value_type())
Resize the vector to newSize and insert copies of .
Definition: smallVector.h:454
void insert(iterator pos, std::initializer_list< T > ilist)
Insert elements from ilist starting at position pos.
Definition: smallVector.h:616
bool empty() const
Returns true if this vector is empty.
Definition: smallVector.h:641
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:629
void pop_back()
Remove the entry at the back of the vector.
Definition: smallVector.h:622
~TfSmallVector()
Destructor.
Definition: smallVector.h:298
TfSmallVector(const TfSmallVector &rhs)
Copy constructor.
Definition: smallVector.h:245
void clear()
Clear the entries in the vector.
Definition: smallVector.h:474
bool operator!=(const TfSmallVector &rhs) const
Lexicographically compares the elements in the vectors for inequality.
Definition: smallVector.h:786
bool operator==(const TfSmallVector &rhs) const
Lexicographically compares the elements in the vectors for equality.
Definition: smallVector.h:780
TfSmallVector & operator=(TfSmallVector &&rhs)
Move assignment operator.
Definition: smallVector.h:314
void push_back(const value_type &v)
Copy an entry to the back of the vector,.
Definition: smallVector.h:511
iterator insert(const_iterator it, const value_type &v)
Insert an entry at the given iterator.
Definition: smallVector.h:402
static constexpr size_type internal_capacity()
Returns the local storage capacity.
Definition: smallVector.h:658
TfSmallVector(ForwardIterator first, ForwardIterator last)
Creates a new vector containing copies of the data between first and last.
Definition: smallVector.h:290
iterator erase(const_iterator it, const_iterator last)
Erase entries between [ first, last ) from the vector.
Definition: smallVector.h:414
TfSmallVector & operator=(const TfSmallVector &rhs)
Assignment operator.
Definition: smallVector.h:305
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:762
TfSmallVector()
}@
Definition: smallVector.h:210
TfSmallVector(std::initializer_list< T > values)
Construct a new vector from initializer list.
Definition: smallVector.h:272
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:732
size_type capacity() const
Returns the current capacity of this vector.
Definition: smallVector.h:650
const_reference back() const
Returns the last elements in the vector.
Definition: smallVector.h:750
iterator insert(const_iterator it, value_type &&v)
Insert an rvalue-reference entry at the given iterator position.
Definition: smallVector.h:396
const_reference front() const
Returns the first element in the vector.
Definition: smallVector.h:738