7#ifndef PXR_BASE_VT_VALUE_H
8#define PXR_BASE_VT_VALUE_H
14#include "pxr/base/tf/pyObjWrapper.h"
16#include "pxr/base/tf/pyLock.h"
21#include "pxr/base/tf/anyUniquePtr.h"
22#include "pxr/base/tf/delegatedCountPtr.h"
23#include "pxr/base/tf/meta.h"
24#include "pxr/base/tf/pointerAndBits.h"
25#include "pxr/base/tf/preprocessorUtilsLite.h"
29#include "pxr/base/tf/type.h"
31#include "pxr/base/vt/api.h"
32#include "pxr/base/vt/hash.h"
33#include "pxr/base/vt/streamOut.h"
41PXR_NAMESPACE_OPEN_SCOPE
47struct Vt_DefaultValueFactory;
51struct Vt_DefaultValueHolder
56 static Vt_DefaultValueHolder Create() {
57 return Vt_DefaultValueHolder(TfAnyUniquePtr::New<T>(),
typeid(T));
63 static Vt_DefaultValueHolder Create(T
const &val) {
64 return Vt_DefaultValueHolder(TfAnyUniquePtr::New(val),
typeid(T));
68 std::type_info
const &GetType()
const {
74 void const *GetPointer()
const {
79 Vt_DefaultValueHolder(
TfAnyUniquePtr &&ptr, std::type_info
const &type)
80 : _ptr(
std::move(ptr)), _type(&type) {}
83 std::type_info
const *_type;
90VT_API std::ostream &VtStreamOut(std::vector<VtValue>
const &val, std::ostream &);
92#define VT_VALUE_SET_STORED_TYPE(SRC, DST) \
93 template <> struct Vt_ValueStoredType<SRC> { typedef DST Type; }
95template <
class T>
struct Vt_ValueStoredType {
typedef T Type; };
96VT_VALUE_SET_STORED_TYPE(
char const *, std::string);
97VT_VALUE_SET_STORED_TYPE(
char *, std::string);
100struct Vt_ValueStoredType<char [N]> {
101 using Type = std::string;
104#ifdef PXR_PYTHON_SUPPORT_ENABLED
105VT_VALUE_SET_STORED_TYPE(pxr_boost::python::object,
TfPyObjWrapper);
108#undef VT_VALUE_SET_STORED_TYPE
112using Vt_ValueGetStored = Vt_ValueStoredType<std::decay_t<T>>;
153 static const unsigned int _LocalFlag = 1 << 0;
154 static const unsigned int _TrivialCopyFlag = 1 << 1;
155 static const unsigned int _ProxyFlag = 1 << 2;
156 static const unsigned int _AllFlags =
157 _LocalFlag | _TrivialCopyFlag | _ProxyFlag;
161 explicit _Counted(T
const &obj) : _obj(obj) {
164 bool IsUnique()
const {
return _refCount == 1; }
165 T
const &Get()
const {
return _obj; }
166 T &GetMutable() {
return _obj; }
170 mutable std::atomic<int> _refCount;
172 friend inline void TfDelegatedCountIncrement(_Counted
const *d) {
173 d->_refCount.fetch_add(1, std::memory_order_relaxed);
175 friend inline void TfDelegatedCountDecrement(_Counted
const *d)
noexcept {
176 if (d->_refCount.fetch_sub(1, std::memory_order_release) == 1) {
177 std::atomic_thread_fence(std::memory_order_acquire);
186 static const size_t _MaxLocalSize =
sizeof(
void*);
187 typedef std::aligned_storage<
188 _MaxLocalSize, _MaxLocalSize>::type _Storage;
191 using _IsTriviallyCopyable = std::integral_constant<bool,
192 std::is_trivially_default_constructible_v<T> &&
193 std::is_trivially_copyable_v<T> &&
194 std::is_trivially_copy_assignable_v<T> &&
195 std::is_trivially_destructible_v<T>>;
200 using _UsesLocalStore = std::integral_constant<bool,
201 (
sizeof(T) <=
sizeof(_Storage)) &&
202 VtValueTypeHasCheapCopy<T>::value &&
203 std::is_nothrow_move_constructible<T>::value &&
204 std::is_nothrow_move_assignable<T>::value>;
209 struct alignas(8) _TypeInfo {
211 using _CopyInitFunc = void (*)(_Storage
const &, _Storage &);
212 using _DestroyFunc = void (*)(_Storage &);
213 using _MoveFunc = void (*)(_Storage &, _Storage &);
214 using _CanHashFunc = bool (*)(_Storage
const &);
215 using _HashFunc = size_t (*)(_Storage
const &);
216 using _EqualFunc = bool (*)(_Storage
const &, _Storage
const &);
217 using _EqualPtrFunc = bool (*)(_Storage
const &,
void const *);
218 using _MakeMutableFunc = void (*)(_Storage &);
220 using _StreamOutFunc =
221 std::ostream & (*)(_Storage
const &, std::ostream &);
222 using _GetTypeidFunc = std::type_info
const & (*)(_Storage
const &);
223 using _IsArrayValuedFunc = bool (*)(_Storage
const &);
224 using _GetElementTypeidFunc =
225 std::type_info
const & (*)(_Storage
const &);
226 using _GetShapeDataFunc =
const Vt_ShapeData* (*)(_Storage
const &);
227 using _GetNumElementsFunc = size_t (*)(_Storage
const &);
228 using _ProxyHoldsTypeFunc = bool (*)(_Storage
const &, std::type_info
const &);
229 using _GetProxiedTypeFunc =
TfType (*)(_Storage
const &);
230 using _GetProxiedTypeidFunc =
231 std::type_info
const & (*)(_Storage
const &);
232 using _GetProxiedObjPtrFunc =
void const *(*)(_Storage
const &);
233 using _GetProxiedAsVtValueFunc =
VtValue (*)(_Storage
const &);
236 constexpr _TypeInfo(
const std::type_info &ti,
237 const std::type_info &elementTi,
242 _CopyInitFunc copyInit,
243 _DestroyFunc destroy,
245 _CanHashFunc canHash,
248 _EqualPtrFunc equalPtr,
249 _MakeMutableFunc makeMutable,
250 _GetPyObjFunc getPyObj,
251 _StreamOutFunc streamOut,
252 _GetTypeidFunc getTypeid,
253 _IsArrayValuedFunc isArrayValued,
254 _GetElementTypeidFunc getElementTypeid,
255 _GetShapeDataFunc getShapeData,
256 _GetNumElementsFunc getNumElements,
257 _ProxyHoldsTypeFunc proxyHoldsType,
258 _GetProxiedTypeFunc getProxiedType,
259 _GetProxiedTypeidFunc getProxiedTypeid,
260 _GetProxiedObjPtrFunc getProxiedObjPtr,
261 _GetProxiedAsVtValueFunc getProxiedAsVtValue)
263 , elementTypeInfo(elementTi)
264 , knownTypeIndex(knownTypeIndex)
267 , isHashable(isHashable)
269 , _copyInit(copyInit)
275 , _equalPtr(equalPtr)
276 , _makeMutable(makeMutable)
277 , _getPyObj(getPyObj)
278 , _streamOut(streamOut)
279 , _getTypeid(getTypeid)
280 , _isArrayValued(isArrayValued)
281 , _getElementTypeid(getElementTypeid)
282 , _getShapeData(getShapeData)
283 , _getNumElements(getNumElements)
284 , _proxyHoldsType(proxyHoldsType)
285 , _getProxiedType(getProxiedType)
286 , _getProxiedTypeid(getProxiedTypeid)
287 , _getProxiedObjPtr(getProxiedObjPtr)
288 , _getProxiedAsVtValue(getProxiedAsVtValue)
292 void CopyInit(_Storage
const &src, _Storage &dst)
const {
295 void Destroy(_Storage &storage)
const {
298 void Move(_Storage &src, _Storage &dst)
const noexcept {
301 bool CanHash(_Storage
const &storage)
const {
302 return _canHash(storage);
304 size_t Hash(_Storage
const &storage)
const {
305 return _hash(storage);
307 bool Equal(_Storage
const &lhs, _Storage
const &rhs)
const {
308 return _equal(lhs, rhs);
310 bool EqualPtr(_Storage
const &lhs,
void const *rhs)
const {
311 return _equalPtr(lhs, rhs);
313 void MakeMutable(_Storage &storage)
const {
314 _makeMutable(storage);
317 return _getPyObj(storage);
319 std::ostream &StreamOut(_Storage
const &storage,
320 std::ostream &out)
const {
321 return _streamOut(storage, out);
324 return _isArrayValued(storage);
327 return _getElementTypeid(storage);
329 std::type_info
const &
GetTypeid(_Storage
const &storage)
const {
330 return _getTypeid(storage);
332 const Vt_ShapeData* GetShapeData(_Storage
const &storage)
const {
333 return _getShapeData(storage);
335 size_t GetNumElements(_Storage
const &storage)
const {
336 return _getNumElements(storage);
338 bool ProxyHoldsType(_Storage
const &storage,
339 std::type_info
const &t)
const {
340 return _proxyHoldsType(storage, t);
342 TfType GetProxiedType(_Storage
const &storage)
const {
343 return _getProxiedType(storage);
345 std::type_info
const &GetProxiedTypeid(_Storage
const &storage)
const {
346 return _getProxiedTypeid(storage);
348 VtValue GetProxiedAsVtValue(_Storage
const &storage)
const {
349 return _getProxiedAsVtValue(storage);
351 void const *GetProxiedObjPtr(_Storage
const &storage)
const {
352 return _getProxiedObjPtr(storage);
355 const std::type_info &typeInfo;
356 const std::type_info &elementTypeInfo;
363 _CopyInitFunc _copyInit;
364 _DestroyFunc _destroy;
366 _CanHashFunc _canHash;
369 _EqualPtrFunc _equalPtr;
370 _MakeMutableFunc _makeMutable;
371 _GetPyObjFunc _getPyObj;
372 _StreamOutFunc _streamOut;
373 _GetTypeidFunc _getTypeid;
374 _IsArrayValuedFunc _isArrayValued;
375 _GetElementTypeidFunc _getElementTypeid;
376 _GetShapeDataFunc _getShapeData;
377 _GetNumElementsFunc _getNumElements;
378 _ProxyHoldsTypeFunc _proxyHoldsType;
379 _GetProxiedTypeFunc _getProxiedType;
380 _GetProxiedTypeidFunc _getProxiedTypeid;
381 _GetProxiedObjPtrFunc _getProxiedObjPtr;
382 _GetProxiedAsVtValueFunc _getProxiedAsVtValue;
390 struct _NonArrayHelper
392 static const Vt_ShapeData* GetShapeData(T
const &) {
return NULL; }
393 static size_t GetNumElements(T
const &) {
return 0; }
394 constexpr static std::type_info
const &GetElementTypeid() {
399 template <
class Array>
400 struct _IsArrayHelper
402 static const Vt_ShapeData* GetShapeData(Array
const &obj) {
403 return obj._GetShapeData();
405 static size_t GetNumElements(Array
const &obj) {
408 constexpr static std::type_info
const &GetElementTypeid() {
409 return typeid(
typename Array::ElementType);
414 template <
class ArrayEdit>
415 struct _IsArrayEditHelper : _NonArrayHelper<ArrayEdit>
417 constexpr static std::type_info
const &GetElementTypeid() {
418 return typeid(
typename ArrayEdit::ElementType);
426 using _ArrayHelper = TfConditionalType<
428 TfConditionalType<VtIsArrayEdit<T>::value,
429 _IsArrayEditHelper<T>, _NonArrayHelper<T>>
435 _TypedProxyEqualityImpl(T
const &a, T
const &b,
int) ->
decltype(a == b) {
439 template <
class NoEqual>
441 _TypedProxyEqualityImpl(NoEqual
const &a, NoEqual
const &b,
long) {
442 return VtGetProxiedObject(a) == VtGetProxiedObject(b);
447 _ErasedProxyEqualityImpl(T
const &a, T
const &b,
int) ->
decltype(a == b) {
451 template <
class NoEqual>
453 _ErasedProxyEqualityImpl(NoEqual
const &a, NoEqual
const &b,
long) {
454 return *VtGetErasedProxiedVtValue(a) == *VtGetErasedProxiedVtValue(b);
459 struct _TypedProxyHelper
461 using ProxiedType =
typename VtGetProxiedType<T>::type;
463 static bool CanHash(T
const &) {
return VtIsHashable<ProxiedType>(); }
464 static size_t Hash(T
const &obj) {
465 return VtHashValue(VtGetProxiedObject(obj));
467 static bool Equal(T
const &a, T
const &b) {
472 return _TypedProxyEqualityImpl(a, b, 0);
475#ifdef PXR_PYTHON_SUPPORT_ENABLED
476 ProxiedType
const &p = VtGetProxiedObject(obj);
478 return pxr_boost::python::api::object(p);
483 static std::ostream &StreamOut(T
const &obj, std::ostream &out) {
484 return VtStreamOut(VtGetProxiedObject(obj), out);
486 static Vt_ShapeData
const *GetShapeData(T
const &obj) {
487 return _ArrayHelper<ProxiedType>::GetShapeData(
488 VtGetProxiedObject(obj));
490 static size_t GetNumElements(T
const &obj) {
491 return _ArrayHelper<ProxiedType>::GetNumElements(
492 VtGetProxiedObject(obj));
497 static std::type_info
const &
GetTypeid(T
const &) {
498 return typeid(ProxiedType);
501 return _ArrayHelper<ProxiedType>::GetElementTypeid();
503 static VtValue GetProxiedAsVtValue(T
const &obj) {
504 return VtValue(VtGetProxiedObject(obj));
506 static bool HoldsType(T
const &tp, std::type_info
const &query) {
509 static TfType GetTfType(T
const &tp) {
510 return TfType::Find<ProxiedType>();
512 static void const *GetObjPtr(T
const &tp) {
513 return static_cast<void const *
>(&VtGetProxiedObject(tp));
518 template <
class ErasedProxy>
519 struct _ErasedProxyHelper
521 static bool CanHash(ErasedProxy
const &proxy) {
522 return VtGetErasedProxiedVtValue(proxy)->CanHash();
524 static size_t Hash(ErasedProxy
const &proxy) {
525 return VtGetErasedProxiedVtValue(proxy)->GetHash();
527 static bool Equal(ErasedProxy
const &a, ErasedProxy
const &b) {
532 return _ErasedProxyEqualityImpl(a, b, 0);
535#ifdef PXR_PYTHON_SUPPORT_ENABLED
536 VtValue const *val = VtGetErasedProxiedVtValue(obj);
538 return pxr_boost::python::api::object(*val);
543 static std::ostream &
544 StreamOut(ErasedProxy
const &obj, std::ostream &out) {
545 return VtStreamOut(obj, out);
547 static Vt_ShapeData
const *GetShapeData(ErasedProxy
const &obj) {
548 return VtGetErasedProxiedVtValue(obj)->_GetShapeData();
550 static size_t GetNumElements(ErasedProxy
const &obj) {
551 return VtGetErasedProxiedVtValue(obj)->_GetNumElements();
554 return VtGetErasedProxiedVtValue(obj)->IsArrayValued();
556 static std::type_info
const &
GetTypeid(ErasedProxy
const &obj) {
557 return VtGetErasedProxiedVtValue(obj)->GetTypeid();
560 return VtGetErasedProxiedVtValue(obj)->GetElementTypeid();
562 static VtValue GetProxiedAsVtValue(ErasedProxy
const &ep) {
563 return *VtGetErasedProxiedVtValue(ep);
566 HoldsType(ErasedProxy
const &ep, std::type_info
const &query) {
567 return VtErasedProxyHoldsType(ep, query);
569 static TfType GetTfType(ErasedProxy
const &ep) {
570 return VtGetErasedProxiedTfType(ep);
572 static void const *GetObjPtr(ErasedProxy
const &ep) {
573 VtValue const *val = VtGetErasedProxiedVtValue(ep);
574 return val ? val->_GetProxiedObjPtr() :
nullptr;
581 template <
class T,
class Container,
class Derived>
582 struct _TypeInfoImpl :
public _TypeInfo
584 static const bool IsLocal = _UsesLocalStore<T>::value;
585 static const bool HasTrivialCopy = _IsTriviallyCopyable<T>::value;
586 static const bool IsProxy = VtIsValueProxy<T>::value;
588 using ProxyHelper = TfConditionalType<
589 VtIsErasedValueProxy<T>::value,
590 _ErasedProxyHelper<T>, _TypedProxyHelper<T>>;
592 using This = _TypeInfoImpl;
594 constexpr _TypeInfoImpl()
595 : _TypeInfo(
typeid(T),
596 _ArrayHelper<T>::GetElementTypeid(),
597 Vt_KnownValueTypeDetail::GetIndex<T>(),
615 &This::_IsArrayValued,
616 &This::_GetElementTypeid,
617 &This::_GetShapeData,
618 &This::_GetNumElements,
621 &This::_ProxyHoldsType,
622 &This::_GetProxiedType,
623 &This::_GetProxiedTypeid,
624 &This::_GetProxiedObjPtr,
625 &This::_GetProxiedAsVtValue)
630 static T
const &GetObj(_Storage
const &storage) {
631 return Derived::_GetObj(_Container(storage));
634 static T &GetMutableObj(_Storage &storage) {
635 return Derived::_GetMutableObj(_Container(storage));
638 static void CopyInitObj(T
const &objSrc, _Storage &dst) {
639 Derived::_PlaceCopy(&_Container(dst), objSrc);
643 static_assert(
sizeof(Container) <=
sizeof(_Storage),
644 "Container size cannot exceed storage size.");
648 static void _CopyInit(_Storage
const &src, _Storage &dst) {
649 new (&_Container(dst)) Container(_Container(src));
652 static void _Destroy(_Storage &storage) {
653 _Container(storage).~Container();
656 static bool _CanHash(_Storage
const &storage) {
657 return ProxyHelper::CanHash(GetObj(storage));
660 static size_t _Hash(_Storage
const &storage) {
661 return ProxyHelper::Hash(GetObj(storage));
664 static bool _Equal(_Storage
const &lhs, _Storage
const &rhs) {
668 return ProxyHelper::Equal(GetObj(lhs), GetObj(rhs));
671 static bool _EqualPtr(_Storage
const &lhs,
void const *rhs) {
675 return ProxyHelper::Equal(
676 GetObj(lhs), *
static_cast<T
const *
>(rhs));
679 static void _Move(_Storage &src, _Storage &dst)
noexcept {
680 new (&_Container(dst)) Container(std::move(_Container(src)));
684 static void _MakeMutable(_Storage &storage) {
685 GetMutableObj(storage);
689 return ProxyHelper::GetPyObj(GetObj(storage));
692 static std::ostream &_StreamOut(
693 _Storage
const &storage, std::ostream &out) {
694 return ProxyHelper::StreamOut(GetObj(storage), out);
697 static std::type_info
const &_GetTypeid(_Storage
const &storage) {
698 return ProxyHelper::GetTypeid(GetObj(storage));
701 static bool _IsArrayValued(_Storage
const &storage) {
702 return ProxyHelper::IsArrayValued(GetObj(storage));
705 static std::type_info
const &
706 _GetElementTypeid(_Storage
const &storage) {
707 return ProxyHelper::GetElementTypeid(GetObj(storage));
710 static const Vt_ShapeData* _GetShapeData(_Storage
const &storage) {
711 return ProxyHelper::GetShapeData(GetObj(storage));
714 static size_t _GetNumElements(_Storage
const &storage) {
715 return ProxyHelper::GetNumElements(GetObj(storage));
719 _ProxyHoldsType(_Storage
const &storage, std::type_info
const &t) {
720 return ProxyHelper::HoldsType(GetObj(storage), t);
724 _GetProxiedType(_Storage
const &storage) {
725 return ProxyHelper::GetTfType(GetObj(storage));
728 static std::type_info
const &
729 _GetProxiedTypeid(_Storage
const &storage) {
730 return ProxyHelper::GetTypeid(GetObj(storage));
734 _GetProxiedObjPtr(_Storage
const &storage) {
735 return ProxyHelper::GetObjPtr(GetObj(storage));
739 _GetProxiedAsVtValue(_Storage
const &storage) {
740 return ProxyHelper::GetProxiedAsVtValue(GetObj(storage));
746 static Container &_Container(_Storage &storage) {
748 return *
reinterpret_cast<Container *
>(&storage);
750 static Container
const &_Container(_Storage
const &storage) {
752 return *
reinterpret_cast<Container
const *
>(&storage);
760 struct _LocalTypeInfo : _TypeInfoImpl<
766 constexpr _LocalTypeInfo()
767 : _TypeInfoImpl<T, T, _LocalTypeInfo<T>>()
771 static T &_GetMutableObj(T &obj) {
return obj; }
772 static T
const &_GetObj(T
const &obj) {
return obj; }
774 static void _PlaceCopy(T *dst, T
const &src) {
new (dst) T(src); }
781 struct _RemoteTypeInfo : _TypeInfoImpl<
783 TfDelegatedCountPtr<_Counted<T>>,
787 constexpr _RemoteTypeInfo()
794 static T &_GetMutableObj(Ptr &ptr) {
795 if (!ptr->IsUnique()) {
796 ptr = TfMakeDelegatedCountPtr<_Counted<T>>(ptr->Get());
798 return ptr->GetMutable();
800 static T
const &_GetObj(Ptr
const &ptr) {
return ptr->Get(); }
802 static void _PlaceCopy(Ptr *dst, T
const &src) {
803 new (dst) Ptr(TfDelegatedCountIncrementTag,
new _Counted<T>(src));
810 TfConditionalType<_UsesLocalStore<T>::value,
811 _LocalTypeInfo<T>, _RemoteTypeInfo<T>>;
819 friend struct _HoldAside;
821 explicit _HoldAside(
VtValue *val)
822 : info((val->
IsEmpty() || val->_IsLocalAndTriviallyCopyable())
823 ?
static_cast<_TypeInfo
const *
>(NULL) : val->_info.
Get()) {
825 info->Move(val->_storage, storage);
829 info->Destroy(storage);
832 _TypeInfo
const *info;
837 using StoredType =
typename Vt_ValueGetStored<T>::Type;
838 using TypeInfo = _TypeInfoFor<StoredType>;
844 static const TypeInfo ti;
845 static constexpr unsigned int flags =
846 (TypeInfo::IsLocal ? _LocalFlag : 0) |
847 (TypeInfo::HasTrivialCopy ? _TrivialCopyFlag : 0) |
848 (TypeInfo::IsProxy ? _ProxyFlag : 0);
852 static void Init(
VtValue *val, T
const &obj) {
853 val->_info = _GetTypeInfo();
854 if constexpr (std::is_same_v<T, StoredType>) {
855 TypeInfo::CopyInitObj(obj, val->_storage);
858 TypeInfo::CopyInitObj(StoredType {obj}, val->_storage);
885 _Init<T>::Init(
this, obj);
919 if (ARCH_LIKELY(
this != &other))
926 if (ARCH_LIKELY(
this != &other))
935 if constexpr (_TypeInfoFor<T>::IsLocal &&
936 _TypeInfoFor<T>::HasTrivialCopy) {
938 _Init<T>::Init(
this, obj);
942 _HoldAside tmp(
this);
943 _Init<T>::Init(
this, obj);
951 if (!
IsEmpty() || !rhs.IsEmpty()) {
970 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
971 "Can only VtValue::Swap with a type T that stores as T");
984 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
985 "Can only VtValue::Swap with a type T that stores as T");
987 swap(_GetMutable<T>(), rhs);
1018 template <
class T,
class Fn>
1021 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
1022 "Can only VtValue::Mutate a type T that stores as T");
1023 if (!IsHolding<T>()) {
1026 UncheckedMutate<T>(std::forward<Fn>(mutateFn));
1033 template <
class T,
class Fn>
1036 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
1037 "Can only VtValue::Mutate a type T that stores as T");
1041 T &stored =_GetMutable<T>();
1042 T tmp = std::move(stored);
1043 std::forward<Fn>(mutateFn)(tmp);
1044 stored = std::move(tmp);
1083 if (ARCH_UNLIKELY(_IsProxy())) {
1084 return _info->GetProxiedAsVtValue(
1085 _storage).GetKnownValueTypeIndex();
1087 return _info.
GetLiteral() ? _info->knownTypeIndex : -1;
1112 typedef Vt_DefaultValueFactory<T> Factory;
1116 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1117 return *(
static_cast<T
const *
>(
1118 _FailGet(Factory::Invoke,
typeid(T))));
1129 typedef Vt_DefaultValueFactory<T> Factory;
1133 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1134 return *(
static_cast<T
const *
>(
1135 _FailGet(Factory::Invoke,
typeid(T))));
1138 return UncheckedRemove<T>();
1147 return IsHolding<T>() ? UncheckedGet<T>() : def;
1151 template <
typename From,
typename To>
1153 _RegisterCast(
typeid(From),
typeid(To), castFn);
1158 template <
typename From,
typename To>
1160 _RegisterCast(
typeid(From),
typeid(To), _SimpleCast<From, To>);
1165 template <
typename From,
typename To>
1167 RegisterSimpleCast<From, To>();
1168 RegisterSimpleCast<To, From>();
1178 template <
typename T>
1209 std::type_info
const &to) {
1210 return _CanCast(from, to);
1220 template <
typename T>
1224 return *
this = _PerformCast(
typeid(T), *
this);
1247 *
this = _PerformCast(type, *
this);
1255 template <
typename T>
1257 return _CanCast(
GetTypeid(),
typeid(T));
1283 friend inline size_t hash_value(
VtValue const &val) {
1288 template <
typename T>
1290 typedef typename Vt_ValueGetStored<T>::Type Stored;
1293 template <
typename T>
1299 template <
typename T>
1301 return !(lhs == rhs);
1303 template <
typename T>
1305 return !(lhs == rhs);
1311 if (empty || rhsEmpty) {
1313 return empty == rhsEmpty;
1317 return _info.
Get()->Equal(_storage, rhs._storage);
1319 return _EqualityImpl(rhs);
1324 VT_API
friend std::ostream &
1328 VT_API
const Vt_ShapeData* _GetShapeData()
const;
1329 VT_API
size_t _GetNumElements()
const;
1330 friend struct Vt_ValueShapeDataAccess;
1338 _HoldAside tmp(&dst);
1339 dst._info = src._info;
1340 if (src._IsLocalAndTriviallyCopyable()) {
1341 dst._storage = src._storage;
1343 dst._info->CopyInit(src._storage, dst._storage);
1353 _HoldAside tmp(&dst);
1354 dst._info = src._info;
1355 if (src._IsLocalAndTriviallyCopyable()) {
1356 dst._storage = src._storage;
1358 dst._info->Move(src._storage, dst._storage);
1361 src._info.
Set(
nullptr, 0);
1367 if constexpr (VtIsKnownValueType_Workaround<T>::value) {
1368 return _info->knownTypeIndex == VtGetKnownValueTypeIndex<T>() ||
1369 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(
typeid(T)));
1372 std::type_info
const &t =
typeid(T);
1374 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(t));
1378 VT_API
bool _TypeIsImpl(std::type_info
const &queriedType)
const;
1380 VT_API
bool _EqualityImpl(
VtValue const &rhs)
const;
1385 using TypeInfo = _TypeInfoFor<T>;
1386 if constexpr (!VtIsValueProxy<T>::value) {
1389 if (ARCH_UNLIKELY(_IsProxy())) {
1390 *
this = _info->GetProxiedAsVtValue(_storage);
1393 return TypeInfo::GetMutableObj(_storage);
1399 using TypeInfo = _TypeInfoFor<T>;
1400 if constexpr (!VtIsValueProxy<T>::value) {
1403 if (ARCH_UNLIKELY(_IsProxy())) {
1404 return *
static_cast<T
const *
>(_GetProxiedObjPtr());
1407 return TypeInfo::GetObj(_storage);
1410 void const *_GetProxiedObjPtr()
const {
1411 return _info->GetProxiedObjPtr(_storage);
1417 _FailGet(Vt_DefaultValueHolder (*factory)(),
1418 std::type_info
const &queryType)
const;
1420 inline void _Clear() {
1424ARCH_PRAGMA_MAYBE_UNINITIALIZED
1425 if (_info.
GetLiteral() && !_IsLocalAndTriviallyCopyable())
1426 _info.
Get()->Destroy(_storage);
1428 _info.
Set(
nullptr, 0);
1431 inline bool _IsLocalAndTriviallyCopyable()
const {
1432 unsigned int bits = _info.
BitsAs<
unsigned int>();
1433 return (bits & (_LocalFlag | _TrivialCopyFlag)) ==
1434 (_LocalFlag | _TrivialCopyFlag);
1437 inline bool _IsProxy()
const {
1438 return _info.
BitsAs<
unsigned int>() & _ProxyFlag;
1441 VT_API
static void _RegisterCast(std::type_info
const &from,
1442 std::type_info
const &to,
1448 _PerformCast(std::type_info
const &to,
VtValue const &val);
1453 _CanCast(std::type_info
const &from, std::type_info
const &to);
1456 template <
typename From,
typename To>
1466 Vt_GetPythonObjectFromHeldValue(
VtValue const &self);
1476struct Vt_ValueShapeDataAccess {
1477 static const Vt_ShapeData* _GetShapeData(
const VtValue& value) {
1478 return value._GetShapeData();
1481 static size_t _GetNumElements(
const VtValue& value) {
1482 return value._GetNumElements();
1490struct Vt_DefaultValueFactory {
1491 static Vt_DefaultValueHolder Invoke();
1495inline Vt_DefaultValueHolder
1496Vt_DefaultValueFactory<T>::Invoke() {
1497 return Vt_DefaultValueHolder::Create<T>();
1508#define _VT_DECLARE_ZERO_VALUE_FACTORY(unused, elem) \
1510VT_API Vt_DefaultValueHolder Vt_DefaultValueFactory<VT_TYPE(elem)>::Invoke();
1512TF_PP_SEQ_FOR_EACH(_VT_DECLARE_ZERO_VALUE_FACTORY, ~,
1514 VT_MATRIX_VALUE_TYPES
1515 VT_QUATERNION_VALUE_TYPES
1516 VT_DUALQUATERNION_VALUE_TYPES)
1518#undef _VT_DECLARE_ZERO_VALUE_FACTORY
1527VtValue::Get<VtValue>() const & {
1533VtValue::Get<VtValue>() && {
1534 return std::move(*
this);
1539VtValue::UncheckedGet<VtValue>() const & {
1545VtValue::UncheckedGet<VtValue>() && {
1546 return std::move(*
this);
1551VtValue::IsHolding<VtValue>()
const {
1558VtValue::IsHolding<void>()
const {
1566PXR_NAMESPACE_CLOSE_SCOPE
Defines all the types "TYPED" for which Vt creates a VtTYPEDArray typedef.
A simple type-erased container that provides only destruction, moves and immutable,...
Stores a pointer to a ValueType which uses TfDelegatedCountIncrement and TfDelegatedCountDecrement to...
This class stores a T * and a small integer in the space of a T *.
void Set(T *ptr) noexcept
Set the pointer value to ptr.
constexpr uintptr_t GetLiteral() const noexcept
Retrieve the raw underlying value.
constexpr T * Get() const noexcept
Retrieve the pointer.
constexpr Integral BitsAs() const noexcept
Retrieve the stored bits as the integral type Integral.
Convenience class for accessing the Python Global Interpreter Lock.
Boost Python object wrapper.
TfType represents a dynamic runtime type.
Provides a container which may hold any type, and provides introspection and iteration over array typ...
VT_API std::string GetTypeName() const
Return the type name of the held typeid.
bool CanCastToTypeid(std::type_info const &type) const
Return if this can be cast to type.
T UncheckedRemove()
Make this value empty and return the held T instance.
friend bool operator==(VtValue const &lhs, T const &rhs)
Tests for equality.
int GetKnownValueTypeIndex() const
Return VtKnownValueTypeIndex<T> for the held type T.
T UncheckedGet() &&
This is an overloaded member function, provided for convenience. It differs from the above function o...
static VT_API VtValue CastToTypeOf(VtValue const &val, VtValue const &other)
Return a VtValue holding val cast to same type that other is holding.
void UncheckedMutate(Fn &&mutateFn)
Invoke mutateFn, passing it a non-const reference to the held object which must be of type T.
T Remove()
Make this value empty and return the held T instance.
static VtValue Take(T &obj)
Create a new VtValue, taking its contents from obj.
static void RegisterSimpleCast()
Register a simple cast from VtValue holding From to VtValue.
VtValue & Cast()
Return this holding value type cast to T.
VtValue & CastToTypeOf(VtValue const &other)
Return this holding value type cast to same type that other is holding.
static void RegisterSimpleBidirectionalCast()
Register a two-way cast from VtValue holding From to VtValue holding To.
bool Mutate(Fn &&mutateFn)
If this value holds an object of type T, invoke mutateFn, passing it a non-const reference to the hel...
VtValue(VtValue const &other)
Copy construct with other.
static void RegisterCast(VtValue(*castFn)(VtValue const &))
Register a cast from VtValue holding From to VtValue holding To.
size_t GetArraySize() const
Return the number of elements in the held value if IsArrayValued(), return 0 otherwise.
T Get() &&
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool CanCastToTypeOf(VtValue const &other) const
Return if this can be cast to type.
T GetWithDefault(T const &def=T()) const
Return a copy of the held object if the held object is of type T.
void UncheckedSwap(T &rhs)
Swap the held value with rhs.
void UncheckedSwap(VtValue &rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
VT_API bool IsArrayValued() const
Return true if this holds a VtArray instance, false otherwise.
bool IsEmpty() const
Returns true iff this value is empty.
VtValue & operator=(VtValue &&other) noexcept
Move assignment from another VtValue.
VtValue & CastToTypeid(std::type_info const &type)
Return this holding value type cast to type.
VT_API TfType GetType() const
Returns the TfType of the type held by this value.
VT_API std::type_info const & GetElementTypeid() const
If this value holds a VtArray or VtArrayEdit instance, return the typeid of its element type.
VtValue & operator=(T const &obj)
Assignment operator from any type.
VtValue(T const &obj)
Construct a VtValue holding a copy of obj.
VT_API size_t GetHash() const
Return a hash code for the held object by calling VtHashValue() on it.
VtValue & Swap(VtValue &rhs) noexcept
Swap this with rhs.
friend void swap(VtValue &lhs, VtValue &rhs)
Overloaded swap() for generic code/stl/etc.
static VtValue Cast(VtValue const &val)
Return a VtValue holding val cast to hold T.
bool CanCast() const
Return if this can be cast to T.
T const & Get() const &
Returns a const reference to the held object if the held object is of type T.
VT_API friend std::ostream & operator<<(std::ostream &out, const VtValue &self)
Calls through to operator << on the held object.
VtValue()
Default ctor gives empty VtValue.
VT_API bool IsArrayEditValued() const
Return true if this holds a VtArrayEdit instance, false otherwise.
friend bool operator!=(VtValue const &lhs, T const &rhs)
Tests for inequality.
static bool CanCastFromTypeidToTypeid(std::type_info const &from, std::type_info const &to)
Return if a value of type from can be cast to type to.
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
VtValue(VtValue &&other) noexcept
Move construct with other.
static VT_API VtValue CastToTypeid(VtValue const &val, std::type_info const &type)
Return a VtValue holding val cast to type.
T const & UncheckedGet() const &
Returns a const reference to the held object if the held object is of type T.
VtValue & operator=(VtValue const &other)
Copy assignment from another VtValue.
VT_API bool CanHash() const
Return true if the held object provides a hash implementation.
void Swap(T &rhs)
Swap the held value with rhs.
VT_API std::type_info const & GetTypeid() const
Return the typeid of the type held by this value.
Demangle C++ typenames generated by the typeid() facility.
Pragmas for controlling compiler-specific behaviors.
Safely compare C++ RTTI type structures.
bool TfSafeTypeCompare(const std::type_info &t1, const std::type_info &t2)
Safely compare std::type_info structures.
Definitions of basic string utilities in tf.
A trait to detect instantiations of VtArray, specialized in array.h.
A file containing basic constants and definitions.