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#include "pxr/base/vt/valueCommon.h"
37
38#include <iosfwd>
39#include <typeinfo>
40#include <type_traits>
41
42PXR_NAMESPACE_OPEN_SCOPE
43
44class VtValue;
45class VtValueRef;
46
47// Overload VtStreamOut for vector<VtValue>. Produces output like [value1,
48// value2, ... valueN].
49VT_API std::ostream &
50VtStreamOut(std::vector<VtValue> const &val, std::ostream &);
51
90{
91 static const unsigned int _LocalFlag = 1 << 0;
92 static const unsigned int _TrivialCopyFlag = 1 << 1;
93 static const unsigned int _ProxyFlag = 1 << 2;
94 static const unsigned int _AllFlags =
95 _LocalFlag | _TrivialCopyFlag | _ProxyFlag;
96
97 template <class T>
98 struct _Counted {
99 explicit _Counted(T const &obj) : _obj(obj) {
100 _refCount = 0;
101 }
102 bool IsUnique() const { return _refCount == 1; }
103 T const &Get() const { return _obj; }
104 T &GetMutable() { return _obj; }
105
106 private:
107 T _obj;
108 mutable std::atomic<int> _refCount;
109
110 friend inline void TfDelegatedCountIncrement(_Counted const *d) {
111 d->_refCount.fetch_add(1, std::memory_order_relaxed);
112 }
113 friend inline void TfDelegatedCountDecrement(_Counted const *d) noexcept {
114 if (d->_refCount.fetch_sub(1, std::memory_order_release) == 1) {
115 std::atomic_thread_fence(std::memory_order_acquire);
116 delete d;
117 }
118 }
119 };
120
121 // Hold objects up to 1 word large locally. This makes the total structure
122 // 16 bytes when compiled 64 bit (1 word type-info pointer, 1 word storage
123 // space).
124 static const size_t _MaxLocalSize = sizeof(void*);
125 typedef std::aligned_storage<
126 /* size */_MaxLocalSize, /* alignment */_MaxLocalSize>::type _Storage;
127
128 template <class T>
129 using _IsTriviallyCopyable = std::integral_constant<bool,
130 std::is_trivially_default_constructible_v<T> &&
131 std::is_trivially_copyable_v<T> &&
132 std::is_trivially_copy_assignable_v<T> &&
133 std::is_trivially_destructible_v<T>>;
134
135 // Metafunction that returns true if T should be stored locally, false if it
136 // should be stored remotely.
137 template <class T>
138 using _UsesLocalStore = std::integral_constant<bool,
139 (sizeof(T) <= sizeof(_Storage)) &&
140 VtValueTypeHasCheapCopy<T>::value &&
141 std::is_nothrow_move_constructible<T>::value &&
142 std::is_nothrow_move_assignable<T>::value>;
143
144 // Type information base class.
145 // We force alignment here in order to ensure that TfPointerAndBits has
146 // enough room to store all TypeInfo related flags.
147 struct alignas(8) _TypeInfo {
148 private:
149 using _CopyInitFunc = void (*)(_Storage const &, _Storage &);
150 using _DestroyFunc = void (*)(_Storage &);
151 using _MoveFunc = void (*)(_Storage &, _Storage &);
152 using _CanHashFunc = bool (*)(_Storage const &);
153 using _HashFunc = size_t (*)(_Storage const &);
154 using _EqualFunc = bool (*)(_Storage const &, _Storage const &);
155 using _EqualPtrFunc = bool (*)(_Storage const &, void const *);
156 using _MakeMutableFunc = void (*)(_Storage &);
157 using _GetPyObjFunc = TfPyObjWrapper (*)(_Storage const &);
158 using _GetValueRefFunc = VtValueRef (*)(_Storage const &, bool);
159 using _StreamOutFunc =
160 std::ostream & (*)(_Storage const &, std::ostream &);
161 using _GetTypeidFunc = std::type_info const & (*)(_Storage const &);
162 using _IsArrayValuedFunc = bool (*)(_Storage const &);
163 using _GetElementTypeidFunc =
164 std::type_info const & (*)(_Storage const &);
165 using _GetShapeDataFunc = const Vt_ShapeData* (*)(_Storage const &);
166 using _GetNumElementsFunc = size_t (*)(_Storage const &);
167 using _ProxyHoldsTypeFunc = bool (*)(_Storage const &, std::type_info const &);
168 using _GetProxiedTypeFunc = TfType (*)(_Storage const &);
169 using _GetProxiedTypeidFunc =
170 std::type_info const & (*)(_Storage const &);
171 using _GetProxiedObjPtrFunc = void const *(*)(_Storage const &);
172 using _GetProxiedAsVtValueFunc = VtValue (*)(_Storage const &);
173
174 protected:
175 constexpr _TypeInfo(const std::type_info &ti,
176 const std::type_info &elementTi,
177 int knownTypeIndex,
178 bool isArray,
179 bool isHashable,
180 bool isProxy,
181 bool canComposeOver,
182 bool canTransform,
183 _CopyInitFunc copyInit,
184 _DestroyFunc destroy,
185 _MoveFunc move,
186 _CanHashFunc canHash,
187 _HashFunc hash,
188 _EqualFunc equal,
189 _EqualPtrFunc equalPtr,
190 _MakeMutableFunc makeMutable,
191 _GetPyObjFunc getPyObj,
192 _GetValueRefFunc getValueRef,
193 _StreamOutFunc streamOut,
194 _GetTypeidFunc getTypeid,
195 _IsArrayValuedFunc isArrayValued,
196 _GetElementTypeidFunc getElementTypeid,
197 _GetShapeDataFunc getShapeData,
198 _GetNumElementsFunc getNumElements,
199 _ProxyHoldsTypeFunc proxyHoldsType,
200 _GetProxiedTypeFunc getProxiedType,
201 _GetProxiedTypeidFunc getProxiedTypeid,
202 _GetProxiedObjPtrFunc getProxiedObjPtr,
203 _GetProxiedAsVtValueFunc getProxiedAsVtValue)
204 : typeInfo(ti)
205 , elementTypeInfo(elementTi)
206 , knownTypeIndex(knownTypeIndex)
207 , isProxy(isProxy)
208 , isArray(isArray)
209 , isHashable(isHashable)
210 , canComposeOver(canComposeOver)
211 , canTransform(canTransform)
212 // Function table
213 , _copyInit(copyInit)
214 , _destroy(destroy)
215 , _move(move)
216 , _canHash(canHash)
217 , _hash(hash)
218 , _equal(equal)
219 , _equalPtr(equalPtr)
220 , _makeMutable(makeMutable)
221 , _getPyObj(getPyObj)
222 , _getValueRef(getValueRef)
223 , _streamOut(streamOut)
224 , _getTypeid(getTypeid)
225 , _isArrayValued(isArrayValued)
226 , _getElementTypeid(getElementTypeid)
227 , _getShapeData(getShapeData)
228 , _getNumElements(getNumElements)
229 , _proxyHoldsType(proxyHoldsType)
230 , _getProxiedType(getProxiedType)
231 , _getProxiedTypeid(getProxiedTypeid)
232 , _getProxiedObjPtr(getProxiedObjPtr)
233 , _getProxiedAsVtValue(getProxiedAsVtValue)
234 {}
235
236 public:
237 void CopyInit(_Storage const &src, _Storage &dst) const {
238 _copyInit(src, dst);
239 }
240 void Destroy(_Storage &storage) const {
241 _destroy(storage);
242 }
243 void Move(_Storage &src, _Storage &dst) const noexcept {
244 _move(src, dst);
245 }
246 bool CanHash(_Storage const &storage) const {
247 return _canHash(storage);
248 }
249 size_t Hash(_Storage const &storage) const {
250 return _hash(storage);
251 }
252 bool Equal(_Storage const &lhs, _Storage const &rhs) const {
253 return _equal(lhs, rhs);
254 }
255 bool EqualPtr(_Storage const &lhs, void const *rhs) const {
256 return _equalPtr(lhs, rhs);
257 }
258 void MakeMutable(_Storage &storage) const {
259 _makeMutable(storage);
260 }
261 TfPyObjWrapper GetPyObj(_Storage const &storage) const {
262 return _getPyObj(storage);
263 }
264 inline VtValueRef GetValueRef(_Storage const &storage,
265 bool rvalue) const;
266 std::ostream &StreamOut(_Storage const &storage,
267 std::ostream &out) const {
268 return _streamOut(storage, out);
269 }
270 bool IsArrayValued(_Storage const &storage) const {
271 return _isArrayValued(storage);
272 }
273 std::type_info const &GetElementTypeid(_Storage const &storage) const {
274 return _getElementTypeid(storage);
275 }
276 std::type_info const &GetTypeid(_Storage const &storage) const {
277 return _getTypeid(storage);
278 }
279 const Vt_ShapeData* GetShapeData(_Storage const &storage) const {
280 return _getShapeData(storage);
281 }
282 size_t GetNumElements(_Storage const &storage) const {
283 return _getNumElements(storage);
284 }
285 bool ProxyHoldsType(_Storage const &storage,
286 std::type_info const &t) const {
287 return _proxyHoldsType(storage, t);
288 }
289 TfType GetProxiedType(_Storage const &storage) const {
290 return _getProxiedType(storage);
291 }
292 std::type_info const &GetProxiedTypeid(_Storage const &storage) const {
293 return _getProxiedTypeid(storage);
294 }
295 VtValue GetProxiedAsVtValue(_Storage const &storage) const {
296 return _getProxiedAsVtValue(storage);
297 }
298 void const *GetProxiedObjPtr(_Storage const &storage) const {
299 return _getProxiedObjPtr(storage);
300 }
301
302 const std::type_info &typeInfo;
303 const std::type_info &elementTypeInfo;
304 int knownTypeIndex;
305 bool isProxy;
306 bool isArray;
307 bool isHashable;
308 bool canComposeOver;
309 bool canTransform;
310
311 private:
312 _CopyInitFunc _copyInit;
313 _DestroyFunc _destroy;
314 _MoveFunc _move;
315 _CanHashFunc _canHash;
316 _HashFunc _hash;
317 _EqualFunc _equal;
318 _EqualPtrFunc _equalPtr;
319 _MakeMutableFunc _makeMutable;
320 _GetPyObjFunc _getPyObj;
321 _GetValueRefFunc _getValueRef;
322 _StreamOutFunc _streamOut;
323 _GetTypeidFunc _getTypeid;
324 _IsArrayValuedFunc _isArrayValued;
325 _GetElementTypeidFunc _getElementTypeid;
326 _GetShapeDataFunc _getShapeData;
327 _GetNumElementsFunc _getNumElements;
328 _ProxyHoldsTypeFunc _proxyHoldsType;
329 _GetProxiedTypeFunc _getProxiedType;
330 _GetProxiedTypeidFunc _getProxiedTypeid;
331 _GetProxiedObjPtrFunc _getProxiedObjPtr;
332 _GetProxiedAsVtValueFunc _getProxiedAsVtValue;
333 };
334
335 // Type-dispatching overloads.
336
337 // Array type helpers. Non-array types have no shape data, no elements and
338 // report `void` for their element types.
339 template <class T>
340 struct _NonArrayHelper
341 {
342 static const Vt_ShapeData* GetShapeData(T const &) { return NULL; }
343 static size_t GetNumElements(T const &) { return 0; }
344 constexpr static std::type_info const &GetElementTypeid() {
345 return typeid(void);
346 }
347 };
348 // VtArray types report their qualities.
349 template <class Array>
350 struct _IsArrayHelper
351 {
352 static const Vt_ShapeData* GetShapeData(Array const &obj) {
353 return obj._GetShapeData();
354 }
355 static size_t GetNumElements(Array const &obj) {
356 return obj.size();
357 }
358 constexpr static std::type_info const &GetElementTypeid() {
359 return typeid(typename Array::ElementType);
360 }
361 };
362 // VtArrayEdit types are identical to non-array types except that they do
363 // report their underlying element type.
364 template <class ArrayEdit>
365 struct _IsArrayEditHelper : _NonArrayHelper<ArrayEdit>
366 {
367 constexpr static std::type_info const &GetElementTypeid() {
368 return typeid(typename ArrayEdit::ElementType);
369 }
370 };
371
372 // Select which flavor of array helper to use -- VtArray uses
373 // _IsArrayHelper, VtArrayEdit uses _IsArrayEditHelper, all other types use
374 // _NonArrayHelper.
375 template <class T>
376 using _ArrayHelper = TfConditionalType<
377 VtIsArray<T>::value, _IsArrayHelper<T>,
378 TfConditionalType<VtIsArrayEdit<T>::value,
379 _IsArrayEditHelper<T>, _NonArrayHelper<T>>
380 >;
381
382 // Function used in case T has equality comparison.
383 template <class T>
384 static inline auto
385 _TypedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
386 return a == b;
387 }
388 // Function used in case T does not have equality comparison.
389 template <class NoEqual>
390 static inline bool
391 _TypedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
392 return VtGetProxiedObject(a) == VtGetProxiedObject(b);
393 }
394
395 template <class T>
396 static inline auto
397 _ErasedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
398 return a == b;
399 }
400 // Function used in case T does not have equality comparison.
401 template <class NoEqual>
402 static inline bool
403 _ErasedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
404 return *VtGetErasedProxiedVtValue(a) == *VtGetErasedProxiedVtValue(b);
405 }
406
407 // Proxy type helper. This version handles non-proxies and typed proxies.
408 template <class T>
409 struct _TypedProxyHelper
410 {
411 using ProxiedType = typename VtGetProxiedType<T>::type;
412
413 static bool CanHash(T const &) { return VtIsHashable<ProxiedType>(); }
414 static size_t Hash(T const &obj) {
415 return VtHashValue(VtGetProxiedObject(obj));
416 }
417 static bool Equal(T const &a, T const &b) {
418 // We use the traditional int/long = 0 arg technique to disambiguate
419 // overloads, so we can invoke equality comparison on the *proxy*
420 // type if it provides one, or if it doesn't then invoke equality
421 // comparison on the *proxied* type instead.
422 return _TypedProxyEqualityImpl(a, b, 0);
423 }
424 static TfPyObjWrapper GetPyObj(T const &obj) {
425#ifdef PXR_PYTHON_SUPPORT_ENABLED
426 ProxiedType const &p = VtGetProxiedObject(obj);
427 TfPyLock lock;
428 return pxr_boost::python::api::object(p);
429#else
430 return {};
431#endif //PXR_PYTHON_SUPPORT_ENABLED
432 }
433 static VtValueRef GetValueRef(T const &obj);
434 static std::ostream &StreamOut(T const &obj, std::ostream &out) {
435 return VtStreamOut(VtGetProxiedObject(obj), out);
436 }
437 static Vt_ShapeData const *GetShapeData(T const &obj) {
438 return _ArrayHelper<ProxiedType>::GetShapeData(
439 VtGetProxiedObject(obj));
440 }
441 static size_t GetNumElements(T const &obj) {
442 return _ArrayHelper<ProxiedType>::GetNumElements(
443 VtGetProxiedObject(obj));
444 }
445 static bool IsArrayValued(T const &) {
447 }
448 static std::type_info const &GetTypeid(T const &) {
449 return typeid(ProxiedType);
450 }
451 static std::type_info const &GetElementTypeid(T const &) {
452 return _ArrayHelper<ProxiedType>::GetElementTypeid();
453 }
454 static VtValue GetProxiedAsVtValue(T const &obj) {
455 return VtValue(VtGetProxiedObject(obj));
456 }
457 static bool HoldsType(T const &tp, std::type_info const &query) {
458 return TfSafeTypeCompare(typeid(ProxiedType), query);
459 }
460 static TfType GetTfType(T const &tp) {
461 return TfType::Find<ProxiedType>();
462 }
463 static void const *GetObjPtr(T const &tp) {
464 return static_cast<void const *>(&VtGetProxiedObject(tp));
465 }
466 };
467
468 // Proxy type helper. This version handles type-erased proxies.
469 template <class ErasedProxy>
470 struct _ErasedProxyHelper
471 {
472 static bool CanHash(ErasedProxy const &proxy) {
473 return VtGetErasedProxiedVtValue(proxy)->CanHash();
474 }
475 static size_t Hash(ErasedProxy const &proxy) {
476 return VtGetErasedProxiedVtValue(proxy)->GetHash();
477 }
478 static bool Equal(ErasedProxy const &a, ErasedProxy const &b) {
479 // We use the traditional int/long = 0 arg technique to disambiguate
480 // overloads, so we can invoke equality comparison on the *proxy*
481 // type if it provides one, or if it doesn't then invoke equality
482 // comparison on the VtValue containing the *proxied* type instead.
483 return _ErasedProxyEqualityImpl(a, b, 0);
484 }
485 static TfPyObjWrapper GetPyObj(ErasedProxy const &obj) {
486#ifdef PXR_PYTHON_SUPPORT_ENABLED
487 VtValue const *val = VtGetErasedProxiedVtValue(obj);
488 TfPyLock lock;
489 return pxr_boost::python::api::object(*val);
490#else
491 return {};
492#endif //PXR_PYTHON_SUPPORT_ENABLED
493 }
494 static VtValueRef GetValueRef(ErasedProxy const &obj);
495 static std::ostream &
496 StreamOut(ErasedProxy const &obj, std::ostream &out) {
497 return VtStreamOut(obj, out);
498 }
499 static Vt_ShapeData const *GetShapeData(ErasedProxy const &obj) {
500 return VtGetErasedProxiedVtValue(obj)->_GetShapeData();
501 }
502 static size_t GetNumElements(ErasedProxy const &obj) {
503 return VtGetErasedProxiedVtValue(obj)->_GetNumElements();
504 }
505 static bool IsArrayValued(ErasedProxy const &obj) {
506 return VtGetErasedProxiedVtValue(obj)->IsArrayValued();
507 }
508 static std::type_info const &GetTypeid(ErasedProxy const &obj) {
509 return VtGetErasedProxiedVtValue(obj)->GetTypeid();
510 }
511 static std::type_info const &GetElementTypeid(ErasedProxy const &obj) {
512 return VtGetErasedProxiedVtValue(obj)->GetElementTypeid();
513 }
514 static VtValue GetProxiedAsVtValue(ErasedProxy const &ep) {
515 return *VtGetErasedProxiedVtValue(ep);
516 }
517 static bool
518 HoldsType(ErasedProxy const &ep, std::type_info const &query) {
519 return VtErasedProxyHoldsType(ep, query);
520 }
521 static TfType GetTfType(ErasedProxy const &ep) {
522 return VtGetErasedProxiedTfType(ep);
523 }
524 static void const *GetObjPtr(ErasedProxy const &ep) {
525 VtValue const *val = VtGetErasedProxiedVtValue(ep);
526 return val ? val->_GetProxiedObjPtr() : nullptr;
527 }
528 };
529
530 // _TypeInfo implementation helper. This is a CRTP base that the
531 // _LocalTypeInfo and _RemoteTypeInfo types derive. It wraps their
532 // type-specific implementations with type-generic interfaces.
533 template <class T, class Container, class Derived>
534 struct _TypeInfoImpl : public _TypeInfo
535 {
536 static const bool IsLocal = _UsesLocalStore<T>::value;
537 static const bool HasTrivialCopy = _IsTriviallyCopyable<T>::value;
538 static const bool IsProxy = VtIsValueProxy<T>::value;
539
540 using ProxyHelper = TfConditionalType<
541 VtIsErasedValueProxy<T>::value,
542 _ErasedProxyHelper<T>, _TypedProxyHelper<T>>;
543
544 using This = _TypeInfoImpl;
545
546 constexpr _TypeInfoImpl()
547 : _TypeInfo(typeid(T),
548 _ArrayHelper<T>::GetElementTypeid(),
549 Vt_KnownValueTypeDetail::GetIndex<T>(),
551 VtIsHashable<T>(),
552 IsProxy,
555 &This::_CopyInit,
556 &This::_Destroy,
557 &This::_Move,
558 &This::_CanHash,
559 &This::_Hash,
560 &This::_Equal,
561 &This::_EqualPtr,
562 &This::_MakeMutable,
563 &This::_GetPyObj,
564 &This::_GetValueRef,
565 &This::_StreamOut,
566
567 &This::_GetTypeid,
568
569 // Array support.
570 &This::_IsArrayValued,
571 &This::_GetElementTypeid,
572 &This::_GetShapeData,
573 &This::_GetNumElements,
574
575 // Proxy support.
576 &This::_ProxyHoldsType,
577 &This::_GetProxiedType,
578 &This::_GetProxiedTypeid,
579 &This::_GetProxiedObjPtr,
580 &This::_GetProxiedAsVtValue)
581 {}
582
584 // Typed API for client use.
585 static T const &GetObj(_Storage const &storage) {
586 return Derived::_GetObj(_Container(storage));
587 }
588
589 static T &GetMutableObj(_Storage &storage) {
590 return Derived::_GetMutableObj(_Container(storage));
591 }
592
593 static void CopyInitObj(T const &objSrc, _Storage &dst) {
594 Derived::_PlaceCopy(&_Container(dst), objSrc);
595 }
596
597 private:
598 static_assert(sizeof(Container) <= sizeof(_Storage),
599 "Container size cannot exceed storage size.");
600
602 // _TypeInfo interface function implementations.
603 static void _CopyInit(_Storage const &src, _Storage &dst) {
604 new (&_Container(dst)) Container(_Container(src));
605 }
606
607 static void _Destroy(_Storage &storage) {
608 _Container(storage).~Container();
609 }
610
611 static bool _CanHash(_Storage const &storage) {
612 return ProxyHelper::CanHash(GetObj(storage));
613 }
614
615 static size_t _Hash(_Storage const &storage) {
616 return ProxyHelper::Hash(GetObj(storage));
617 }
618
619 static bool _Equal(_Storage const &lhs, _Storage const &rhs) {
620 // Equal is only ever invoked with an object of this specific type.
621 // That is, we only ever ask a proxy to compare to a proxy; we never
622 // ask a proxy to compare to the proxied object.
623 return ProxyHelper::Equal(GetObj(lhs), GetObj(rhs));
624 }
625
626 static bool _EqualPtr(_Storage const &lhs, void const *rhs) {
627 // Equal is only ever invoked with an object of this specific type.
628 // That is, we only ever ask a proxy to compare to a proxy; we never
629 // ask a proxy to compare to the proxied object.
630 return ProxyHelper::Equal(
631 GetObj(lhs), *static_cast<T const *>(rhs));
632 }
633
634 static void _Move(_Storage &src, _Storage &dst) noexcept {
635 new (&_Container(dst)) Container(std::move(_Container(src)));
636 _Destroy(src);
637 }
638
639 static void _MakeMutable(_Storage &storage) {
640 GetMutableObj(storage);
641 }
642
643 static TfPyObjWrapper _GetPyObj(_Storage const &storage) {
644 return ProxyHelper::GetPyObj(GetObj(storage));
645 }
646
647 static VtValueRef _GetValueRef(_Storage const &storage, bool rvalue);
648
649 static std::ostream &_StreamOut(
650 _Storage const &storage, std::ostream &out) {
651 return ProxyHelper::StreamOut(GetObj(storage), out);
652 }
653
654 static std::type_info const &_GetTypeid(_Storage const &storage) {
655 return ProxyHelper::GetTypeid(GetObj(storage));
656 }
657
658 static bool _IsArrayValued(_Storage const &storage) {
659 return ProxyHelper::IsArrayValued(GetObj(storage));
660 }
661
662 static std::type_info const &
663 _GetElementTypeid(_Storage const &storage) {
664 return ProxyHelper::GetElementTypeid(GetObj(storage));
665 }
666
667 static const Vt_ShapeData* _GetShapeData(_Storage const &storage) {
668 return ProxyHelper::GetShapeData(GetObj(storage));
669 }
670
671 static size_t _GetNumElements(_Storage const &storage) {
672 return ProxyHelper::GetNumElements(GetObj(storage));
673 }
674
675 static bool
676 _ProxyHoldsType(_Storage const &storage, std::type_info const &t) {
677 return ProxyHelper::HoldsType(GetObj(storage), t);
678 }
679
680 static TfType
681 _GetProxiedType(_Storage const &storage) {
682 return ProxyHelper::GetTfType(GetObj(storage));
683 }
684
685 static std::type_info const &
686 _GetProxiedTypeid(_Storage const &storage) {
687 return ProxyHelper::GetTypeid(GetObj(storage));
688 }
689
690 static void const *
691 _GetProxiedObjPtr(_Storage const &storage) {
692 return ProxyHelper::GetObjPtr(GetObj(storage));
693 }
694
695 static VtValue
696 _GetProxiedAsVtValue(_Storage const &storage) {
697 return ProxyHelper::GetProxiedAsVtValue(GetObj(storage));
698 }
699
701 // Internal helper -- cast type-generic storage to type-specific
702 // container.
703 static Container &_Container(_Storage &storage) {
704 // XXX Will need std::launder in c++17.
705 return *reinterpret_cast<Container *>(&storage);
706 }
707 static Container const &_Container(_Storage const &storage) {
708 // XXX Will need std::launder in c++17.
709 return *reinterpret_cast<Container const *>(&storage);
710 }
711 };
712
714 // Local-storage type info implementation. The container and the object are
715 // the same -- there is no distinct container.
716 template <class T>
717 struct _LocalTypeInfo : _TypeInfoImpl<
718 T, // type
719 T, // container
720 _LocalTypeInfo<T> // CRTP
721 >
722 {
723 constexpr _LocalTypeInfo()
724 : _TypeInfoImpl<T, T, _LocalTypeInfo<T>>()
725 {}
726
727 // Get returns object directly.
728 static T &_GetMutableObj(T &obj) { return obj; }
729 static T const &_GetObj(T const &obj) { return obj; }
730 // Place placement new's object directly.
731 static void _PlaceCopy(T *dst, T const &src) { new (dst) T(src); }
732 };
733
735 // Remote-storage type info implementation. The container is an
736 // TfDelegatedCountPtr to an object holder: _Counted<T>.
737 template <class T>
738 struct _RemoteTypeInfo : _TypeInfoImpl<
739 T, // type
740 TfDelegatedCountPtr<_Counted<T>>, // container
741 _RemoteTypeInfo<T> // CRTP
742 >
743 {
744 constexpr _RemoteTypeInfo()
745 : _TypeInfoImpl<
746 T, TfDelegatedCountPtr<_Counted<T>>, _RemoteTypeInfo<T>>()
747 {}
748
750 // Get returns object stored in the pointed-to _Counted<T>.
751 static T &_GetMutableObj(Ptr &ptr) {
752 if (!ptr->IsUnique()) {
753 ptr = TfMakeDelegatedCountPtr<_Counted<T>>(ptr->Get());
754 }
755 return ptr->GetMutable();
756 }
757 static T const &_GetObj(Ptr const &ptr) { return ptr->Get(); }
758 // PlaceCopy() allocates a new _Counted<T> with a copy of the object.
759 static void _PlaceCopy(Ptr *dst, T const &src) {
760 new (dst) Ptr(TfDelegatedCountIncrementTag, new _Counted<T>(src));
761 }
762 };
763
764 // Metafunction that returns the specific _TypeInfo subclass for T.
765 template <class T>
766 using _TypeInfoFor =
767 TfConditionalType<_UsesLocalStore<T>::value,
768 _LocalTypeInfo<T>, _RemoteTypeInfo<T>>;
769
770 // A helper that moves a held value to temporary storage, but keeps it alive
771 // until the _HoldAside object is destroyed. This is used when assigning
772 // over a VtValue that might own the object being assigned. For instance,
773 // if I have a VtValue holding a map<string, VtValue>, and I reassign this
774 // VtValue with one of the elements from the map, we must ensure that the
775 // map isn't destroyed until after the assignment has taken place.
776 friend struct _HoldAside;
777 struct _HoldAside {
778 explicit _HoldAside(VtValue *val)
779 : info((val->IsEmpty() || val->_IsLocalAndTriviallyCopyable())
780 ? static_cast<_TypeInfo const *>(NULL) : val->_info.Get()) {
781 if (info)
782 info->Move(val->_storage, storage);
783 }
784 ~_HoldAside() {
785 if (info)
786 info->Destroy(storage);
787 }
788 _Storage storage;
789 _TypeInfo const *info;
790 };
791
792 template <class T>
793 struct _Init {
794 using StoredType = typename Vt_ValueGetStored<T>::Type;
795 using TypeInfo = _TypeInfoFor<StoredType>;
796
797 static_assert(
799
800 static TfPointerAndBits<const _TypeInfo> _GetTypeInfo() {
801 static const TypeInfo ti;
802 static constexpr unsigned int flags =
803 (TypeInfo::IsLocal ? _LocalFlag : 0) |
804 (TypeInfo::HasTrivialCopy ? _TrivialCopyFlag : 0) |
805 (TypeInfo::IsProxy ? _ProxyFlag : 0);
806 return TfPointerAndBits<const _TypeInfo>(&ti, flags);
807 }
808
809 static void Init(VtValue *val, T const &obj) {
810 val->_info = _GetTypeInfo();
811 if constexpr (std::is_same_v<T, StoredType>) {
812 TypeInfo::CopyInitObj(obj, val->_storage);
813 }
814 else {
815 TypeInfo::CopyInitObj(StoredType {obj}, val->_storage);
816 }
817 }
818 };
819
820public:
821
824
826 VtValue(VtValue const &other) {
827 _Copy(other, *this);
828 }
829
831 VtValue(VtValue &&other) noexcept {
832 _Move(other, *this);
833 }
834
840 template <class T>
841 explicit VtValue(T const &obj) {
842 _Init<T>::Init(this, obj);
843 }
844
846 VT_API
847 explicit VtValue(VtValueRef ref);
848
868 template <class T>
869 static VtValue Take(T &obj) {
870 VtValue ret;
871 ret.Swap(obj);
872 return ret;
873 }
874
876 ~VtValue() { _Clear(); }
877
879 VtValue &operator=(VtValue const &other) {
880 if (ARCH_LIKELY(this != &other))
881 _Copy(other, *this);
882 return *this;
883 }
884
886 VtValue &operator=(VtValue &&other) noexcept {
887 if (ARCH_LIKELY(this != &other))
888 _Move(other, *this);
889 return *this;
890 }
891
893 VT_API
895
897 template <class T>
898 VtValue &operator=(T const &obj);
899
901 VtValue &Swap(VtValue &rhs) noexcept {
902 // Do nothing if both empty. Otherwise general swap.
903 if (!IsEmpty() || !rhs.IsEmpty()) {
904 VtValue tmp;
905 _Move(*this, tmp);
906 _Move(rhs, *this);
907 _Move(tmp, rhs);
908 }
909 return *this;
910 }
911
913 friend void swap(VtValue &lhs, VtValue &rhs) { lhs.Swap(rhs); }
914
919 template <class T>
920 void
921 Swap(T &rhs) {
922 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
923 "Can only VtValue::Swap with a type T that stores as T");
924 if (!IsHolding<T>())
925 *this = T();
926 UncheckedSwap(rhs);
927 }
928
933 template <class T>
934 void
936 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
937 "Can only VtValue::Swap with a type T that stores as T");
938 using std::swap;
939 swap(_GetMutable<T>(), rhs);
940 }
941
943 void UncheckedSwap(VtValue &rhs) { Swap(rhs); }
944
948 template <class T>
949 T Remove() {
950 T result;
951 Swap(result);
952 _Clear();
953 return result;
954 }
955
959 template <class T>
961 T result;
962 UncheckedSwap(result);
963 _Clear();
964 return result;
965 }
966
970 template <class T, class Fn>
971 bool
972 Mutate(Fn &&mutateFn) {
973 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
974 "Can only VtValue::Mutate a type T that stores as T");
975 if (!IsHolding<T>()) {
976 return false;
977 }
978 UncheckedMutate<T>(std::forward<Fn>(mutateFn));
979 return true;
980 }
981
985 template <class T, class Fn>
986 void
987 UncheckedMutate(Fn &&mutateFn) {
988 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
989 "Can only VtValue::Mutate a type T that stores as T");
990 // We move to a temporary, mutate the temporary, then move back. This
991 // prevents callers from escaping a mutable reference to the held object
992 // via a side-effect of mutateFn.
993 T &stored =_GetMutable<T>();
994 T tmp = std::move(stored);
995 std::forward<Fn>(mutateFn)(tmp);
996 stored = std::move(tmp);
997 }
998
1001 template <class T>
1002 bool IsHolding() const {
1003 return _info.GetLiteral() && _TypeIs<T>();
1004 }
1005
1007 VT_API bool IsArrayValued() const;
1008
1010 VT_API bool IsArrayEditValued() const;
1011
1014 size_t GetArraySize() const { return _GetNumElements(); }
1015
1017 VT_API std::type_info const &GetTypeid() const;
1018
1022 VT_API std::type_info const &GetElementTypeid() const;
1023
1025 VT_API TfType GetType() const;
1026
1028 VT_API std::string GetTypeName() const;
1029
1035 if (ARCH_UNLIKELY(_IsProxy())) {
1036 return _info->GetProxiedAsVtValue(
1037 _storage).GetKnownValueTypeIndex();
1038 }
1039 return _info.GetLiteral() ? _info->knownTypeIndex : -1;
1040 }
1041
1045 template <class T>
1046 T const &UncheckedGet() const & { return _Get<T>(); }
1047
1051 template <class T>
1052 T UncheckedGet() && { return UncheckedRemove<T>(); }
1053
1062 template <class T>
1063 T const &Get() const & {
1064 typedef Vt_DefaultValueFactory<T> Factory;
1065
1066 // In the unlikely case that the types don't match, we obtain a default
1067 // value to return and issue an error via _FailGet.
1068 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1069 return *(static_cast<T const *>(
1070 _FailGet(Factory::Invoke, typeid(T))));
1071 }
1072
1073 return _Get<T>();
1074 }
1075
1079 template <class T>
1080 T Get() && {
1081 typedef Vt_DefaultValueFactory<T> Factory;
1082
1083 // In the unlikely case that the types don't match, we obtain a default
1084 // value to return and issue an error via _FailGet.
1085 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1086 return *(static_cast<T const *>(
1087 _FailGet(Factory::Invoke, typeid(T))));
1088 }
1089
1090 return UncheckedRemove<T>();
1091 }
1092
1097 template <class T>
1098 T GetWithDefault(T const &def = T()) const {
1099 return IsHolding<T>() ? UncheckedGet<T>() : def;
1100 }
1101
1103 template <typename From, typename To>
1104 static void RegisterCast(VtValue (*castFn)(VtValue const &)) {
1105 _RegisterCast(typeid(From), typeid(To), castFn);
1106 }
1107
1109 // holding To.
1110 template <typename From, typename To>
1111 static void RegisterSimpleCast() {
1112 _RegisterCast(typeid(From), typeid(To), _SimpleCast<From, To>);
1113 }
1114
1117 template <typename From, typename To>
1119 RegisterSimpleCast<From, To>();
1120 RegisterSimpleCast<To, From>();
1121 }
1122
1130 template <typename T>
1131 static VtValue Cast(VtValue const &val) {
1132 VtValue ret = val;
1133 ret.Cast<T>();
1134 return ret;
1135 }
1136
1144 VT_API static VtValue
1145 CastToTypeOf(VtValue const &val, VtValue const &other);
1146
1154 VT_API static VtValue
1155 CastToTypeid(VtValue const &val, std::type_info const &type);
1156
1160 static bool CanCastFromTypeidToTypeid(std::type_info const &from,
1161 std::type_info const &to) {
1162 return _CanCast(from, to);
1163 }
1164
1172 template <typename T>
1174 if (IsHolding<T>())
1175 return *this;
1176 return *this = _PerformCast(typeid(T), *this);
1177 }
1178
1187 return CastToTypeid(other.GetTypeid());
1188 }
1189
1197 VtValue &CastToTypeid(std::type_info const &type) {
1198 if (!TfSafeTypeCompare(GetTypeid(), type)) {
1199 *this = _PerformCast(type, *this);
1200 }
1201 return *this;
1202 }
1203
1207 template <typename T>
1208 bool CanCast() const {
1209 return _CanCast(GetTypeid(), typeid(T));
1210 }
1211
1215 bool CanCastToTypeOf(VtValue const &other) const {
1216 return _CanCast(GetTypeid(), other.GetTypeid());
1217 }
1218
1222 bool CanCastToTypeid(std::type_info const &type) const {
1223 return _CanCast(GetTypeid(), type);
1224 }
1225
1227 bool IsEmpty() const { return _info.GetLiteral() == 0; }
1228
1232 VT_API VtValueRef Ref() const &;
1233
1237 VT_API VtValueRef Ref() &&;
1238
1240 VT_API operator VtValueRef() const &;
1241
1243 VT_API operator VtValueRef() &&;
1244
1246 VT_API bool CanHash() const;
1247
1249 VT_API size_t GetHash() const;
1250
1251 friend inline size_t hash_value(VtValue const &val) {
1252 return val.GetHash();
1253 }
1254
1260 VT_API bool CanComposeOver() const;
1261
1267 VT_API bool CanTransform() const;
1268
1270 template <typename T>
1271 friend bool operator == (VtValue const &lhs, T const &rhs) {
1272 typedef typename Vt_ValueGetStored<T>::Type Stored;
1273 return lhs.IsHolding<Stored>() && lhs.UncheckedGet<Stored>() == rhs;
1274 }
1275 template <typename T>
1276 friend bool operator == (T const &lhs, VtValue const &rhs) {
1277 return rhs == lhs;
1278 }
1279
1281 template <typename T>
1282 friend bool operator != (VtValue const &lhs, T const &rhs) {
1283 return !(lhs == rhs);
1284 }
1285 template <typename T>
1286 friend bool operator != (T const &lhs, VtValue const &rhs) {
1287 return !(lhs == rhs);
1288 }
1289
1291 bool operator == (const VtValue &rhs) const {
1292 bool empty = IsEmpty(), rhsEmpty = rhs.IsEmpty();
1293 if (empty || rhsEmpty) {
1294 // Either one or both empty -- only equal if both empty.
1295 return empty == rhsEmpty;
1296 }
1297 if (_info.GetLiteral() == rhs._info.GetLiteral()) {
1298 // Holding identical types -- compare directly.
1299 return _info.Get()->Equal(_storage, rhs._storage);
1300 }
1301 return _EqualityImpl(rhs);
1302 }
1303 bool operator != (const VtValue &rhs) const { return !(*this == rhs); }
1304
1306 VT_API friend std::ostream &
1307 operator << (std::ostream &out, const VtValue &self);
1308
1309private:
1310 VT_API const Vt_ShapeData* _GetShapeData() const;
1311 VT_API size_t _GetNumElements() const;
1312 friend struct Vt_ValueShapeDataAccess;
1313
1314 static inline void _Copy(VtValue const &src, VtValue &dst) {
1315 if (src.IsEmpty()) {
1316 dst._Clear();
1317 return;
1318 }
1319
1320 _HoldAside tmp(&dst);
1321 dst._info = src._info;
1322 if (src._IsLocalAndTriviallyCopyable()) {
1323 dst._storage = src._storage;
1324 } else {
1325 dst._info->CopyInit(src._storage, dst._storage);
1326 }
1327 }
1328
1329 static inline void _Move(VtValue &src, VtValue &dst) noexcept {
1330 if (src.IsEmpty()) {
1331 dst._Clear();
1332 return;
1333 }
1334
1335 _HoldAside tmp(&dst);
1336 dst._info = src._info;
1337 if (src._IsLocalAndTriviallyCopyable()) {
1338 dst._storage = src._storage;
1339 } else {
1340 dst._info->Move(src._storage, dst._storage);
1341 }
1342
1343 src._info.Set(nullptr, 0);
1344 }
1345
1346 template <class T>
1347 inline bool
1348 _TypeIs() const {
1349 if constexpr (VtIsKnownValueType_Workaround<T>::value) {
1350 return _info->knownTypeIndex == VtGetKnownValueTypeIndex<T>() ||
1351 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(typeid(T)));
1352 }
1353 else {
1354 std::type_info const &t = typeid(T);
1355 return TfSafeTypeCompare(_info->typeInfo, t) ||
1356 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(t));
1357 }
1358 }
1359
1360 VT_API bool _TypeIsImpl(std::type_info const &queriedType) const;
1361
1362 VT_API bool _EqualityImpl(VtValue const &rhs) const;
1363
1364 template <class T>
1365 T &
1366 _GetMutable() {
1367 using TypeInfo = _TypeInfoFor<T>;
1368 if constexpr (!VtIsValueProxy<T>::value) {
1369 // The request is not for a proxy type, so if we are holding a
1370 // proxy, collapse it out to the proxied value first.
1371 if (ARCH_UNLIKELY(_IsProxy())) {
1372 *this = _info->GetProxiedAsVtValue(_storage);
1373 }
1374 }
1375 return TypeInfo::GetMutableObj(_storage);
1376 }
1377
1378 template <class T>
1379 T const &
1380 _Get() const {
1381 using TypeInfo = _TypeInfoFor<T>;
1382 if constexpr (!VtIsValueProxy<T>::value) {
1383 // The request is not for a proxy type, so if we are holding a
1384 // proxy, fetch the underlying proxied object pointer.
1385 if (ARCH_UNLIKELY(_IsProxy())) {
1386 return *static_cast<T const *>(_GetProxiedObjPtr());
1387 }
1388 }
1389 return TypeInfo::GetObj(_storage);
1390 }
1391
1392 void const *_GetProxiedObjPtr() const {
1393 return _info->GetProxiedObjPtr(_storage);
1394 }
1395
1396 // Helper invoked in case Get fails. Reports an error and returns a default
1397 // value for \a queryType.
1398 VT_API void const *
1399 _FailGet(Vt_DefaultValueHolder (*factory)(),
1400 std::type_info const &queryType) const;
1401
1402 inline void _Clear() {
1403 // optimize for local types not to deref _info.
1404ARCH_PRAGMA_PUSH
1405// XXX: http://bug/DEV-16695
1406ARCH_PRAGMA_MAYBE_UNINITIALIZED
1407 if (_info.GetLiteral() && !_IsLocalAndTriviallyCopyable())
1408 _info.Get()->Destroy(_storage);
1409ARCH_PRAGMA_POP
1410 _info.Set(nullptr, 0);
1411 }
1412
1413 inline bool _IsLocalAndTriviallyCopyable() const {
1414 unsigned int bits = _info.BitsAs<unsigned int>();
1415 return (bits & (_LocalFlag | _TrivialCopyFlag)) ==
1416 (_LocalFlag | _TrivialCopyFlag);
1417 }
1418
1419 inline bool _IsProxy() const {
1420 return _info.BitsAs<unsigned int>() & _ProxyFlag;
1421 }
1422
1423 VT_API static void _RegisterCast(std::type_info const &from,
1424 std::type_info const &to,
1425 VtValue (*castFn)(VtValue const &));
1426
1427 // Cast \p value to the type \p to. Caller must ensure that val's type is
1428 // not already \p to.
1429 VT_API static VtValue
1430 _PerformCast(std::type_info const &to, VtValue const &val);
1431
1432 // Return true if \p from == \p to or if there is a registered cast to
1433 // convert VtValues holding \p from to \p to.
1434 VT_API static bool
1435 _CanCast(std::type_info const &from, std::type_info const &to);
1436
1437 // helper template function for simple casts from From to To.
1438 template <typename From, typename To>
1439 static VtValue _SimpleCast(VtValue const &val) {
1440 return VtValue(To(val.UncheckedGet<From>()));
1441 }
1442
1443 // This grants friend access to a function in the wrapper file for this
1444 // class. This lets the wrapper reach down into a value to get a
1445 // pxr_boost::python wrapped object corresponding to the held type. This
1446 // facility is necessary to get the python API we want.
1447 friend TfPyObjWrapper
1448 Vt_GetPythonObjectFromHeldValue(VtValue const &self);
1449
1450 VT_API TfPyObjWrapper _GetPythonObject() const;
1451
1452 _Storage _storage;
1454};
1455
1456#ifndef doxygen
1457
1458struct Vt_ValueShapeDataAccess {
1459 static const Vt_ShapeData* _GetShapeData(const VtValue& value) {
1460 return value._GetShapeData();
1461 }
1462
1463 static size_t _GetNumElements(const VtValue& value) {
1464 return value._GetNumElements();
1465 }
1466};
1467
1468//
1469// The Get()/IsHolding routines needs to be special-cased to handle getting a
1470// VtValue *as* a VtValue.
1471//
1472
1473template <>
1474inline const VtValue&
1475VtValue::Get<VtValue>() const & {
1476 return *this;
1477}
1478
1479template <>
1480inline VtValue
1481VtValue::Get<VtValue>() && {
1482 return std::move(*this);
1483}
1484
1485template <>
1486inline const VtValue&
1487VtValue::UncheckedGet<VtValue>() const & {
1488 return *this;
1489}
1490
1491template <>
1492inline VtValue
1493VtValue::UncheckedGet<VtValue>() && {
1494 return std::move(*this);
1495}
1496
1497template <>
1498inline bool
1499VtValue::IsHolding<VtValue>() const {
1500 return true;
1501}
1502
1503// Specialize VtValue::IsHolding<void>() to always return false.
1504template <>
1505inline bool
1506VtValue::IsHolding<void>() const {
1507 return false;
1508}
1509
1510#endif // !doxygen
1511
1512PXR_NAMESPACE_CLOSE_SCOPE
1513
1514// This unusual arrangement of closing the namespace, including valueRef.h, then
1515// reopening the namespace exists because value.h and valueRef.h are
1516// interdependent. A similar symmetric construct exists in valueRef.h. If
1517// value.h is included first, then valueRef.h will be included here. Otherwise
1518// if valueRef.h is included first then it will have included value.h. Either
1519// way all the necessary declarations from both types are present prior to the
1520// appearance of the following defintions.
1521
1522#include "pxr/base/vt/valueRef.h"
1523
1524PXR_NAMESPACE_OPEN_SCOPE
1525
1526template <class T>
1527VtValue &
1529{
1530 if constexpr (_TypeInfoFor<T>::IsLocal &&
1531 _TypeInfoFor<T>::HasTrivialCopy) {
1532 _Clear();
1533 _Init<T>::Init(this, obj);
1534 return *this;
1535 }
1536 else {
1537 _HoldAside tmp(this);
1538 _Init<T>::Init(this, obj);
1539 return *this;
1540 }
1541}
1542
1543template <>
1544VtValue &
1545VtValue::operator=<VtValueRef>(VtValueRef const &obj) = delete;
1546
1548VtValue::_TypeInfo::GetValueRef(_Storage const &storage, bool rvalue) const
1549{
1550 return _getValueRef(storage, rvalue);
1551}
1552
1553template <class T>
1555VtValue::_TypedProxyHelper<T>::GetValueRef(T const &obj)
1556{
1557 return VtGetProxiedObject(obj);
1558}
1559
1560template <class T>
1562VtValue::_ErasedProxyHelper<T>::GetValueRef(T const &obj)
1563{
1564 return *VtGetErasedProxiedVtValue(obj);
1565}
1566
1567template <class T, class C, class D>
1569VtValue::_TypeInfoImpl<T, C, D>
1570::_GetValueRef(_Storage const &storage, bool rvalue)
1571{
1572 if constexpr (!IsProxy) {
1573 // If `rvalue` is true, then this value is not a proxy, and we've been
1574 // called by a non-const member function, so it is safe to cast away
1575 // constness here.
1576 if (rvalue) {
1577 return std::move(GetMutableObj(const_cast<_Storage &>(storage)));
1578 }
1579 }
1580 return ProxyHelper::GetValueRef(GetObj(storage));
1581}
1582
1583PXR_NAMESPACE_CLOSE_SCOPE
1584
1585#endif // PXR_BASE_VT_VALUE_H
Defines all the types "TYPED" for which Vt creates a VtTYPEDArray typedef.
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:90
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:1222
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition: value.h:960
friend bool operator==(VtValue const &lhs, T const &rhs)
Tests for equality.
Definition: value.h:1271
int GetKnownValueTypeIndex() const
Return VtKnownValueTypeIndex<T> for the held type T.
Definition: value.h:1034
VT_API VtValue(VtValueRef ref)
Construct with VtValueRef.
T UncheckedGet() &&
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: value.h:1052
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:987
T Remove()
Make this value empty and return the held T instance.
Definition: value.h:949
static VtValue Take(T &obj)
Create a new VtValue, taking its contents from obj.
Definition: value.h:869
static void RegisterSimpleCast()
Register a simple cast from VtValue holding From to VtValue.
Definition: value.h:1111
VtValue & Cast()
Return this holding value type cast to T.
Definition: value.h:1173
VtValue & CastToTypeOf(VtValue const &other)
Return this holding value type cast to same type that other is holding.
Definition: value.h:1186
static void RegisterSimpleBidirectionalCast()
Register a two-way cast from VtValue holding From to VtValue holding To.
Definition: value.h:1118
VT_API VtValueRef Ref() const &
Return a VtValueRef that refers to the current object held by this VtValue.
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:972
VtValue(VtValue const &other)
Copy construct with other.
Definition: value.h:826
static void RegisterCast(VtValue(*castFn)(VtValue const &))
Register a cast from VtValue holding From to VtValue holding To.
Definition: value.h:1104
size_t GetArraySize() const
Return the number of elements in the held value if IsArrayValued(), return 0 otherwise.
Definition: value.h:1014
T Get() &&
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: value.h:1080
bool CanCastToTypeOf(VtValue const &other) const
Return if this can be cast to type.
Definition: value.h:1215
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:1098
void UncheckedSwap(T &rhs)
Swap the held value with rhs.
Definition: value.h:935
void UncheckedSwap(VtValue &rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: value.h:943
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:1227
VtValue & operator=(VtValue &&other) noexcept
Move assignment from another VtValue.
Definition: value.h:886
VtValue & CastToTypeid(std::type_info const &type)
Return this holding value type cast to type.
Definition: value.h:1197
VT_API TfType GetType() const
Returns the TfType of the type held by this value.
~VtValue()
Destructor.
Definition: value.h:876
VT_API std::type_info const & GetElementTypeid() const
If this value holds a VtArray or VtArrayEdit instance, return the typeid of its element type.
VT_API bool CanComposeOver() const
Return true if this value holds a type that has been declared at compile time to support composing ov...
VtValue(T const &obj)
Construct a VtValue holding a copy of obj.
Definition: value.h:841
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:901
friend void swap(VtValue &lhs, VtValue &rhs)
Overloaded swap() for generic code/stl/etc.
Definition: value.h:913
static VtValue Cast(VtValue const &val)
Return a VtValue holding val cast to hold T.
Definition: value.h:1131
VT_API VtValue & operator=(VtValueRef ref)
Assignment from VtValueRef.
bool CanCast() const
Return if this can be cast to T.
Definition: value.h:1208
T const & Get() const &
Returns a const reference to the held object if the held object is of type T.
Definition: value.h:1063
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:823
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:1282
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:1160
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
Definition: value.h:1002
VtValue(VtValue &&other) noexcept
Move construct with other.
Definition: value.h:831
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:1046
VtValue & operator=(VtValue const &other)
Copy assignment from another VtValue.
Definition: value.h:879
VT_API bool CanTransform() const
Return true if this value holds a type that has been declared to support value transforms at compile ...
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:921
VT_API std::type_info const & GetTypeid() const
Return the typeid of the type held by this value.
A non-owning type-erased view of a value, interoperating with VtValue.
Definition: valueRef.h:65
Demangle C++ typenames generated by the typeid() facility.
Compiler hints.
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 trait indicating whether VtValue compose-over functionality can be registered for a type.
Definition: traits.h:137
A trait indicating whether VtValue transform functionality can be registered for a type.
Definition: traits.h:147
A file containing basic constants and definitions.