7#ifndef PXR_BASE_VT_ARRAY_H
8#define PXR_BASE_VT_ARRAY_H
13#include "pxr/base/vt/api.h"
14#include "pxr/base/vt/hash.h"
15#include "pxr/base/vt/streamOut.h"
23#include "pxr/base/tf/preprocessorUtilsLite.h"
35PXR_NAMESPACE_OPEN_SCOPE
39class Vt_ArrayForeignDataSource
42 explicit Vt_ArrayForeignDataSource(
43 void (*detachedFn)(Vt_ArrayForeignDataSource *self) =
nullptr,
44 size_t initRefCount = 0)
45 : _refCount(initRefCount)
46 , _detachedFn(detachedFn) {}
49 template <
class T>
friend class VtArray;
51 void _ArraysDetached() {
if (_detachedFn) { _detachedFn(
this); } }
53 std::atomic<size_t> _refCount;
54 void (*_detachedFn)(Vt_ArrayForeignDataSource *self);
61 Vt_ArrayBase() : _shapeData { 0 }, _foreignSource(nullptr) {}
63 Vt_ArrayBase(Vt_ArrayForeignDataSource *foreignSrc)
64 : _shapeData { 0 }, _foreignSource(foreignSrc) {}
66 Vt_ArrayBase(Vt_ArrayBase
const &other) =
default;
67 Vt_ArrayBase(Vt_ArrayBase &&other) : Vt_ArrayBase(other) {
68 other._shapeData.clear();
69 other._foreignSource =
nullptr;
72 Vt_ArrayBase &operator=(Vt_ArrayBase
const &other) =
default;
73 Vt_ArrayBase &operator=(Vt_ArrayBase &&other) {
77 other._shapeData.clear();
78 other._foreignSource =
nullptr;
87 struct _ControlBlock {
88 _ControlBlock() : nativeRefCount(0), capacity(0) {}
89 _ControlBlock(
size_t initCount,
size_t initCap)
90 : nativeRefCount(initCount), capacity(initCap) {}
91 mutable std::atomic<size_t> nativeRefCount;
95 _ControlBlock &_GetControlBlock(
void *nativeData) {
97 return *(
reinterpret_cast<_ControlBlock *
>(nativeData) - 1);
100 _ControlBlock
const &_GetControlBlock(
void *nativeData)
const {
102 return *(
reinterpret_cast<_ControlBlock *
>(nativeData) - 1);
106 std::atomic<size_t> &_GetNativeRefCount(
void *nativeData)
const {
107 return _GetControlBlock(nativeData).nativeRefCount;
110 size_t &_GetCapacity(
void *nativeData) {
111 return _GetControlBlock(nativeData).capacity;
113 size_t const &_GetCapacity(
void *nativeData)
const {
114 return _GetControlBlock(nativeData).capacity;
117 VT_API
void _DetachCopyHook(
char const *funcName)
const;
119 Vt_ShapeData _shapeData;
120 Vt_ArrayForeignDataSource *_foreignSource;
211ARCH_PRAGMA_NON_EXPORTED_BASE_CLASS
212template<
typename ELEM>
219 typedef ELEM value_type;
260 template <
typename LegacyInputIterator>
261 VtArray(LegacyInputIterator first, LegacyInputIterator last,
263 !std::is_integral_v<LegacyInputIterator>> * =
nullptr)
269 VtArray(Vt_ArrayForeignDataSource *foreignSrc,
271 : Vt_ArrayBase(foreignSrc)
274 foreignSrc->_refCount.fetch_add(1, std::memory_order_relaxed);
276 _shapeData.totalSize =
size;
281 , _data(other._data) {
285 if (ARCH_LIKELY(!_foreignSource)) {
286 _GetNativeRefCount(_data).fetch_add(1, std::memory_order_relaxed);
289 _foreignSource->_refCount.fetch_add(1, std::memory_order_relaxed);
296 , _data(other._data) {
297 other._data =
nullptr;
301 VtArray(std::initializer_list<ELEM> initializerList)
313 explicit VtArray(
size_t n, value_type
const &value)
334 static_cast<Vt_ArrayBase &
>(*this) = std::move(other);
336 other._data =
nullptr;
342 this->
assign(initializerList.begin(), initializerList.end());
414 template <
typename... Args>
417 if (ARCH_UNLIKELY(_shapeData.otherDims[0])) {
422 size_t curSize =
size();
424 _foreignSource || !_IsUnique() || curSize ==
capacity())) {
425 value_type *newData = _AllocateCopy(
426 _data, _CapacityForSize(curSize + 1), curSize);
427 ::new (
static_cast<void*
>(newData + curSize)) value_type(
428 std::forward<Args>(args)...);
433 ::new (
static_cast<void*
>(_data + curSize)) value_type(
434 std::forward<Args>(args)...);
437 ++_shapeData.totalSize;
462 if (ARCH_UNLIKELY(_shapeData.otherDims[0])) {
466 _DetachIfNotUnique();
468 (_data +
size() - 1)->~value_type();
470 --_shapeData.totalSize;
474 size_t size()
const {
return _shapeData.totalSize; }
486 return ARCH_UNLIKELY(_foreignSource) ?
size() : _GetCapacity(_data);
497 return (std::numeric_limits<ptrdiff_t>::max() - 1 -
498 sizeof(_ControlBlock)) /
sizeof(value_type);
511 value_type *newData =
512 _data ? _AllocateCopy(_data, num,
size()) : _AllocateNew(num);
546 return resize(newSize, value_type());
551 void resize(
size_t newSize, value_type
const &value) {
554 std::uninitialized_fill(b, e, value);
560 void resize(
size_t newSize, value_type &value) {
561 return resize(newSize,
const_cast<value_type
const &
>(value));
566 void resize(
size_t newSize, value_type &&value) {
567 return resize(newSize,
const_cast<value_type
const &
>(value));
574 template <
class FillElemsFn>
575 void resize(
size_t newSize, FillElemsFn &&fillElems) {
576 const size_t oldSize =
size();
577 if (oldSize == newSize) {
585 const bool growing = newSize > oldSize;
586 value_type *newData = _data;
590 newData = _AllocateNew(newSize);
591 std::forward<FillElemsFn>(fillElems)(newData, newData + newSize);
593 else if (_IsUnique()) {
595 if (newSize > _GetCapacity(_data)) {
596 newData = _AllocateCopy(_data, newSize, oldSize);
599 std::forward<FillElemsFn>(fillElems)(newData + oldSize,
604 for (
auto *cur = newData + newSize,
605 *
end = newData + oldSize; cur !=
end; ++cur) {
612 _AllocateCopy(_data, newSize, growing ? oldSize : newSize);
615 std::forward<FillElemsFn>(fillElems)(newData + oldSize,
621 if (newData != _data) {
626 _shapeData.totalSize = newSize;
635 for (value_type *p = _data, *e = _data +
size(); p != e; ++p) {
643 _shapeData.totalSize = 0;
653 if (std::less_equal<const_pointer>{}(
cdata(), valuePtr) &&
654 std::less<const_pointer>{}(valuePtr,
cdata() +
size())) {
655 value_type tmp { value };
657 std::make_move_iterator(std::addressof(tmp)),
658 std::make_move_iterator(std::addressof(tmp) + 1));
660 return insert(pos, valuePtr, valuePtr + 1);
670 if (std::less_equal<const_pointer>{}(
cdata(), valuePtr) &&
671 std::less<const_pointer>{}(valuePtr,
cdata() +
size())) {
672 value_type tmp { std::move(value) };
674 std::make_move_iterator(std::addressof(tmp)),
675 std::make_move_iterator(std::addressof(tmp) + 1));
678 std::make_move_iterator(valuePtr),
679 std::make_move_iterator(valuePtr + 1));
690 if (std::less_equal<const_pointer>{}(
cdata(), fillPtr) &&
691 std::less<const_pointer>{}(fillPtr,
cdata() +
size())) {
692 value_type tmp { fill };
694 std::uninitialized_fill(b, e, tmp);
698 std::uninitialized_fill(b, e, fill);
706 return insert(pos, ilist.begin(), ilist.end());
713 template <
class LegacyInputIterator>
715 !std::is_integral_v<LegacyInputIterator>,
iterator>
718 LegacyInputIterator first, LegacyInputIterator last) {
719 return insert(pos, std::distance(first, last),
721 std::uninitialized_copy(first, last, b);
731 template <
class FillElemsFn>
733 !std::is_integral_v<std::decay_t<FillElemsFn>>,
740 resize(count, std::forward<FillElemsFn>(fillElems));
744 const size_t newSize =
size() + count;
753 std::uninitialized_copy(
754 std::make_move_iterator(iend-count),
755 std::make_move_iterator(iend), iend);
756 std::move_backward(ncpos, iend-count, iend);
759 value_type *p = std::addressof(*ncpos);
760 std::forward<FillElemsFn>(fillElems)(p, p + count);
762 _shapeData.totalSize = newSize;
767 value_type* newData = _AllocateNew(newSize);
768 size_t posOffset = std::distance(
cbegin(), pos);
769 std::uninitialized_copy(
770 std::make_move_iterator(
begin()),
771 std::make_move_iterator(
begin() + posOffset), newData);
772 std::uninitialized_copy(
773 std::make_move_iterator(
begin() + posOffset),
774 std::make_move_iterator(
end()),
775 newData + posOffset + count);
779 _shapeData.totalSize = newSize;
780 std::forward<FillElemsFn>(fillElems)(
781 newData + posOffset, newData + posOffset + count);
782 return begin() + posOffset;
787 value_type* newData = _AllocateNew(newSize);
788 size_t posOffset = std::distance(
cbegin(), pos);
789 std::uninitialized_copy(
cbegin(), pos, newData);
790 std::uninitialized_copy(pos,
cend(), newData + posOffset + count);
794 _shapeData.totalSize = newSize;
795 std::forward<FillElemsFn>(fillElems)(
796 newData + posOffset, newData + posOffset + count);
797 return begin() + posOffset;
816 return erase(pos, pos+1);
836 return std::next(
begin(), std::distance(
cbegin(), last));
838 if ((first ==
cbegin()) && (last ==
cend())) {
845 value_type* removeStart =
846 std::next(_data, std::distance(
cbegin(), first));
847 value_type* removeEnd = std::next(_data, std::distance(
cbegin(), last));
848 value_type* endIt = std::next(_data,
size());
849 size_t newSize =
size() - std::distance(first, last);
853 value_type* deleteIt = std::move(removeEnd, endIt, removeStart);
854 for (; deleteIt != endIt; ++deleteIt) {
855 deleteIt->~value_type();
857 _shapeData.totalSize = newSize;
864 value_type* newData = _AllocateNew(newSize);
865 value_type* newMiddle = std::uninitialized_copy(
866 _data, removeStart, newData);
867 value_type* newEnd = std::uninitialized_copy(
868 removeEnd, endIt, newMiddle);
871 std::distance(_data, removeStart));
874 _shapeData.totalSize = newSize;
885 template <
class ForwardIter>
886 typename std::enable_if<!std::is_integral<ForwardIter>::value>::type
887 assign(ForwardIter first, ForwardIter last) {
890 std::uninitialized_copy(first, last, b);
892 ForwardIter
const &first, &last;
895 resize(std::distance(first, last), _Copier { first, last });
904 void assign(
size_t n,
const value_type &fill) {
907 std::uninitialized_fill(b, e, fill);
909 const value_type &fill;
912 resize(n, _Filler { fill });
920 void assign(std::initializer_list<ELEM> initializerList) {
921 assign(initializerList.begin(), initializerList.end());
926 std::swap(_data, other._data);
927 std::swap(_shapeData, other._shapeData);
928 std::swap(_foreignSource, other._foreignSource);
935 return data()[index];
940 return data()[index];
947 _data == other._data &&
948 _shapeData == other._shapeData &&
949 _foreignSource == other._foreignSource;
955 (*_GetShapeData() == *other._GetShapeData() &&
961 return !(*
this == other);
972 return _DetachIfNotUnique(
false);
977 Vt_ShapeData
const *_GetShapeData()
const {
980 Vt_ShapeData *_GetShapeData() {
988 void operator()(std::ostream &out)
const {
989 VtStreamOut(*_p++, out);
999 VtArray::_Streamer streamer(self.
cdata());
1000 VtStreamOutArray(out, self._GetShapeData(), streamer);
1009 bool _DetachIfNotUnique(
bool invokeHook=
true) {
1015 _DetachCopyHook(__ARCH_PRETTY_FUNCTION__);
1017 auto *newData = _AllocateCopy(_data,
size(),
size());
1023 inline bool _IsUnique()
const {
1025 (ARCH_LIKELY(!_foreignSource) && _GetNativeRefCount(_data) == 1);
1028 inline size_t _CapacityForSize(
size_t sz)
const {
1037 value_type *_AllocateNew(
size_t capacity) {
1044 ?
sizeof(_ControlBlock) +
capacity *
sizeof(value_type)
1045 : std::numeric_limits<size_t>::max();
1046 void *
data = ::operator
new(numBytes);
1050 return reinterpret_cast<value_type *
>(
1051 static_cast<_ControlBlock *
>(
data) + 1);
1054 value_type *_AllocateCopy(value_type *src,
size_t newCapacity,
1057 value_type *newData = _AllocateNew(newCapacity);
1058 std::uninitialized_copy(src, src + numToCopy, newData);
1065 if (ARCH_LIKELY(!_foreignSource)) {
1067 if (_GetNativeRefCount(_data).fetch_sub(
1068 1, std::memory_order_release) == 1) {
1069 std::atomic_thread_fence(std::memory_order_acquire);
1070 for (value_type *p = _data, *e = _data + _shapeData.totalSize;
1074 ::operator
delete(
static_cast<void *
>(
1075 std::addressof(_GetControlBlock(_data))));
1081 if (_foreignSource->_refCount.fetch_sub(
1082 1, std::memory_order_release) == 1) {
1083 std::atomic_thread_fence(std::memory_order_acquire);
1084 _foreignSource->_ArraysDetached();
1087 _foreignSource =
nullptr;
1096#define VT_ARRAY_EXTERN_TMPL(unused, elem) \
1097 VT_API_TEMPLATE_CLASS(VtArray< VT_TYPE(elem) >);
1098TF_PP_SEQ_FOR_EACH(VT_ARRAY_EXTERN_TMPL, ~, VT_SCALAR_VALUE_TYPES)
1100template <
class HashState,
class ELEM>
1101inline std::enable_if_t<VtIsHashable<ELEM>()>
1104 h.Append(array.
size());
1105 h.AppendContiguous(array.
cdata(), array.
size());
1108template <
class ELEM>
1109typename std::enable_if<VtIsHashable<ELEM>(),
size_t>::type
1115template <
typename T>
1119struct Vt_ArrayOpHelp {
1120 static T Add(T l, T r) {
return l + r; }
1121 static T Sub(T l, T r) {
return l - r; }
1122 static T Mul(T l, T r) {
return l * r; }
1123 static T Div(T l, T r) {
return l / r; }
1124 static T Mod(T l, T r) {
return l % r; }
1128struct Vt_ArrayOpHelpScalar {
1129 static T Mul(T l,
double r) {
return l * r; }
1130 static T Mul(
double l, T r) {
return l * r; }
1131 static T Div(T l,
double r) {
return l / r; }
1132 static T Div(
double l, T r) {
return l / r; }
1138struct Vt_ArrayOpHelp<bool> {
1139 static bool Add(
bool l,
bool r) {
return l | r; }
1140 static bool Sub(
bool l,
bool r) {
return l ^ r; }
1141 static bool Mul(
bool l,
bool r) {
return l & r; }
1142 static bool Div(
bool l,
bool r) {
return l; }
1143 static bool Mod(
bool l,
bool r) {
return false; }
1147struct Vt_ArrayOpHelpScalar<bool> {
1148 static bool Mul(
bool l,
double r) {
return l && (r != 0.0); }
1149 static bool Mul(
double l,
bool r) {
return (l != 0.0) && r; }
1150 static bool Div(
bool l,
double r) {
return (r == 0.0) || l; }
1151 static bool Div(
double l,
bool r) {
return !r || (l != 0.0); }
1154#define VTOPERATOR_CPPARRAY(op, opName) \
1155 template <class T> \
1157 operator op (VtArray<T> const &lhs, VtArray<T> const &rhs) \
1159 using Op = Vt_ArrayOpHelp<T>; \
1161 if (!lhs.empty() && !rhs.empty() && lhs.size() != rhs.size()) { \
1162 TF_CODING_ERROR("Non-conforming inputs for operator %s", #op); \
1163 return VtArray<T>(); \
1166 const bool leftEmpty = lhs.size() == 0, rightEmpty = rhs.size() == 0; \
1167 VtArray<T> ret(leftEmpty ? rhs.size() : lhs.size()); \
1168 T zero = VtZero<T>(); \
1171 rhs.begin(), rhs.end(), ret.begin(), \
1172 [zero](T const &r) { return Op:: opName (zero, r); }); \
1174 else if (rightEmpty) { \
1176 lhs.begin(), lhs.end(), ret.begin(), \
1177 [zero](T const &l) { return Op:: opName (l, zero); }); \
1181 lhs.begin(), lhs.end(), rhs.begin(), ret.begin(), \
1182 [](T const &l, T const &r) { return Op:: opName (l, r); }); \
1188ARCH_PRAGMA_FORCING_TO_BOOL
1189ARCH_PRAGMA_UNSAFE_USE_OF_BOOL
1190ARCH_PRAGMA_UNARY_MINUS_ON_UNSIGNED
1192VTOPERATOR_CPPARRAY(+, Add);
1193VTOPERATOR_CPPARRAY(-, Sub);
1194VTOPERATOR_CPPARRAY(*, Mul);
1195VTOPERATOR_CPPARRAY(/, Div);
1196VTOPERATOR_CPPARRAY(%, Mod);
1202 std::transform(a.
begin(), a.
end(), ret.begin(),
1203 [](T
const &x) { return -x; });
1211#define VTOPERATOR_CPPSCALAR(op,opName) \
1212 template<typename T> \
1213 VtArray<T> operator op (T const &scalar, VtArray<T> const &arr) { \
1214 using Op = Vt_ArrayOpHelp<T>; \
1215 VtArray<T> ret(arr.size()); \
1216 std::transform(arr.begin(), arr.end(), ret.begin(), \
1217 [&scalar](T const &aObj) { \
1218 return Op:: opName (scalar, aObj); \
1222 template<typename T> \
1223 VtArray<T> operator op (VtArray<T> const &arr, T const &scalar) { \
1224 using Op = Vt_ArrayOpHelp<T>; \
1225 VtArray<T> ret(arr.size()); \
1226 std::transform(arr.begin(), arr.end(), ret.begin(), \
1227 [&scalar](T const &aObj) { \
1228 return Op:: opName (aObj, scalar); \
1236#define VTOPERATOR_CPPSCALAR_DOUBLE(op,opName) \
1237 template<typename T> \
1238 std::enable_if_t<!std::is_same<T, double>::value, VtArray<T>> \
1239 operator op (double const &scalar, VtArray<T> const &arr) { \
1240 using Op = Vt_ArrayOpHelpScalar<T>; \
1241 VtArray<T> ret(arr.size()); \
1242 std::transform(arr.begin(), arr.end(), ret.begin(), \
1243 [&scalar](T const &aObj) { \
1244 return Op:: opName (scalar, aObj); \
1248 template<typename T> \
1249 std::enable_if_t<!std::is_same<T, double>::value, VtArray<T>> \
1250 operator op (VtArray<T> const &arr, double const &scalar) { \
1251 using Op = Vt_ArrayOpHelpScalar<T>; \
1252 VtArray<T> ret(arr.size()); \
1253 std::transform(arr.begin(), arr.end(), ret.begin(), \
1254 [&scalar](T const &aObj) { \
1255 return Op:: opName (aObj, scalar); \
1262ARCH_PRAGMA_FORCING_TO_BOOL
1263ARCH_PRAGMA_UNSAFE_USE_OF_BOOL
1264ARCH_PRAGMA_UNARY_MINUS_ON_UNSIGNED
1265VTOPERATOR_CPPSCALAR(+, Add)
1266VTOPERATOR_CPPSCALAR(-, Sub)
1267VTOPERATOR_CPPSCALAR(*, Mul)
1268VTOPERATOR_CPPSCALAR_DOUBLE(*, Mul)
1269VTOPERATOR_CPPSCALAR(/, Div)
1270VTOPERATOR_CPPSCALAR_DOUBLE(/, Div)
1271VTOPERATOR_CPPSCALAR(%, Mod)
1274PXR_NAMESPACE_CLOSE_SCOPE
Low-level utilities for informing users of various internal and external diagnostic conditions.
Defines all the types "TYPED" for which Vt creates a VtTYPEDArray typedef.
A user-extensible hashing mechanism for use with runtime hash tables.
Represents an arbitrary dimensional rectangular container class.
VtArray(Vt_ArrayForeignDataSource *foreignSrc, ElementType *data, size_t size, bool addRef=true)
Create an array with foreign source.
ELEM ElementType
Type this array holds.
VtArray(LegacyInputIterator first, LegacyInputIterator last, std::enable_if_t< !std::is_integral_v< LegacyInputIterator > > *=nullptr)
Create an array from a pair of iterators.
VtArray const & AsConst() const noexcept
Return *this as a const reference.
VtArray & operator=(VtArray &&other)
Move assign from other.
VtArray & operator=(std::initializer_list< ELEM > initializerList)
Replace current array contents with those in initializerList.
friend void swap(VtArray &lhs, VtArray &rhs)
Swap array contents.
bool IsIdentical(VtArray const &other) const
Tests if two arrays are identical, i.e.
friend std::ostream & operator<<(std::ostream &out, const VtArray &self)
Outputs a comma-separated list of the values in the array surrounded by square brackets [].
bool operator!=(VtArray const &other) const
Tests two arrays for inequality.
VtArray(std::initializer_list< ELEM > initializerList)
Initialize array from the contents of a initializerList.
bool MakeUnique()
Ensure that this array does not share its underlying data with any other instance by making a copy if...
VtArray(VtArray const &other)
Copy other. The new array shares underlying data with other.
VtArray(size_t n)
Create an array filled with n value-initialized elements.
ElementType & operator[](size_t index)
Allows usage of [i].
VtArray()
Create an empty array.
VtArray(VtArray &&other)
Move from other.
ElementType const & operator[](size_t index) const
Allows usage of [i].
VtArray & operator=(VtArray const &other)
Copy assign from other.
bool operator==(VtArray const &other) const
Tests two arrays for equality. See also IsIdentical().
VtArray(size_t n, value_type const &value)
Create an array filled with n copies of value.
Define preprocessor function name macros.
void resize(size_t newSize, value_type &value)
Resize this array.
void assign(std::initializer_list< ELEM > initializerList)
Assign array contents via intializer list Equivalent to:
void pop_back()
Remove the last element of an array.
ElementType & reference
Reference type.
std::enable_if_t< !std::is_integral_v< std::decay_t< FillElemsFn > >, iterator > insert(const_iterator pos, size_t count, FillElemsFn &&fillElems)
Insert count elements into the array starting at pos, calling fillElems(first, last) to construct the...
const_reverse_iterator rend() const
Return a const reverse iterator to the start of the array.
const_reference front() const
Return a const reference to the first element in this array.
const_pointer cdata() const
Return a const pointer to the data held by this array.
ElementType * iterator
Iterator type.
size_t size() const
Return the total number of elements in this array.
const_iterator begin() const
Return a const iterator to the start of the array.
iterator erase(const_iterator pos)
Removes a single element at pos from the array.
std::enable_if_t< !std::is_integral_v< LegacyInputIterator >, iterator > insert(const_iterator pos, LegacyInputIterator first, LegacyInputIterator last)
Insert the elements from the range [first, last) into the array at pos.
constexpr size_t max_size() const
Return a theoretical maximum size limit for the container.
const_pointer data() const
Return a const pointer to this array's data.
pointer data()
Return a non-const pointer to this array's data.
void reserve(size_t num)
Ensure enough memory is allocated to hold num elements.
const_iterator cbegin() const
Return a const iterator to the start of the array.
iterator insert(const_iterator pos, value_type &&value)
Insert by moving a single element at pos into the array.
std::reverse_iterator< const_iterator > const_reverse_iterator
Reverse const iterator type.
void swap(VtArray &other)
Swap the contents of this array with other.
void push_back(ElementType const &element)
Appends an element at the end of the array.
ElementType * pointer
Pointer type.
iterator insert(const_iterator pos, value_type const &value)
Insert a copy of a single element at pos into the array.
ElementType const * const_iterator
Const iterator type.
void assign(size_t n, const value_type &fill)
Assign array contents.
iterator insert(const_iterator pos, size_t count, value_type const &fill)
Insert count copies of fill starting at pos in the array.
const_reference back() const
Return a const reference to the last element in this array.
ElementType const & const_reference
Const reference type.
bool empty() const
Return true if this array contains no elements, false otherwise.
reverse_iterator rend()
Return a reverse iterator to the start of the array.
reference front()
Return a non-const reference to the first element in this array.
std::enable_if<!std::is_integral< ForwardIter >::value >::type assign(ForwardIter first, ForwardIter last)
Assign array contents.
const_reference cback() const
Return a const reference to the last element in this array.
size_t capacity() const
Return the number of items this container can grow to hold without triggering a (re)allocation.
void resize(size_t newSize)
Resize this array.
void resize(size_t newSize, value_type &&value)
Resize this array.
const_reverse_iterator crbegin() const
Return a const reverse iterator to the end of the array.
ElementType const * const_pointer
Const pointer type.
std::reverse_iterator< iterator > reverse_iterator
Reverse iterator type.
const_iterator cend() const
Return a const iterator to the end of the array.
iterator erase(const_iterator first, const_iterator last)
Remove a range of elements [first, last) from the array.
void resize(size_t newSize, value_type const &value)
Resize this array.
iterator insert(const_iterator pos, std::initializer_list< ELEM > ilist)
Insert the contents of ilist into the array at pos.
const_reverse_iterator crend() const
Return a const reverse iterator to the start of the array.
void emplace_back(Args &&... args)
Initializes a new element at the end of the array.
void clear()
Equivalent to resize(0).
iterator end()
Returns a non-const iterator to the end of the array.
const_iterator end() const
Return a const iterator to the end of the array.
reverse_iterator rbegin()
Return a non-const reverse iterator to the end of the array.
void push_back(ElementType &&element)
Appends an element at the end of the array.
iterator begin()
Return a non-const iterator to the start of the array.
void resize(size_t newSize, FillElemsFn &&fillElems)
Resize this array.
const_reference cfront() const
Return a const reference to the first element in this array.
const_reverse_iterator rbegin() const
Return a const reverse iterator to the end of the array.
reference back()
Return a reference to the last element in this array.
#define TF_DEV_AXIOM(cond)
The same as TF_AXIOM, but compiled only in dev builds.
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
std::size_t hash_value(const half h)
Overload hash_value for half.
Pragmas for controlling compiler-specific behaviors.
A trait to detect instantiations of VtArray, specialized in array.h.