Loading...
Searching...
No Matches
value.h
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_VT_VALUE_H
8#define PXR_BASE_VT_VALUE_H
9
10#include "pxr/pxr.h"
11
12// XXX: Include pyLock.h after pyObjWrapper.h to work around
13// Python include ordering issues.
14#include "pxr/base/tf/pyObjWrapper.h"
15
16#include "pxr/base/tf/pyLock.h"
17
19#include "pxr/base/arch/hints.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"
28#include "pxr/base/tf/tf.h"
29#include "pxr/base/tf/type.h"
30
31#include "pxr/base/vt/api.h"
32#include "pxr/base/vt/hash.h"
33#include "pxr/base/vt/streamOut.h"
34#include "pxr/base/vt/traits.h"
35#include "pxr/base/vt/types.h"
36
37#include <iosfwd>
38#include <typeinfo>
39#include <type_traits>
40
41PXR_NAMESPACE_OPEN_SCOPE
42
46template <class T>
47struct Vt_DefaultValueFactory;
48
49// This is a helper class used by Vt_DefaultValueFactory to return a value with
50// its type erased and only known at runtime via a std::type_info.
51struct Vt_DefaultValueHolder
52{
53 // Creates a value-initialized object and stores the type_info for the
54 // static type.
55 template <typename T>
56 static Vt_DefaultValueHolder Create() {
57 return Vt_DefaultValueHolder(TfAnyUniquePtr::New<T>(), typeid(T));
58 }
59
60 // Creates a copy of the object and stores the type_info for the static
61 // type.
62 template <typename T>
63 static Vt_DefaultValueHolder Create(T const &val) {
64 return Vt_DefaultValueHolder(TfAnyUniquePtr::New(val), typeid(T));
65 }
66
67 // Return the runtime type of the held object.
68 std::type_info const &GetType() const {
69 return *_type;
70 }
71
72 // Return a pointer to the held object. This may be safely cast to the
73 // static type corresponding to the type_info returned by GetType.
74 void const *GetPointer() const {
75 return _ptr.Get();
76 }
77
78private:
79 Vt_DefaultValueHolder(TfAnyUniquePtr &&ptr, std::type_info const &type)
80 : _ptr(std::move(ptr)), _type(&type) {}
81
82 TfAnyUniquePtr _ptr;
83 std::type_info const *_type;
84};
85
86class VtValue;
87
88// Overload VtStreamOut for vector<VtValue>. Produces output like [value1,
89// value2, ... valueN].
90VT_API std::ostream &VtStreamOut(std::vector<VtValue> const &val, std::ostream &);
91
92#define VT_VALUE_SET_STORED_TYPE(SRC, DST) \
93 template <> struct Vt_ValueStoredType<SRC> { typedef DST Type; }
94
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);
98
99template <size_t N>
100struct Vt_ValueStoredType<char [N]> {
101 using Type = std::string;
102};
103
104#ifdef PXR_PYTHON_SUPPORT_ENABLED
105VT_VALUE_SET_STORED_TYPE(pxr_boost::python::object, TfPyObjWrapper);
106#endif // PXR_PYTHON_SUPPORT_ENABLED
107
108#undef VT_VALUE_SET_STORED_TYPE
109
110// A metafunction that gives the type VtValue should store for a given type T.
111template <class T>
112using Vt_ValueGetStored = Vt_ValueStoredType<std::decay_t<T>>;
113
152{
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;
158
159 template <class T>
160 struct _Counted {
161 explicit _Counted(T const &obj) : _obj(obj) {
162 _refCount = 0;
163 }
164 bool IsUnique() const { return _refCount == 1; }
165 T const &Get() const { return _obj; }
166 T &GetMutable() { return _obj; }
167
168 private:
169 T _obj;
170 mutable std::atomic<int> _refCount;
171
172 friend inline void TfDelegatedCountIncrement(_Counted const *d) {
173 d->_refCount.fetch_add(1, std::memory_order_relaxed);
174 }
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);
178 delete d;
179 }
180 }
181 };
182
183 // Hold objects up to 1 word large locally. This makes the total structure
184 // 16 bytes when compiled 64 bit (1 word type-info pointer, 1 word storage
185 // space).
186 static const size_t _MaxLocalSize = sizeof(void*);
187 typedef std::aligned_storage<
188 /* size */_MaxLocalSize, /* alignment */_MaxLocalSize>::type _Storage;
189
190 template <class T>
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>>;
196
197 // Metafunction that returns true if T should be stored locally, false if it
198 // should be stored remotely.
199 template <class 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>;
205
206 // Type information base class.
207 // We force alignment here in order to ensure that TfPointerAndBits has
208 // enough room to store all TypeInfo related flags.
209 struct alignas(8) _TypeInfo {
210 private:
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 &);
219 using _GetPyObjFunc = TfPyObjWrapper (*)(_Storage const &);
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 &);
234
235 protected:
236 constexpr _TypeInfo(const std::type_info &ti,
237 const std::type_info &elementTi,
238 int knownTypeIndex,
239 bool isArray,
240 bool isHashable,
241 bool isProxy,
242 _CopyInitFunc copyInit,
243 _DestroyFunc destroy,
244 _MoveFunc move,
245 _CanHashFunc canHash,
246 _HashFunc hash,
247 _EqualFunc equal,
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)
262 : typeInfo(ti)
263 , elementTypeInfo(elementTi)
264 , knownTypeIndex(knownTypeIndex)
265 , isProxy(isProxy)
266 , isArray(isArray)
267 , isHashable(isHashable)
268 // Function table
269 , _copyInit(copyInit)
270 , _destroy(destroy)
271 , _move(move)
272 , _canHash(canHash)
273 , _hash(hash)
274 , _equal(equal)
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)
289 {}
290
291 public:
292 void CopyInit(_Storage const &src, _Storage &dst) const {
293 _copyInit(src, dst);
294 }
295 void Destroy(_Storage &storage) const {
296 _destroy(storage);
297 }
298 void Move(_Storage &src, _Storage &dst) const noexcept {
299 _move(src, dst);
300 }
301 bool CanHash(_Storage const &storage) const {
302 return _canHash(storage);
303 }
304 size_t Hash(_Storage const &storage) const {
305 return _hash(storage);
306 }
307 bool Equal(_Storage const &lhs, _Storage const &rhs) const {
308 return _equal(lhs, rhs);
309 }
310 bool EqualPtr(_Storage const &lhs, void const *rhs) const {
311 return _equalPtr(lhs, rhs);
312 }
313 void MakeMutable(_Storage &storage) const {
314 _makeMutable(storage);
315 }
316 TfPyObjWrapper GetPyObj(_Storage const &storage) const {
317 return _getPyObj(storage);
318 }
319 std::ostream &StreamOut(_Storage const &storage,
320 std::ostream &out) const {
321 return _streamOut(storage, out);
322 }
323 bool IsArrayValued(_Storage const &storage) const {
324 return _isArrayValued(storage);
325 }
326 std::type_info const &GetElementTypeid(_Storage const &storage) const {
327 return _getElementTypeid(storage);
328 }
329 std::type_info const &GetTypeid(_Storage const &storage) const {
330 return _getTypeid(storage);
331 }
332 const Vt_ShapeData* GetShapeData(_Storage const &storage) const {
333 return _getShapeData(storage);
334 }
335 size_t GetNumElements(_Storage const &storage) const {
336 return _getNumElements(storage);
337 }
338 bool ProxyHoldsType(_Storage const &storage,
339 std::type_info const &t) const {
340 return _proxyHoldsType(storage, t);
341 }
342 TfType GetProxiedType(_Storage const &storage) const {
343 return _getProxiedType(storage);
344 }
345 std::type_info const &GetProxiedTypeid(_Storage const &storage) const {
346 return _getProxiedTypeid(storage);
347 }
348 VtValue GetProxiedAsVtValue(_Storage const &storage) const {
349 return _getProxiedAsVtValue(storage);
350 }
351 void const *GetProxiedObjPtr(_Storage const &storage) const {
352 return _getProxiedObjPtr(storage);
353 }
354
355 const std::type_info &typeInfo;
356 const std::type_info &elementTypeInfo;
357 int knownTypeIndex;
358 bool isProxy;
359 bool isArray;
360 bool isHashable;
361
362 private:
363 _CopyInitFunc _copyInit;
364 _DestroyFunc _destroy;
365 _MoveFunc _move;
366 _CanHashFunc _canHash;
367 _HashFunc _hash;
368 _EqualFunc _equal;
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;
383 };
384
385 // Type-dispatching overloads.
386
387 // Array type helpers. Non-array types have no shape data, no elements and
388 // report `void` for their element types.
389 template <class T>
390 struct _NonArrayHelper
391 {
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() {
395 return typeid(void);
396 }
397 };
398 // VtArray types report their qualities.
399 template <class Array>
400 struct _IsArrayHelper
401 {
402 static const Vt_ShapeData* GetShapeData(Array const &obj) {
403 return obj._GetShapeData();
404 }
405 static size_t GetNumElements(Array const &obj) {
406 return obj.size();
407 }
408 constexpr static std::type_info const &GetElementTypeid() {
409 return typeid(typename Array::ElementType);
410 }
411 };
412 // VtArrayEdit types are identical to non-array types except that they do
413 // report their underlying element type.
414 template <class ArrayEdit>
415 struct _IsArrayEditHelper : _NonArrayHelper<ArrayEdit>
416 {
417 constexpr static std::type_info const &GetElementTypeid() {
418 return typeid(typename ArrayEdit::ElementType);
419 }
420 };
421
422 // Select which flavor of array helper to use -- VtArray uses
423 // _IsArrayHelper, VtArrayEdit uses _IsArrayEditHelper, all other types use
424 // _NonArrayHelper.
425 template <class T>
426 using _ArrayHelper = TfConditionalType<
427 VtIsArray<T>::value, _IsArrayHelper<T>,
428 TfConditionalType<VtIsArrayEdit<T>::value,
429 _IsArrayEditHelper<T>, _NonArrayHelper<T>>
430 >;
431
432 // Function used in case T has equality comparison.
433 template <class T>
434 static inline auto
435 _TypedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
436 return a == b;
437 }
438 // Function used in case T does not have equality comparison.
439 template <class NoEqual>
440 static inline bool
441 _TypedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
442 return VtGetProxiedObject(a) == VtGetProxiedObject(b);
443 }
444
445 template <class T>
446 static inline auto
447 _ErasedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
448 return a == b;
449 }
450 // Function used in case T does not have equality comparison.
451 template <class NoEqual>
452 static inline bool
453 _ErasedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
454 return *VtGetErasedProxiedVtValue(a) == *VtGetErasedProxiedVtValue(b);
455 }
456
457 // Proxy type helper. This version handles non-proxies and typed proxies.
458 template <class T>
459 struct _TypedProxyHelper
460 {
461 using ProxiedType = typename VtGetProxiedType<T>::type;
462
463 static bool CanHash(T const &) { return VtIsHashable<ProxiedType>(); }
464 static size_t Hash(T const &obj) {
465 return VtHashValue(VtGetProxiedObject(obj));
466 }
467 static bool Equal(T const &a, T const &b) {
468 // We use the traditional int/long = 0 arg technique to disambiguate
469 // overloads, so we can invoke equality comparison on the *proxy*
470 // type if it provides one, or if it doesn't then invoke equality
471 // comparison on the *proxied* type instead.
472 return _TypedProxyEqualityImpl(a, b, 0);
473 }
474 static TfPyObjWrapper GetPyObj(T const &obj) {
475#ifdef PXR_PYTHON_SUPPORT_ENABLED
476 ProxiedType const &p = VtGetProxiedObject(obj);
477 TfPyLock lock;
478 return pxr_boost::python::api::object(p);
479#else
480 return {};
481#endif //PXR_PYTHON_SUPPORT_ENABLED
482 }
483 static std::ostream &StreamOut(T const &obj, std::ostream &out) {
484 return VtStreamOut(VtGetProxiedObject(obj), out);
485 }
486 static Vt_ShapeData const *GetShapeData(T const &obj) {
487 return _ArrayHelper<ProxiedType>::GetShapeData(
488 VtGetProxiedObject(obj));
489 }
490 static size_t GetNumElements(T const &obj) {
491 return _ArrayHelper<ProxiedType>::GetNumElements(
492 VtGetProxiedObject(obj));
493 }
494 static bool IsArrayValued(T const &) {
496 }
497 static std::type_info const &GetTypeid(T const &) {
498 return typeid(ProxiedType);
499 }
500 static std::type_info const &GetElementTypeid(T const &) {
501 return _ArrayHelper<ProxiedType>::GetElementTypeid();
502 }
503 static VtValue GetProxiedAsVtValue(T const &obj) {
504 return VtValue(VtGetProxiedObject(obj));
505 }
506 static bool HoldsType(T const &tp, std::type_info const &query) {
507 return TfSafeTypeCompare(typeid(ProxiedType), query);
508 }
509 static TfType GetTfType(T const &tp) {
510 return TfType::Find<ProxiedType>();
511 }
512 static void const *GetObjPtr(T const &tp) {
513 return static_cast<void const *>(&VtGetProxiedObject(tp));
514 }
515 };
516
517 // Proxy type helper. This version handles type-erased proxies.
518 template <class ErasedProxy>
519 struct _ErasedProxyHelper
520 {
521 static bool CanHash(ErasedProxy const &proxy) {
522 return VtGetErasedProxiedVtValue(proxy)->CanHash();
523 }
524 static size_t Hash(ErasedProxy const &proxy) {
525 return VtGetErasedProxiedVtValue(proxy)->GetHash();
526 }
527 static bool Equal(ErasedProxy const &a, ErasedProxy const &b) {
528 // We use the traditional int/long = 0 arg technique to disambiguate
529 // overloads, so we can invoke equality comparison on the *proxy*
530 // type if it provides one, or if it doesn't then invoke equality
531 // comparison on the VtValue containing the *proxied* type instead.
532 return _ErasedProxyEqualityImpl(a, b, 0);
533 }
534 static TfPyObjWrapper GetPyObj(ErasedProxy const &obj) {
535#ifdef PXR_PYTHON_SUPPORT_ENABLED
536 VtValue const *val = VtGetErasedProxiedVtValue(obj);
537 TfPyLock lock;
538 return pxr_boost::python::api::object(*val);
539#else
540 return {};
541#endif //PXR_PYTHON_SUPPORT_ENABLED
542 }
543 static std::ostream &
544 StreamOut(ErasedProxy const &obj, std::ostream &out) {
545 return VtStreamOut(obj, out);
546 }
547 static Vt_ShapeData const *GetShapeData(ErasedProxy const &obj) {
548 return VtGetErasedProxiedVtValue(obj)->_GetShapeData();
549 }
550 static size_t GetNumElements(ErasedProxy const &obj) {
551 return VtGetErasedProxiedVtValue(obj)->_GetNumElements();
552 }
553 static bool IsArrayValued(ErasedProxy const &obj) {
554 return VtGetErasedProxiedVtValue(obj)->IsArrayValued();
555 }
556 static std::type_info const &GetTypeid(ErasedProxy const &obj) {
557 return VtGetErasedProxiedVtValue(obj)->GetTypeid();
558 }
559 static std::type_info const &GetElementTypeid(ErasedProxy const &obj) {
560 return VtGetErasedProxiedVtValue(obj)->GetElementTypeid();
561 }
562 static VtValue GetProxiedAsVtValue(ErasedProxy const &ep) {
563 return *VtGetErasedProxiedVtValue(ep);
564 }
565 static bool
566 HoldsType(ErasedProxy const &ep, std::type_info const &query) {
567 return VtErasedProxyHoldsType(ep, query);
568 }
569 static TfType GetTfType(ErasedProxy const &ep) {
570 return VtGetErasedProxiedTfType(ep);
571 }
572 static void const *GetObjPtr(ErasedProxy const &ep) {
573 VtValue const *val = VtGetErasedProxiedVtValue(ep);
574 return val ? val->_GetProxiedObjPtr() : nullptr;
575 }
576 };
577
578 // _TypeInfo implementation helper. This is a CRTP base that the
579 // _LocalTypeInfo and _RemoteTypeInfo types derive. It wraps their
580 // type-specific implementations with type-generic interfaces.
581 template <class T, class Container, class Derived>
582 struct _TypeInfoImpl : public _TypeInfo
583 {
584 static const bool IsLocal = _UsesLocalStore<T>::value;
585 static const bool HasTrivialCopy = _IsTriviallyCopyable<T>::value;
586 static const bool IsProxy = VtIsValueProxy<T>::value;
587
588 using ProxyHelper = TfConditionalType<
589 VtIsErasedValueProxy<T>::value,
590 _ErasedProxyHelper<T>, _TypedProxyHelper<T>>;
591
592 using This = _TypeInfoImpl;
593
594 constexpr _TypeInfoImpl()
595 : _TypeInfo(typeid(T),
596 _ArrayHelper<T>::GetElementTypeid(),
597 Vt_KnownValueTypeDetail::GetIndex<T>(),
599 VtIsHashable<T>(),
600 IsProxy,
601 &This::_CopyInit,
602 &This::_Destroy,
603 &This::_Move,
604 &This::_CanHash,
605 &This::_Hash,
606 &This::_Equal,
607 &This::_EqualPtr,
608 &This::_MakeMutable,
609 &This::_GetPyObj,
610 &This::_StreamOut,
611
612 &This::_GetTypeid,
613
614 // Array support.
615 &This::_IsArrayValued,
616 &This::_GetElementTypeid,
617 &This::_GetShapeData,
618 &This::_GetNumElements,
619
620 // Proxy support.
621 &This::_ProxyHoldsType,
622 &This::_GetProxiedType,
623 &This::_GetProxiedTypeid,
624 &This::_GetProxiedObjPtr,
625 &This::_GetProxiedAsVtValue)
626 {}
627
629 // Typed API for client use.
630 static T const &GetObj(_Storage const &storage) {
631 return Derived::_GetObj(_Container(storage));
632 }
633
634 static T &GetMutableObj(_Storage &storage) {
635 return Derived::_GetMutableObj(_Container(storage));
636 }
637
638 static void CopyInitObj(T const &objSrc, _Storage &dst) {
639 Derived::_PlaceCopy(&_Container(dst), objSrc);
640 }
641
642 private:
643 static_assert(sizeof(Container) <= sizeof(_Storage),
644 "Container size cannot exceed storage size.");
645
647 // _TypeInfo interface function implementations.
648 static void _CopyInit(_Storage const &src, _Storage &dst) {
649 new (&_Container(dst)) Container(_Container(src));
650 }
651
652 static void _Destroy(_Storage &storage) {
653 _Container(storage).~Container();
654 }
655
656 static bool _CanHash(_Storage const &storage) {
657 return ProxyHelper::CanHash(GetObj(storage));
658 }
659
660 static size_t _Hash(_Storage const &storage) {
661 return ProxyHelper::Hash(GetObj(storage));
662 }
663
664 static bool _Equal(_Storage const &lhs, _Storage const &rhs) {
665 // Equal is only ever invoked with an object of this specific type.
666 // That is, we only ever ask a proxy to compare to a proxy; we never
667 // ask a proxy to compare to the proxied object.
668 return ProxyHelper::Equal(GetObj(lhs), GetObj(rhs));
669 }
670
671 static bool _EqualPtr(_Storage const &lhs, void const *rhs) {
672 // Equal is only ever invoked with an object of this specific type.
673 // That is, we only ever ask a proxy to compare to a proxy; we never
674 // ask a proxy to compare to the proxied object.
675 return ProxyHelper::Equal(
676 GetObj(lhs), *static_cast<T const *>(rhs));
677 }
678
679 static void _Move(_Storage &src, _Storage &dst) noexcept {
680 new (&_Container(dst)) Container(std::move(_Container(src)));
681 _Destroy(src);
682 }
683
684 static void _MakeMutable(_Storage &storage) {
685 GetMutableObj(storage);
686 }
687
688 static TfPyObjWrapper _GetPyObj(_Storage const &storage) {
689 return ProxyHelper::GetPyObj(GetObj(storage));
690 }
691
692 static std::ostream &_StreamOut(
693 _Storage const &storage, std::ostream &out) {
694 return ProxyHelper::StreamOut(GetObj(storage), out);
695 }
696
697 static std::type_info const &_GetTypeid(_Storage const &storage) {
698 return ProxyHelper::GetTypeid(GetObj(storage));
699 }
700
701 static bool _IsArrayValued(_Storage const &storage) {
702 return ProxyHelper::IsArrayValued(GetObj(storage));
703 }
704
705 static std::type_info const &
706 _GetElementTypeid(_Storage const &storage) {
707 return ProxyHelper::GetElementTypeid(GetObj(storage));
708 }
709
710 static const Vt_ShapeData* _GetShapeData(_Storage const &storage) {
711 return ProxyHelper::GetShapeData(GetObj(storage));
712 }
713
714 static size_t _GetNumElements(_Storage const &storage) {
715 return ProxyHelper::GetNumElements(GetObj(storage));
716 }
717
718 static bool
719 _ProxyHoldsType(_Storage const &storage, std::type_info const &t) {
720 return ProxyHelper::HoldsType(GetObj(storage), t);
721 }
722
723 static TfType
724 _GetProxiedType(_Storage const &storage) {
725 return ProxyHelper::GetTfType(GetObj(storage));
726 }
727
728 static std::type_info const &
729 _GetProxiedTypeid(_Storage const &storage) {
730 return ProxyHelper::GetTypeid(GetObj(storage));
731 }
732
733 static void const *
734 _GetProxiedObjPtr(_Storage const &storage) {
735 return ProxyHelper::GetObjPtr(GetObj(storage));
736 }
737
738 static VtValue
739 _GetProxiedAsVtValue(_Storage const &storage) {
740 return ProxyHelper::GetProxiedAsVtValue(GetObj(storage));
741 }
742
744 // Internal helper -- cast type-generic storage to type-specific
745 // container.
746 static Container &_Container(_Storage &storage) {
747 // XXX Will need std::launder in c++17.
748 return *reinterpret_cast<Container *>(&storage);
749 }
750 static Container const &_Container(_Storage const &storage) {
751 // XXX Will need std::launder in c++17.
752 return *reinterpret_cast<Container const *>(&storage);
753 }
754 };
755
757 // Local-storage type info implementation. The container and the object are
758 // the same -- there is no distinct container.
759 template <class T>
760 struct _LocalTypeInfo : _TypeInfoImpl<
761 T, // type
762 T, // container
763 _LocalTypeInfo<T> // CRTP
764 >
765 {
766 constexpr _LocalTypeInfo()
767 : _TypeInfoImpl<T, T, _LocalTypeInfo<T>>()
768 {}
769
770 // Get returns object directly.
771 static T &_GetMutableObj(T &obj) { return obj; }
772 static T const &_GetObj(T const &obj) { return obj; }
773 // Place placement new's object directly.
774 static void _PlaceCopy(T *dst, T const &src) { new (dst) T(src); }
775 };
776
778 // Remote-storage type info implementation. The container is an
779 // TfDelegatedCountPtr to an object holder: _Counted<T>.
780 template <class T>
781 struct _RemoteTypeInfo : _TypeInfoImpl<
782 T, // type
783 TfDelegatedCountPtr<_Counted<T>>, // container
784 _RemoteTypeInfo<T> // CRTP
785 >
786 {
787 constexpr _RemoteTypeInfo()
788 : _TypeInfoImpl<
789 T, TfDelegatedCountPtr<_Counted<T>>, _RemoteTypeInfo<T>>()
790 {}
791
793 // Get returns object stored in the pointed-to _Counted<T>.
794 static T &_GetMutableObj(Ptr &ptr) {
795 if (!ptr->IsUnique()) {
796 ptr = TfMakeDelegatedCountPtr<_Counted<T>>(ptr->Get());
797 }
798 return ptr->GetMutable();
799 }
800 static T const &_GetObj(Ptr const &ptr) { return ptr->Get(); }
801 // PlaceCopy() allocates a new _Counted<T> with a copy of the object.
802 static void _PlaceCopy(Ptr *dst, T const &src) {
803 new (dst) Ptr(TfDelegatedCountIncrementTag, new _Counted<T>(src));
804 }
805 };
806
807 // Metafunction that returns the specific _TypeInfo subclass for T.
808 template <class T>
809 using _TypeInfoFor =
810 TfConditionalType<_UsesLocalStore<T>::value,
811 _LocalTypeInfo<T>, _RemoteTypeInfo<T>>;
812
813 // A helper that moves a held value to temporary storage, but keeps it alive
814 // until the _HoldAside object is destroyed. This is used when assigning
815 // over a VtValue that might own the object being assigned. For instance,
816 // if I have a VtValue holding a map<string, VtValue>, and I reassign this
817 // VtValue with one of the elements from the map, we must ensure that the
818 // map isn't destroyed until after the assignment has taken place.
819 friend struct _HoldAside;
820 struct _HoldAside {
821 explicit _HoldAside(VtValue *val)
822 : info((val->IsEmpty() || val->_IsLocalAndTriviallyCopyable())
823 ? static_cast<_TypeInfo const *>(NULL) : val->_info.Get()) {
824 if (info)
825 info->Move(val->_storage, storage);
826 }
827 ~_HoldAside() {
828 if (info)
829 info->Destroy(storage);
830 }
831 _Storage storage;
832 _TypeInfo const *info;
833 };
834
835 template <class T>
836 struct _Init {
837 using StoredType = typename Vt_ValueGetStored<T>::Type;
838 using TypeInfo = _TypeInfoFor<StoredType>;
839
840 static_assert(
842
843 static TfPointerAndBits<const _TypeInfo> _GetTypeInfo() {
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);
849 return TfPointerAndBits<const _TypeInfo>(&ti, flags);
850 }
851
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);
856 }
857 else {
858 TypeInfo::CopyInitObj(StoredType {obj}, val->_storage);
859 }
860 }
861 };
862
863public:
864
867
869 VtValue(VtValue const &other) {
870 _Copy(other, *this);
871 }
872
874 VtValue(VtValue &&other) noexcept {
875 _Move(other, *this);
876 }
877
883 template <class T>
884 explicit VtValue(T const &obj) {
885 _Init<T>::Init(this, obj);
886 }
887
907 template <class T>
908 static VtValue Take(T &obj) {
909 VtValue ret;
910 ret.Swap(obj);
911 return ret;
912 }
913
915 ~VtValue() { _Clear(); }
916
918 VtValue &operator=(VtValue const &other) {
919 if (ARCH_LIKELY(this != &other))
920 _Copy(other, *this);
921 return *this;
922 }
923
925 VtValue &operator=(VtValue &&other) noexcept {
926 if (ARCH_LIKELY(this != &other))
927 _Move(other, *this);
928 return *this;
929 }
930
932 template <class T>
933 VtValue &
934 operator=(T const &obj) {
935 if constexpr (_TypeInfoFor<T>::IsLocal &&
936 _TypeInfoFor<T>::HasTrivialCopy) {
937 _Clear();
938 _Init<T>::Init(this, obj);
939 return *this;
940 }
941 else {
942 _HoldAside tmp(this);
943 _Init<T>::Init(this, obj);
944 return *this;
945 }
946 }
947
949 VtValue &Swap(VtValue &rhs) noexcept {
950 // Do nothing if both empty. Otherwise general swap.
951 if (!IsEmpty() || !rhs.IsEmpty()) {
952 VtValue tmp;
953 _Move(*this, tmp);
954 _Move(rhs, *this);
955 _Move(tmp, rhs);
956 }
957 return *this;
958 }
959
961 friend void swap(VtValue &lhs, VtValue &rhs) { lhs.Swap(rhs); }
962
967 template <class T>
968 void
969 Swap(T &rhs) {
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");
972 if (!IsHolding<T>())
973 *this = T();
974 UncheckedSwap(rhs);
975 }
976
981 template <class T>
982 void
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");
986 using std::swap;
987 swap(_GetMutable<T>(), rhs);
988 }
989
991 void UncheckedSwap(VtValue &rhs) { Swap(rhs); }
992
996 template <class T>
997 T Remove() {
998 T result;
999 Swap(result);
1000 _Clear();
1001 return result;
1002 }
1003
1007 template <class T>
1009 T result;
1010 UncheckedSwap(result);
1011 _Clear();
1012 return result;
1013 }
1014
1018 template <class T, class Fn>
1019 bool
1020 Mutate(Fn &&mutateFn) {
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>()) {
1024 return false;
1025 }
1026 UncheckedMutate<T>(std::forward<Fn>(mutateFn));
1027 return true;
1028 }
1029
1033 template <class T, class Fn>
1034 void
1035 UncheckedMutate(Fn &&mutateFn) {
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");
1038 // We move to a temporary, mutate the temporary, then move back. This
1039 // prevents callers from escaping a mutable reference to the held object
1040 // via a side-effect of mutateFn.
1041 T &stored =_GetMutable<T>();
1042 T tmp = std::move(stored);
1043 std::forward<Fn>(mutateFn)(tmp);
1044 stored = std::move(tmp);
1045 }
1046
1049 template <class T>
1050 bool IsHolding() const {
1051 return _info.GetLiteral() && _TypeIs<T>();
1052 }
1053
1055 VT_API bool IsArrayValued() const;
1056
1058 VT_API bool IsArrayEditValued() const;
1059
1062 size_t GetArraySize() const { return _GetNumElements(); }
1063
1065 VT_API std::type_info const &GetTypeid() const;
1066
1070 VT_API std::type_info const &GetElementTypeid() const;
1071
1073 VT_API TfType GetType() const;
1074
1076 VT_API std::string GetTypeName() const;
1077
1083 if (ARCH_UNLIKELY(_IsProxy())) {
1084 return _info->GetProxiedAsVtValue(
1085 _storage).GetKnownValueTypeIndex();
1086 }
1087 return _info.GetLiteral() ? _info->knownTypeIndex : -1;
1088 }
1089
1093 template <class T>
1094 T const &UncheckedGet() const & { return _Get<T>(); }
1095
1099 template <class T>
1100 T UncheckedGet() && { return UncheckedRemove<T>(); }
1101
1110 template <class T>
1111 T const &Get() const & {
1112 typedef Vt_DefaultValueFactory<T> Factory;
1113
1114 // In the unlikely case that the types don't match, we obtain a default
1115 // value to return and issue an error via _FailGet.
1116 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1117 return *(static_cast<T const *>(
1118 _FailGet(Factory::Invoke, typeid(T))));
1119 }
1120
1121 return _Get<T>();
1122 }
1123
1127 template <class T>
1128 T Get() && {
1129 typedef Vt_DefaultValueFactory<T> Factory;
1130
1131 // In the unlikely case that the types don't match, we obtain a default
1132 // value to return and issue an error via _FailGet.
1133 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1134 return *(static_cast<T const *>(
1135 _FailGet(Factory::Invoke, typeid(T))));
1136 }
1137
1138 return UncheckedRemove<T>();
1139 }
1140
1145 template <class T>
1146 T GetWithDefault(T const &def = T()) const {
1147 return IsHolding<T>() ? UncheckedGet<T>() : def;
1148 }
1149
1151 template <typename From, typename To>
1152 static void RegisterCast(VtValue (*castFn)(VtValue const &)) {
1153 _RegisterCast(typeid(From), typeid(To), castFn);
1154 }
1155
1157 // holding To.
1158 template <typename From, typename To>
1159 static void RegisterSimpleCast() {
1160 _RegisterCast(typeid(From), typeid(To), _SimpleCast<From, To>);
1161 }
1162
1165 template <typename From, typename To>
1167 RegisterSimpleCast<From, To>();
1168 RegisterSimpleCast<To, From>();
1169 }
1170
1178 template <typename T>
1179 static VtValue Cast(VtValue const &val) {
1180 VtValue ret = val;
1181 ret.Cast<T>();
1182 return ret;
1183 }
1184
1192 VT_API static VtValue
1193 CastToTypeOf(VtValue const &val, VtValue const &other);
1194
1202 VT_API static VtValue
1203 CastToTypeid(VtValue const &val, std::type_info const &type);
1204
1208 static bool CanCastFromTypeidToTypeid(std::type_info const &from,
1209 std::type_info const &to) {
1210 return _CanCast(from, to);
1211 }
1212
1220 template <typename T>
1222 if (IsHolding<T>())
1223 return *this;
1224 return *this = _PerformCast(typeid(T), *this);
1225 }
1226
1235 return CastToTypeid(other.GetTypeid());
1236 }
1237
1245 VtValue &CastToTypeid(std::type_info const &type) {
1246 if (!TfSafeTypeCompare(GetTypeid(), type)) {
1247 *this = _PerformCast(type, *this);
1248 }
1249 return *this;
1250 }
1251
1255 template <typename T>
1256 bool CanCast() const {
1257 return _CanCast(GetTypeid(), typeid(T));
1258 }
1259
1263 bool CanCastToTypeOf(VtValue const &other) const {
1264 return _CanCast(GetTypeid(), other.GetTypeid());
1265 }
1266
1270 bool CanCastToTypeid(std::type_info const &type) const {
1271 return _CanCast(GetTypeid(), type);
1272 }
1273
1275 bool IsEmpty() const { return _info.GetLiteral() == 0; }
1276
1278 VT_API bool CanHash() const;
1279
1281 VT_API size_t GetHash() const;
1282
1283 friend inline size_t hash_value(VtValue const &val) {
1284 return val.GetHash();
1285 }
1286
1288 template <typename T>
1289 friend bool operator == (VtValue const &lhs, T const &rhs) {
1290 typedef typename Vt_ValueGetStored<T>::Type Stored;
1291 return lhs.IsHolding<Stored>() && lhs.UncheckedGet<Stored>() == rhs;
1292 }
1293 template <typename T>
1294 friend bool operator == (T const &lhs, VtValue const &rhs) {
1295 return rhs == lhs;
1296 }
1297
1299 template <typename T>
1300 friend bool operator != (VtValue const &lhs, T const &rhs) {
1301 return !(lhs == rhs);
1302 }
1303 template <typename T>
1304 friend bool operator != (T const &lhs, VtValue const &rhs) {
1305 return !(lhs == rhs);
1306 }
1307
1309 bool operator == (const VtValue &rhs) const {
1310 bool empty = IsEmpty(), rhsEmpty = rhs.IsEmpty();
1311 if (empty || rhsEmpty) {
1312 // Either one or both empty -- only equal if both empty.
1313 return empty == rhsEmpty;
1314 }
1315 if (_info.GetLiteral() == rhs._info.GetLiteral()) {
1316 // Holding identical types -- compare directly.
1317 return _info.Get()->Equal(_storage, rhs._storage);
1318 }
1319 return _EqualityImpl(rhs);
1320 }
1321 bool operator != (const VtValue &rhs) const { return !(*this == rhs); }
1322
1324 VT_API friend std::ostream &
1325 operator << (std::ostream &out, const VtValue &self);
1326
1327private:
1328 VT_API const Vt_ShapeData* _GetShapeData() const;
1329 VT_API size_t _GetNumElements() const;
1330 friend struct Vt_ValueShapeDataAccess;
1331
1332 static inline void _Copy(VtValue const &src, VtValue &dst) {
1333 if (src.IsEmpty()) {
1334 dst._Clear();
1335 return;
1336 }
1337
1338 _HoldAside tmp(&dst);
1339 dst._info = src._info;
1340 if (src._IsLocalAndTriviallyCopyable()) {
1341 dst._storage = src._storage;
1342 } else {
1343 dst._info->CopyInit(src._storage, dst._storage);
1344 }
1345 }
1346
1347 static inline void _Move(VtValue &src, VtValue &dst) noexcept {
1348 if (src.IsEmpty()) {
1349 dst._Clear();
1350 return;
1351 }
1352
1353 _HoldAside tmp(&dst);
1354 dst._info = src._info;
1355 if (src._IsLocalAndTriviallyCopyable()) {
1356 dst._storage = src._storage;
1357 } else {
1358 dst._info->Move(src._storage, dst._storage);
1359 }
1360
1361 src._info.Set(nullptr, 0);
1362 }
1363
1364 template <class T>
1365 inline bool
1366 _TypeIs() const {
1367 if constexpr (VtIsKnownValueType_Workaround<T>::value) {
1368 return _info->knownTypeIndex == VtGetKnownValueTypeIndex<T>() ||
1369 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(typeid(T)));
1370 }
1371 else {
1372 std::type_info const &t = typeid(T);
1373 return TfSafeTypeCompare(_info->typeInfo, t) ||
1374 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(t));
1375 }
1376 }
1377
1378 VT_API bool _TypeIsImpl(std::type_info const &queriedType) const;
1379
1380 VT_API bool _EqualityImpl(VtValue const &rhs) const;
1381
1382 template <class T>
1383 T &
1384 _GetMutable() {
1385 using TypeInfo = _TypeInfoFor<T>;
1386 if constexpr (!VtIsValueProxy<T>::value) {
1387 // The request is not for a proxy type, so if we are holding a
1388 // proxy, collapse it out to the proxied value first.
1389 if (ARCH_UNLIKELY(_IsProxy())) {
1390 *this = _info->GetProxiedAsVtValue(_storage);
1391 }
1392 }
1393 return TypeInfo::GetMutableObj(_storage);
1394 }
1395
1396 template <class T>
1397 T const &
1398 _Get() const {
1399 using TypeInfo = _TypeInfoFor<T>;
1400 if constexpr (!VtIsValueProxy<T>::value) {
1401 // The request is not for a proxy type, so if we are holding a
1402 // proxy, fetch the underlying proxied object pointer.
1403 if (ARCH_UNLIKELY(_IsProxy())) {
1404 return *static_cast<T const *>(_GetProxiedObjPtr());
1405 }
1406 }
1407 return TypeInfo::GetObj(_storage);
1408 }
1409
1410 void const *_GetProxiedObjPtr() const {
1411 return _info->GetProxiedObjPtr(_storage);
1412 }
1413
1414 // Helper invoked in case Get fails. Reports an error and returns a default
1415 // value for \a queryType.
1416 VT_API void const *
1417 _FailGet(Vt_DefaultValueHolder (*factory)(),
1418 std::type_info const &queryType) const;
1419
1420 inline void _Clear() {
1421 // optimize for local types not to deref _info.
1422ARCH_PRAGMA_PUSH
1423// XXX: http://bug/DEV-16695
1424ARCH_PRAGMA_MAYBE_UNINITIALIZED
1425 if (_info.GetLiteral() && !_IsLocalAndTriviallyCopyable())
1426 _info.Get()->Destroy(_storage);
1427ARCH_PRAGMA_POP
1428 _info.Set(nullptr, 0);
1429 }
1430
1431 inline bool _IsLocalAndTriviallyCopyable() const {
1432 unsigned int bits = _info.BitsAs<unsigned int>();
1433 return (bits & (_LocalFlag | _TrivialCopyFlag)) ==
1434 (_LocalFlag | _TrivialCopyFlag);
1435 }
1436
1437 inline bool _IsProxy() const {
1438 return _info.BitsAs<unsigned int>() & _ProxyFlag;
1439 }
1440
1441 VT_API static void _RegisterCast(std::type_info const &from,
1442 std::type_info const &to,
1443 VtValue (*castFn)(VtValue const &));
1444
1445 // Cast \p value to the type \p to. Caller must ensure that val's type is
1446 // not already \p to.
1447 VT_API static VtValue
1448 _PerformCast(std::type_info const &to, VtValue const &val);
1449
1450 // Return true if \p from == \p to or if there is a registered cast to
1451 // convert VtValues holding \p from to \p to.
1452 VT_API static bool
1453 _CanCast(std::type_info const &from, std::type_info const &to);
1454
1455 // helper template function for simple casts from From to To.
1456 template <typename From, typename To>
1457 static VtValue _SimpleCast(VtValue const &val) {
1458 return VtValue(To(val.UncheckedGet<From>()));
1459 }
1460
1461 // This grants friend access to a function in the wrapper file for this
1462 // class. This lets the wrapper reach down into a value to get a
1463 // pxr_boost::python wrapped object corresponding to the held type. This
1464 // facility is necessary to get the python API we want.
1465 friend TfPyObjWrapper
1466 Vt_GetPythonObjectFromHeldValue(VtValue const &self);
1467
1468 VT_API TfPyObjWrapper _GetPythonObject() const;
1469
1470 _Storage _storage;
1472};
1473
1474#ifndef doxygen
1475
1476struct Vt_ValueShapeDataAccess {
1477 static const Vt_ShapeData* _GetShapeData(const VtValue& value) {
1478 return value._GetShapeData();
1479 }
1480
1481 static size_t _GetNumElements(const VtValue& value) {
1482 return value._GetNumElements();
1483 }
1484};
1485
1489template <class T>
1490struct Vt_DefaultValueFactory {
1491 static Vt_DefaultValueHolder Invoke();
1492};
1493
1494template <class T>
1495inline Vt_DefaultValueHolder
1496Vt_DefaultValueFactory<T>::Invoke() {
1497 return Vt_DefaultValueHolder::Create<T>();
1498}
1499
1500// For performance reasons, the default constructors for vectors,
1501// matrices, and quaternions do *not* initialize the data of the
1502// object. This greatly improves the performance of creating large
1503// arrays of objects. However, for consistency and to avoid
1504// errors complaining about uninitialized values, we use VtZero
1505// to construct zeroed out vectors, matrices, and quaternions by
1506// explicitly instantiating the factory for these types.
1507//
1508#define _VT_DECLARE_ZERO_VALUE_FACTORY(unused, elem) \
1509template <> \
1510VT_API Vt_DefaultValueHolder Vt_DefaultValueFactory<VT_TYPE(elem)>::Invoke();
1511
1512TF_PP_SEQ_FOR_EACH(_VT_DECLARE_ZERO_VALUE_FACTORY, ~,
1513 VT_VEC_VALUE_TYPES
1514 VT_MATRIX_VALUE_TYPES
1515 VT_QUATERNION_VALUE_TYPES
1516 VT_DUALQUATERNION_VALUE_TYPES)
1517
1518#undef _VT_DECLARE_ZERO_VALUE_FACTORY
1519
1520//
1521// The Get()/IsHolding routines needs to be special-cased to handle getting a
1522// VtValue *as* a VtValue.
1523//
1524
1525template <>
1526inline const VtValue&
1527VtValue::Get<VtValue>() const & {
1528 return *this;
1529}
1530
1531template <>
1532inline VtValue
1533VtValue::Get<VtValue>() && {
1534 return std::move(*this);
1535}
1536
1537template <>
1538inline const VtValue&
1539VtValue::UncheckedGet<VtValue>() const & {
1540 return *this;
1541}
1542
1543template <>
1544inline VtValue
1545VtValue::UncheckedGet<VtValue>() && {
1546 return std::move(*this);
1547}
1548
1549template <>
1550inline bool
1551VtValue::IsHolding<VtValue>() const {
1552 return true;
1553}
1554
1555// Specialize VtValue::IsHolding<void>() to always return false.
1556template <>
1557inline bool
1558VtValue::IsHolding<void>() const {
1559 return false;
1560}
1561
1562
1563
1564#endif // !doxygen
1565
1566PXR_NAMESPACE_CLOSE_SCOPE
1567
1568#endif // PXR_BASE_VT_VALUE_H
Defines all the types "TYPED" for which Vt creates a VtTYPEDArray typedef.
A simple type-erased container that provides only destruction, moves and immutable,...
Definition: anyUniquePtr.h:27
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.
Definition: pyLock.h:105
Boost Python object wrapper.
Definition: pyObjWrapper.h:79
TfType represents a dynamic runtime type.
Definition: type.h:48
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:152
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.
Definition: value.h:1270
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition: value.h:1008
friend bool operator==(VtValue const &lhs, T const &rhs)
Tests for equality.
Definition: value.h:1289
int GetKnownValueTypeIndex() const
Return VtKnownValueTypeIndex<T> for the held type T.
Definition: value.h:1082
T UncheckedGet() &&
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: value.h:1100
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.
Definition: value.h:1035
T Remove()
Make this value empty and return the held T instance.
Definition: value.h:997
static VtValue Take(T &obj)
Create a new VtValue, taking its contents from obj.
Definition: value.h:908
static void RegisterSimpleCast()
Register a simple cast from VtValue holding From to VtValue.
Definition: value.h:1159
VtValue & Cast()
Return this holding value type cast to T.
Definition: value.h:1221
VtValue & CastToTypeOf(VtValue const &other)
Return this holding value type cast to same type that other is holding.
Definition: value.h:1234
static void RegisterSimpleBidirectionalCast()
Register a two-way cast from VtValue holding From to VtValue holding To.
Definition: value.h:1166
bool Mutate(Fn &&mutateFn)
If this value holds an object of type T, invoke mutateFn, passing it a non-const reference to the hel...
Definition: value.h:1020
VtValue(VtValue const &other)
Copy construct with other.
Definition: value.h:869
static void RegisterCast(VtValue(*castFn)(VtValue const &))
Register a cast from VtValue holding From to VtValue holding To.
Definition: value.h:1152
size_t GetArraySize() const
Return the number of elements in the held value if IsArrayValued(), return 0 otherwise.
Definition: value.h:1062
T Get() &&
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: value.h:1128
bool CanCastToTypeOf(VtValue const &other) const
Return if this can be cast to type.
Definition: value.h:1263
T GetWithDefault(T const &def=T()) const
Return a copy of the held object if the held object is of type T.
Definition: value.h:1146
void UncheckedSwap(T &rhs)
Swap the held value with rhs.
Definition: value.h:983
void UncheckedSwap(VtValue &rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: value.h:991
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.
Definition: value.h:1275
VtValue & operator=(VtValue &&other) noexcept
Move assignment from another VtValue.
Definition: value.h:925
VtValue & CastToTypeid(std::type_info const &type)
Return this holding value type cast to type.
Definition: value.h:1245
VT_API TfType GetType() const
Returns the TfType of the type held by this value.
~VtValue()
Destructor.
Definition: value.h:915
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.
Definition: value.h:934
VtValue(T const &obj)
Construct a VtValue holding a copy of obj.
Definition: value.h:884
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.
Definition: value.h:949
friend void swap(VtValue &lhs, VtValue &rhs)
Overloaded swap() for generic code/stl/etc.
Definition: value.h:961
static VtValue Cast(VtValue const &val)
Return a VtValue holding val cast to hold T.
Definition: value.h:1179
bool CanCast() const
Return if this can be cast to T.
Definition: value.h:1256
T const & Get() const &
Returns a const reference to the held object if the held object is of type T.
Definition: value.h:1111
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.
Definition: value.h:866
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.
Definition: value.h:1300
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.
Definition: value.h:1208
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
Definition: value.h:1050
VtValue(VtValue &&other) noexcept
Move construct with other.
Definition: value.h:874
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.
Definition: value.h:1094
VtValue & operator=(VtValue const &other)
Copy assignment from another VtValue.
Definition: value.h:918
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.
Definition: value.h:969
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.
Compiler hints.
STL namespace.
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.
Definition: traits.h:22
A file containing basic constants and definitions.