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 explicit _Counted(T &&obj) : _obj(std::move(obj)) {
103 _refCount = 0;
104 }
105 bool IsUnique() const { return _refCount == 1; }
106 T const &Get() const { return _obj; }
107 T &GetMutable() { return _obj; }
108
109 private:
110 T _obj;
111 mutable std::atomic<int> _refCount;
112
113 friend inline void TfDelegatedCountIncrement(_Counted const *d) {
114 d->_refCount.fetch_add(1, std::memory_order_relaxed);
115 }
116 friend inline void TfDelegatedCountDecrement(_Counted const *d) noexcept {
117 if (d->_refCount.fetch_sub(1, std::memory_order_release) == 1) {
118 std::atomic_thread_fence(std::memory_order_acquire);
119 delete d;
120 }
121 }
122 };
123
124 // Hold objects up to 1 word large locally. This makes the total structure
125 // 16 bytes when compiled 64 bit (1 word type-info pointer, 1 word storage
126 // space).
127 static const size_t _MaxLocalSize = sizeof(void*);
128 typedef std::aligned_storage<
129 /* size */_MaxLocalSize, /* alignment */_MaxLocalSize>::type _Storage;
130
131 template <class T>
132 using _IsTriviallyCopyable = std::integral_constant<bool,
133 std::is_trivially_default_constructible_v<T> &&
134 std::is_trivially_copyable_v<T> &&
135 std::is_trivially_copy_assignable_v<T> &&
136 std::is_trivially_destructible_v<T>>;
137
138 // Metafunction that returns true if T should be stored locally, false if it
139 // should be stored remotely.
140 template <class T>
141 using _UsesLocalStore = std::integral_constant<bool,
142 (sizeof(T) <= sizeof(_Storage)) &&
143 VtValueTypeHasCheapCopy<T>::value &&
144 std::is_nothrow_move_constructible<T>::value &&
145 std::is_nothrow_move_assignable<T>::value>;
146
147 // Type information base class.
148 // We force alignment here in order to ensure that TfPointerAndBits has
149 // enough room to store all TypeInfo related flags.
150 struct alignas(8) _TypeInfo {
151 private:
152 using _CopyInitFunc = void (*)(_Storage const &, _Storage &);
153 using _DestroyFunc = void (*)(_Storage &);
154 using _MoveFunc = void (*)(_Storage &, _Storage &);
155 using _CanHashFunc = bool (*)(_Storage const &);
156 using _HashFunc = size_t (*)(_Storage const &);
157 using _EqualFunc = bool (*)(_Storage const &, _Storage const &);
158 using _EqualPtrFunc = bool (*)(_Storage const &, void const *);
159 using _MakeMutableFunc = void (*)(_Storage &);
160 using _GetPyObjFunc = TfPyObjWrapper (*)(_Storage const &);
161 using _GetValueRefFunc = VtValueRef (*)(_Storage const &, bool);
162 using _StreamOutFunc =
163 std::ostream & (*)(_Storage const &, std::ostream &);
164 using _GetTypeidFunc = std::type_info const & (*)(_Storage const &);
165 using _IsArrayValuedFunc = bool (*)(_Storage const &);
166 using _GetElementTypeidFunc =
167 std::type_info const & (*)(_Storage const &);
168 using _GetShapeDataFunc = const Vt_ShapeData* (*)(_Storage const &);
169 using _GetNumElementsFunc = size_t (*)(_Storage const &);
170 using _ProxyHoldsTypeFunc = bool (*)(_Storage const &, std::type_info const &);
171 using _GetProxiedTypeFunc = TfType (*)(_Storage const &);
172 using _GetProxiedTypeidFunc =
173 std::type_info const & (*)(_Storage const &);
174 using _GetProxiedObjPtrFunc = void const *(*)(_Storage const &);
175 using _GetProxiedAsVtValueFunc = VtValue (*)(_Storage const &);
176
177 protected:
178 constexpr _TypeInfo(const std::type_info &ti,
179 const std::type_info &elementTi,
180 int knownTypeIndex,
181 bool isArray,
182 bool isHashable,
183 bool isProxy,
184 bool canComposeOver,
185 bool canTransform,
186 _CopyInitFunc copyInit,
187 _DestroyFunc destroy,
188 _MoveFunc move,
189 _CanHashFunc canHash,
190 _HashFunc hash,
191 _EqualFunc equal,
192 _EqualPtrFunc equalPtr,
193 _MakeMutableFunc makeMutable,
194 _GetPyObjFunc getPyObj,
195 _GetValueRefFunc getValueRef,
196 _StreamOutFunc streamOut,
197 _GetTypeidFunc getTypeid,
198 _IsArrayValuedFunc isArrayValued,
199 _GetElementTypeidFunc getElementTypeid,
200 _GetShapeDataFunc getShapeData,
201 _GetNumElementsFunc getNumElements,
202 _ProxyHoldsTypeFunc proxyHoldsType,
203 _GetProxiedTypeFunc getProxiedType,
204 _GetProxiedTypeidFunc getProxiedTypeid,
205 _GetProxiedObjPtrFunc getProxiedObjPtr,
206 _GetProxiedAsVtValueFunc getProxiedAsVtValue)
207 : typeInfo(ti)
208 , elementTypeInfo(elementTi)
209 , knownTypeIndex(knownTypeIndex)
210 , isProxy(isProxy)
211 , isArray(isArray)
212 , isHashable(isHashable)
213 , canComposeOver(canComposeOver)
214 , canTransform(canTransform)
215 // Function table
216 , _copyInit(copyInit)
217 , _destroy(destroy)
218 , _move(move)
219 , _canHash(canHash)
220 , _hash(hash)
221 , _equal(equal)
222 , _equalPtr(equalPtr)
223 , _makeMutable(makeMutable)
224 , _getPyObj(getPyObj)
225 , _getValueRef(getValueRef)
226 , _streamOut(streamOut)
227 , _getTypeid(getTypeid)
228 , _isArrayValued(isArrayValued)
229 , _getElementTypeid(getElementTypeid)
230 , _getShapeData(getShapeData)
231 , _getNumElements(getNumElements)
232 , _proxyHoldsType(proxyHoldsType)
233 , _getProxiedType(getProxiedType)
234 , _getProxiedTypeid(getProxiedTypeid)
235 , _getProxiedObjPtr(getProxiedObjPtr)
236 , _getProxiedAsVtValue(getProxiedAsVtValue)
237 {}
238
239 public:
240 void CopyInit(_Storage const &src, _Storage &dst) const {
241 _copyInit(src, dst);
242 }
243 void Destroy(_Storage &storage) const {
244 _destroy(storage);
245 }
246 void Move(_Storage &src, _Storage &dst) const noexcept {
247 _move(src, dst);
248 }
249 bool CanHash(_Storage const &storage) const {
250 return _canHash(storage);
251 }
252 size_t Hash(_Storage const &storage) const {
253 return _hash(storage);
254 }
255 bool Equal(_Storage const &lhs, _Storage const &rhs) const {
256 return _equal(lhs, rhs);
257 }
258 bool EqualPtr(_Storage const &lhs, void const *rhs) const {
259 return _equalPtr(lhs, rhs);
260 }
261 void MakeMutable(_Storage &storage) const {
262 _makeMutable(storage);
263 }
264 TfPyObjWrapper GetPyObj(_Storage const &storage) const {
265 return _getPyObj(storage);
266 }
267 inline VtValueRef GetValueRef(_Storage const &storage,
268 bool rvalue) const;
269 std::ostream &StreamOut(_Storage const &storage,
270 std::ostream &out) const {
271 return _streamOut(storage, out);
272 }
273 bool IsArrayValued(_Storage const &storage) const {
274 return _isArrayValued(storage);
275 }
276 std::type_info const &GetElementTypeid(_Storage const &storage) const {
277 return _getElementTypeid(storage);
278 }
279 std::type_info const &GetTypeid(_Storage const &storage) const {
280 return _getTypeid(storage);
281 }
282 const Vt_ShapeData* GetShapeData(_Storage const &storage) const {
283 return _getShapeData(storage);
284 }
285 size_t GetNumElements(_Storage const &storage) const {
286 return _getNumElements(storage);
287 }
288 bool ProxyHoldsType(_Storage const &storage,
289 std::type_info const &t) const {
290 return _proxyHoldsType(storage, t);
291 }
292 TfType GetProxiedType(_Storage const &storage) const {
293 return _getProxiedType(storage);
294 }
295 std::type_info const &GetProxiedTypeid(_Storage const &storage) const {
296 return _getProxiedTypeid(storage);
297 }
298 VtValue GetProxiedAsVtValue(_Storage const &storage) const {
299 return _getProxiedAsVtValue(storage);
300 }
301 void const *GetProxiedObjPtr(_Storage const &storage) const {
302 return _getProxiedObjPtr(storage);
303 }
304
305 const std::type_info &typeInfo;
306 const std::type_info &elementTypeInfo;
307 int knownTypeIndex;
308 bool isProxy;
309 bool isArray;
310 bool isHashable;
311 bool canComposeOver;
312 bool canTransform;
313
314 private:
315 _CopyInitFunc _copyInit;
316 _DestroyFunc _destroy;
317 _MoveFunc _move;
318 _CanHashFunc _canHash;
319 _HashFunc _hash;
320 _EqualFunc _equal;
321 _EqualPtrFunc _equalPtr;
322 _MakeMutableFunc _makeMutable;
323 _GetPyObjFunc _getPyObj;
324 _GetValueRefFunc _getValueRef;
325 _StreamOutFunc _streamOut;
326 _GetTypeidFunc _getTypeid;
327 _IsArrayValuedFunc _isArrayValued;
328 _GetElementTypeidFunc _getElementTypeid;
329 _GetShapeDataFunc _getShapeData;
330 _GetNumElementsFunc _getNumElements;
331 _ProxyHoldsTypeFunc _proxyHoldsType;
332 _GetProxiedTypeFunc _getProxiedType;
333 _GetProxiedTypeidFunc _getProxiedTypeid;
334 _GetProxiedObjPtrFunc _getProxiedObjPtr;
335 _GetProxiedAsVtValueFunc _getProxiedAsVtValue;
336 };
337
338 // Type-dispatching overloads.
339
340 // Array type helpers. Non-array types have no shape data, no elements and
341 // report `void` for their element types.
342 template <class T>
343 struct _NonArrayHelper
344 {
345 static const Vt_ShapeData* GetShapeData(T const &) { return NULL; }
346 static size_t GetNumElements(T const &) { return 0; }
347 constexpr static std::type_info const &GetElementTypeid() {
348 return typeid(void);
349 }
350 };
351 // VtArray types report their qualities.
352 template <class Array>
353 struct _IsArrayHelper
354 {
355 static const Vt_ShapeData* GetShapeData(Array const &obj) {
356 return obj._GetShapeData();
357 }
358 static size_t GetNumElements(Array const &obj) {
359 return obj.size();
360 }
361 constexpr static std::type_info const &GetElementTypeid() {
362 return typeid(typename Array::ElementType);
363 }
364 };
365 // VtArrayEdit types are identical to non-array types except that they do
366 // report their underlying element type.
367 template <class ArrayEdit>
368 struct _IsArrayEditHelper : _NonArrayHelper<ArrayEdit>
369 {
370 constexpr static std::type_info const &GetElementTypeid() {
371 return typeid(typename ArrayEdit::ElementType);
372 }
373 };
374
375 // Select which flavor of array helper to use -- VtArray uses
376 // _IsArrayHelper, VtArrayEdit uses _IsArrayEditHelper, all other types use
377 // _NonArrayHelper.
378 template <class T>
379 using _ArrayHelper = TfConditionalType<
380 VtIsArray<T>::value, _IsArrayHelper<T>,
381 TfConditionalType<VtIsArrayEdit<T>::value,
382 _IsArrayEditHelper<T>, _NonArrayHelper<T>>
383 >;
384
385 // Function used in case T has equality comparison.
386 template <class T>
387 static inline auto
388 _TypedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
389 return a == b;
390 }
391 // Function used in case T does not have equality comparison.
392 template <class NoEqual>
393 static inline bool
394 _TypedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
395 return VtGetProxiedObject(a) == VtGetProxiedObject(b);
396 }
397
398 template <class T>
399 static inline auto
400 _ErasedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
401 return a == b;
402 }
403 // Function used in case T does not have equality comparison.
404 template <class NoEqual>
405 static inline bool
406 _ErasedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
407 return *VtGetErasedProxiedVtValue(a) == *VtGetErasedProxiedVtValue(b);
408 }
409
410 // Proxy type helper. This version handles non-proxies and typed proxies.
411 template <class T>
412 struct _TypedProxyHelper
413 {
414 using ProxiedType = typename VtGetProxiedType<T>::type;
415
416 static bool CanHash(T const &) { return VtIsHashable<ProxiedType>(); }
417 static size_t Hash(T const &obj) {
418 return VtHashValue(VtGetProxiedObject(obj));
419 }
420 static bool Equal(T const &a, T const &b) {
421 // We use the traditional int/long = 0 arg technique to disambiguate
422 // overloads, so we can invoke equality comparison on the *proxy*
423 // type if it provides one, or if it doesn't then invoke equality
424 // comparison on the *proxied* type instead.
425 return _TypedProxyEqualityImpl(a, b, 0);
426 }
427 static TfPyObjWrapper GetPyObj(T const &obj) {
428#ifdef PXR_PYTHON_SUPPORT_ENABLED
429 ProxiedType const &p = VtGetProxiedObject(obj);
430 TfPyLock lock;
431 return pxr_boost::python::api::object(p);
432#else
433 return {};
434#endif //PXR_PYTHON_SUPPORT_ENABLED
435 }
436 static VtValueRef GetValueRef(T const &obj);
437 static std::ostream &StreamOut(T const &obj, std::ostream &out) {
438 return VtStreamOut(VtGetProxiedObject(obj), out);
439 }
440 static Vt_ShapeData const *GetShapeData(T const &obj) {
441 return _ArrayHelper<ProxiedType>::GetShapeData(
442 VtGetProxiedObject(obj));
443 }
444 static size_t GetNumElements(T const &obj) {
445 return _ArrayHelper<ProxiedType>::GetNumElements(
446 VtGetProxiedObject(obj));
447 }
448 static bool IsArrayValued(T const &) {
450 }
451 static std::type_info const &GetTypeid(T const &) {
452 return typeid(ProxiedType);
453 }
454 static std::type_info const &GetElementTypeid(T const &) {
455 return _ArrayHelper<ProxiedType>::GetElementTypeid();
456 }
457 static VtValue GetProxiedAsVtValue(T const &obj) {
458 return VtValue(VtGetProxiedObject(obj));
459 }
460 static bool HoldsType(T const &tp, std::type_info const &query) {
461 return TfSafeTypeCompare(typeid(ProxiedType), query);
462 }
463 static TfType GetTfType(T const &tp) {
465 }
466 static void const *GetObjPtr(T const &tp) {
467 return static_cast<void const *>(&VtGetProxiedObject(tp));
468 }
469 };
470
471 // Proxy type helper. This version handles type-erased proxies.
472 template <class ErasedProxy>
473 struct _ErasedProxyHelper
474 {
475 static bool CanHash(ErasedProxy const &proxy) {
476 return VtGetErasedProxiedVtValue(proxy)->CanHash();
477 }
478 static size_t Hash(ErasedProxy const &proxy) {
479 return VtGetErasedProxiedVtValue(proxy)->GetHash();
480 }
481 static bool Equal(ErasedProxy const &a, ErasedProxy const &b) {
482 // We use the traditional int/long = 0 arg technique to disambiguate
483 // overloads, so we can invoke equality comparison on the *proxy*
484 // type if it provides one, or if it doesn't then invoke equality
485 // comparison on the VtValue containing the *proxied* type instead.
486 return _ErasedProxyEqualityImpl(a, b, 0);
487 }
488 static TfPyObjWrapper GetPyObj(ErasedProxy const &obj) {
489#ifdef PXR_PYTHON_SUPPORT_ENABLED
490 VtValue const *val = VtGetErasedProxiedVtValue(obj);
491 TfPyLock lock;
492 return pxr_boost::python::api::object(*val);
493#else
494 return {};
495#endif //PXR_PYTHON_SUPPORT_ENABLED
496 }
497 static VtValueRef GetValueRef(ErasedProxy const &obj);
498 static std::ostream &
499 StreamOut(ErasedProxy const &obj, std::ostream &out) {
500 return VtStreamOut(obj, out);
501 }
502 static Vt_ShapeData const *GetShapeData(ErasedProxy const &obj) {
503 return VtGetErasedProxiedVtValue(obj)->_GetShapeData();
504 }
505 static size_t GetNumElements(ErasedProxy const &obj) {
506 return VtGetErasedProxiedVtValue(obj)->_GetNumElements();
507 }
508 static bool IsArrayValued(ErasedProxy const &obj) {
509 return VtGetErasedProxiedVtValue(obj)->IsArrayValued();
510 }
511 static std::type_info const &GetTypeid(ErasedProxy const &obj) {
512 return VtGetErasedProxiedVtValue(obj)->GetTypeid();
513 }
514 static std::type_info const &GetElementTypeid(ErasedProxy const &obj) {
515 return VtGetErasedProxiedVtValue(obj)->GetElementTypeid();
516 }
517 static VtValue GetProxiedAsVtValue(ErasedProxy const &ep) {
518 return *VtGetErasedProxiedVtValue(ep);
519 }
520 static bool
521 HoldsType(ErasedProxy const &ep, std::type_info const &query) {
522 return VtErasedProxyHoldsType(ep, query);
523 }
524 static TfType GetTfType(ErasedProxy const &ep) {
525 return VtGetErasedProxiedTfType(ep);
526 }
527 static void const *GetObjPtr(ErasedProxy const &ep) {
528 VtValue const *val = VtGetErasedProxiedVtValue(ep);
529 return val ? val->_GetProxiedObjPtr() : nullptr;
530 }
531 };
532
533 // _TypeInfo implementation helper. This is a CRTP base that the
534 // _LocalTypeInfo and _RemoteTypeInfo types derive. It wraps their
535 // type-specific implementations with type-generic interfaces.
536 template <class T, class Container, class Derived>
537 struct _TypeInfoImpl : public _TypeInfo
538 {
539 static const bool IsLocal = _UsesLocalStore<T>::value;
540 static const bool HasTrivialCopy = _IsTriviallyCopyable<T>::value;
541 static const bool IsProxy = VtIsValueProxy<T>::value;
542
543 using ProxyHelper = TfConditionalType<
544 VtIsErasedValueProxy<T>::value,
545 _ErasedProxyHelper<T>, _TypedProxyHelper<T>>;
546
547 using This = _TypeInfoImpl;
548
549 constexpr _TypeInfoImpl()
550 : _TypeInfo(typeid(T),
551 _ArrayHelper<T>::GetElementTypeid(),
552 Vt_KnownValueTypeDetail::GetIndex<T>(),
555 IsProxy,
558 &This::_CopyInit,
559 &This::_Destroy,
560 &This::_Move,
561 &This::_CanHash,
562 &This::_Hash,
563 &This::_Equal,
564 &This::_EqualPtr,
565 &This::_MakeMutable,
566 &This::_GetPyObj,
567 &This::_GetValueRef,
568 &This::_StreamOut,
569
570 &This::_GetTypeid,
571
572 // Array support.
573 &This::_IsArrayValued,
574 &This::_GetElementTypeid,
575 &This::_GetShapeData,
576 &This::_GetNumElements,
577
578 // Proxy support.
579 &This::_ProxyHoldsType,
580 &This::_GetProxiedType,
581 &This::_GetProxiedTypeid,
582 &This::_GetProxiedObjPtr,
583 &This::_GetProxiedAsVtValue)
584 {}
585
587 // Typed API for client use.
588 static T const &GetObj(_Storage const &storage) {
589 return Derived::_GetObj(_Container(storage));
590 }
591
592 static T &GetMutableObj(_Storage &storage) {
593 return Derived::_GetMutableObj(_Container(storage));
594 }
595
596 template <class Arg>
597 static void InitObj(Arg &&objSrc, _Storage &dst) {
598 Derived::_Place(&_Container(dst), std::forward<Arg>(objSrc));
599 }
600
601 private:
602 static_assert(sizeof(Container) <= sizeof(_Storage),
603 "Container size cannot exceed storage size.");
604
606 // _TypeInfo interface function implementations.
607 static void _CopyInit(_Storage const &src, _Storage &dst) {
608 new (&_Container(dst)) Container(_Container(src));
609 }
610
611 static void _Destroy(_Storage &storage) {
612 _Container(storage).~Container();
613 }
614
615 static bool _CanHash(_Storage const &storage) {
616 return ProxyHelper::CanHash(GetObj(storage));
617 }
618
619 static size_t _Hash(_Storage const &storage) {
620 return ProxyHelper::Hash(GetObj(storage));
621 }
622
623 static bool _Equal(_Storage const &lhs, _Storage const &rhs) {
624 // Equal is only ever invoked with an object of this specific type.
625 // That is, we only ever ask a proxy to compare to a proxy; we never
626 // ask a proxy to compare to the proxied object.
627 return ProxyHelper::Equal(GetObj(lhs), GetObj(rhs));
628 }
629
630 static bool _EqualPtr(_Storage const &lhs, void const *rhs) {
631 // Equal is only ever invoked with an object of this specific type.
632 // That is, we only ever ask a proxy to compare to a proxy; we never
633 // ask a proxy to compare to the proxied object.
634 return ProxyHelper::Equal(
635 GetObj(lhs), *static_cast<T const *>(rhs));
636 }
637
638 static void _Move(_Storage &src, _Storage &dst) noexcept {
639 new (&_Container(dst)) Container(std::move(_Container(src)));
640 _Destroy(src);
641 }
642
643 static void _MakeMutable(_Storage &storage) {
644 GetMutableObj(storage);
645 }
646
647 static TfPyObjWrapper _GetPyObj(_Storage const &storage) {
648 return ProxyHelper::GetPyObj(GetObj(storage));
649 }
650
651 static VtValueRef _GetValueRef(_Storage const &storage, bool rvalue);
652
653 static std::ostream &_StreamOut(
654 _Storage const &storage, std::ostream &out) {
655 return ProxyHelper::StreamOut(GetObj(storage), out);
656 }
657
658 static std::type_info const &_GetTypeid(_Storage const &storage) {
659 return ProxyHelper::GetTypeid(GetObj(storage));
660 }
661
662 static bool _IsArrayValued(_Storage const &storage) {
663 return ProxyHelper::IsArrayValued(GetObj(storage));
664 }
665
666 static std::type_info const &
667 _GetElementTypeid(_Storage const &storage) {
668 return ProxyHelper::GetElementTypeid(GetObj(storage));
669 }
670
671 static const Vt_ShapeData* _GetShapeData(_Storage const &storage) {
672 return ProxyHelper::GetShapeData(GetObj(storage));
673 }
674
675 static size_t _GetNumElements(_Storage const &storage) {
676 return ProxyHelper::GetNumElements(GetObj(storage));
677 }
678
679 static bool
680 _ProxyHoldsType(_Storage const &storage, std::type_info const &t) {
681 return ProxyHelper::HoldsType(GetObj(storage), t);
682 }
683
684 static TfType
685 _GetProxiedType(_Storage const &storage) {
686 return ProxyHelper::GetTfType(GetObj(storage));
687 }
688
689 static std::type_info const &
690 _GetProxiedTypeid(_Storage const &storage) {
691 return ProxyHelper::GetTypeid(GetObj(storage));
692 }
693
694 static void const *
695 _GetProxiedObjPtr(_Storage const &storage) {
696 return ProxyHelper::GetObjPtr(GetObj(storage));
697 }
698
699 static VtValue
700 _GetProxiedAsVtValue(_Storage const &storage) {
701 return ProxyHelper::GetProxiedAsVtValue(GetObj(storage));
702 }
703
705 // Internal helper -- cast type-generic storage to type-specific
706 // container.
707 static Container &_Container(_Storage &storage) {
708 // XXX Will need std::launder in c++17.
709 return *reinterpret_cast<Container *>(&storage);
710 }
711 static Container const &_Container(_Storage const &storage) {
712 // XXX Will need std::launder in c++17.
713 return *reinterpret_cast<Container const *>(&storage);
714 }
715 };
716
718 // Local-storage type info implementation. The container and the object are
719 // the same -- there is no distinct container.
720 template <class T>
721 struct _LocalTypeInfo : _TypeInfoImpl<
722 T, // type
723 T, // container
724 _LocalTypeInfo<T> // CRTP
725 >
726 {
727 constexpr _LocalTypeInfo()
728 : _TypeInfoImpl<T, T, _LocalTypeInfo<T>>()
729 {}
730
731 // Get returns object directly.
732 static T &_GetMutableObj(T &obj) { return obj; }
733 static T const &_GetObj(T const &obj) { return obj; }
734 // Place-construct object directly.
735 template <class Arg>
736 static void _Place(T *dst, Arg &&arg) {
737 new (dst) T(std::forward<Arg>(arg));
738 }
739 };
740
742 // Remote-storage type info implementation. The container is an
743 // TfDelegatedCountPtr to an object holder: _Counted<T>.
744 template <class T>
745 struct _RemoteTypeInfo : _TypeInfoImpl<
746 T, // type
747 TfDelegatedCountPtr<_Counted<T>>, // container
748 _RemoteTypeInfo<T> // CRTP
749 >
750 {
751 constexpr _RemoteTypeInfo()
752 : _TypeInfoImpl<
753 T, TfDelegatedCountPtr<_Counted<T>>, _RemoteTypeInfo<T>>()
754 {}
755
756 using Ptr = TfDelegatedCountPtr<_Counted<T>>;
757 // Get returns object stored in the pointed-to _Counted<T>.
758 static T &_GetMutableObj(Ptr &ptr) {
759 if (!ptr->IsUnique()) {
760 ptr = TfMakeDelegatedCountPtr<_Counted<T>>(ptr->Get());
761 }
762 return ptr->GetMutable();
763 }
764 static T const &_GetObj(Ptr const &ptr) { return ptr->Get(); }
765 // Allocate a new _Counted<T> holding the object.
766 template <class Arg>
767 static void _Place(Ptr *dst, Arg &&arg) {
768 new (dst) Ptr(TfDelegatedCountIncrementTag,
769 new _Counted<T>(std::forward<Arg>(arg)));
770 }
771 };
772
773 // Metafunction that returns the specific _TypeInfo subclass for T.
774 template <class T>
775 using _TypeInfoFor =
776 TfConditionalType<_UsesLocalStore<T>::value,
777 _LocalTypeInfo<T>, _RemoteTypeInfo<T>>;
778
779 // A helper that moves a held value to temporary storage, but keeps it alive
780 // until the _HoldAside object is destroyed. This is used when assigning
781 // over a VtValue that might own the object being assigned. For instance,
782 // if I have a VtValue holding a map<string, VtValue>, and I reassign this
783 // VtValue with one of the elements from the map, we must ensure that the
784 // map isn't destroyed until after the assignment has taken place.
785 friend struct _HoldAside;
786 struct _HoldAside {
787 explicit _HoldAside(VtValue *val)
788 : info((val->IsEmpty() || val->_IsLocalAndTriviallyCopyable())
789 ? static_cast<_TypeInfo const *>(NULL) : val->_info.Get()) {
790 if (info)
791 info->Move(val->_storage, storage);
792 }
793 ~_HoldAside() {
794 if (info)
795 info->Destroy(storage);
796 }
797 _Storage storage;
798 _TypeInfo const *info;
799 };
800
801 template <class T>
802 struct _Init {
803 using StoredType = typename Vt_ValueGetStored<T>::Type;
804 using TypeInfo = _TypeInfoFor<StoredType>;
805
806 static_assert(
808
809 static TfPointerAndBits<const _TypeInfo> _GetTypeInfo() {
810 static const TypeInfo ti;
811 static constexpr unsigned int flags =
812 (TypeInfo::IsLocal ? _LocalFlag : 0) |
813 (TypeInfo::HasTrivialCopy ? _TrivialCopyFlag : 0) |
814 (TypeInfo::IsProxy ? _ProxyFlag : 0);
815 return TfPointerAndBits<const _TypeInfo>(&ti, flags);
816 }
817
818 template <class Arg>
819 static void Init(VtValue *val, Arg &&obj) {
820 val->_info = _GetTypeInfo();
821 if constexpr (std::is_same_v<T, StoredType>) {
822 TypeInfo::InitObj(std::forward<Arg>(obj), val->_storage);
823 }
824 else {
825 TypeInfo::InitObj(
826 StoredType{std::forward<Arg>(obj)}, val->_storage);
827 }
828 }
829 };
830
831public:
832
835
837 VtValue(VtValue const &other) {
838 _Copy(other, *this);
839 }
840
842 VtValue(VtValue &&other) noexcept {
843 _Move(other, *this);
844 }
845
846 // Overloads to prevent the forwarding templates from matching VtValue
847 // arguments of any value category.
848 VtValue(VtValue &other) : VtValue(const_cast<VtValue const &>(other)) {}
849 VtValue(VtValue const &&other) : VtValue(other) {}
850
856 template <class T>
857 explicit VtValue(T const &obj) {
858 _Init<T>::Init(this, obj);
859 }
860
862 template <class T, std::enable_if_t<!std::is_lvalue_reference_v<T>, int> = 0>
863 explicit VtValue(T &&obj) {
864 _Init<T>::Init(this, std::move(obj));
865 }
866
868 VT_API
869 explicit VtValue(VtValueRef const &ref);
870
872 VT_API
873 explicit VtValue(VtValueRef &ref);
874
876 VT_API
877 explicit VtValue(VtValueRef &&ref);
878
880 VT_API
881 explicit VtValue(VtValueRef const &&ref);
882
902 template <class T>
903 static VtValue Take(T &obj) {
904 VtValue ret;
905 ret.Swap(obj);
906 return ret;
907 }
908
910 ~VtValue() { _Clear(); }
911
913 VtValue &operator=(VtValue const &other) {
914 if (ARCH_LIKELY(this != &other))
915 _Copy(other, *this);
916 return *this;
917 }
918
920 VtValue &operator=(VtValue &&other) noexcept {
921 if (ARCH_LIKELY(this != &other))
922 _Move(other, *this);
923 return *this;
924 }
925
926 // Overloads to prevent the forwarding templates from matching VtValue
927 // arguments of any value category.
928 VtValue &operator=(VtValue &other) {
929 return *this = const_cast<VtValue const &>(other);
930 }
931 VtValue &operator=(VtValue const &&other) {
932 return *this = other;
933 }
934
936 VT_API
938
940 VT_API
942
944 VT_API
946
948 VT_API
950
952 template <class T>
953 VtValue &operator=(T const &obj);
954
956 template <class T, std::enable_if_t<!std::is_lvalue_reference_v<T>, int> = 0>
957 VtValue &operator=(T &&obj);
958
960 VtValue &Swap(VtValue &rhs) noexcept {
961 // Do nothing if both empty. Otherwise general swap.
962 if (!IsEmpty() || !rhs.IsEmpty()) {
963 VtValue tmp;
964 _Move(*this, tmp);
965 _Move(rhs, *this);
966 _Move(tmp, rhs);
967 }
968 return *this;
969 }
970
972 friend void swap(VtValue &lhs, VtValue &rhs) { lhs.Swap(rhs); }
973
978 template <class T>
979 void
980 Swap(T &rhs) {
981 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
982 "Can only VtValue::Swap with a type T that stores as T");
983 if (!IsHolding<T>())
984 *this = T();
985 UncheckedSwap(rhs);
986 }
987
992 template <class T>
993 void
995 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
996 "Can only VtValue::Swap with a type T that stores as T");
997 using std::swap;
998 swap(_GetMutable<T>(), rhs);
999 }
1000
1002 void UncheckedSwap(VtValue &rhs) { Swap(rhs); }
1003
1007 template <class T>
1009 T result;
1010 Swap(result);
1011 _Clear();
1012 return result;
1013 }
1014
1018 template <class T>
1020 T result;
1021 UncheckedSwap(result);
1022 _Clear();
1023 return result;
1024 }
1025
1029 template <class T, class Fn>
1030 bool
1031 Mutate(Fn &&mutateFn) {
1032 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
1033 "Can only VtValue::Mutate a type T that stores as T");
1034 if (!IsHolding<T>()) {
1035 return false;
1036 }
1037 UncheckedMutate<T>(std::forward<Fn>(mutateFn));
1038 return true;
1039 }
1040
1044 template <class T, class Fn>
1045 void
1046 UncheckedMutate(Fn &&mutateFn) {
1047 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
1048 "Can only VtValue::Mutate a type T that stores as T");
1049 // We move to a temporary, mutate the temporary, then move back. This
1050 // prevents callers from escaping a mutable reference to the held object
1051 // via a side-effect of mutateFn.
1052 T &stored =_GetMutable<T>();
1053 T tmp = std::move(stored);
1054 std::forward<Fn>(mutateFn)(tmp);
1055 stored = std::move(tmp);
1056 }
1057
1060 template <class T>
1061 bool IsHolding() const {
1062 return _info.GetLiteral() && _TypeIs<T>();
1063 }
1064
1066 VT_API bool IsArrayValued() const;
1067
1069 VT_API bool IsArrayEditValued() const;
1070
1073 size_t GetArraySize() const { return _GetNumElements(); }
1074
1076 VT_API std::type_info const &GetTypeid() const;
1077
1081 VT_API std::type_info const &GetElementTypeid() const;
1082
1084 VT_API TfType GetType() const;
1085
1087 VT_API std::string GetTypeName() const;
1088
1094 if (ARCH_UNLIKELY(_IsProxy())) {
1095 return _info->GetProxiedAsVtValue(
1096 _storage).GetKnownValueTypeIndex();
1097 }
1098 return _info.GetLiteral() ? _info->knownTypeIndex : -1;
1099 }
1100
1104 template <class T>
1105 T const &UncheckedGet() const & { return _Get<T>(); }
1106
1110 template <class T>
1112
1121 template <class T>
1122 T const &Get() const & {
1123 typedef Vt_DefaultValueFactory<T> Factory;
1124
1125 // In the unlikely case that the types don't match, we obtain a default
1126 // value to return and issue an error via _FailGet.
1127 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1128 return *(static_cast<T const *>(
1129 _FailGet(Factory::Invoke, typeid(T))));
1130 }
1131
1132 return _Get<T>();
1133 }
1134
1138 template <class T>
1139 T Get() && {
1140 typedef Vt_DefaultValueFactory<T> Factory;
1141
1142 // In the unlikely case that the types don't match, we obtain a default
1143 // value to return and issue an error via _FailGet.
1144 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1145 return *(static_cast<T const *>(
1146 _FailGet(Factory::Invoke, typeid(T))));
1147 }
1148
1149 return UncheckedRemove<T>();
1150 }
1151
1156 template <class T>
1157 T GetWithDefault(T const &def = T()) const {
1158 return IsHolding<T>() ? UncheckedGet<T>() : def;
1159 }
1160
1162 template <typename From, typename To>
1163 static void RegisterCast(VtValue (*castFn)(VtValue const &)) {
1164 _RegisterCast(typeid(From), typeid(To), castFn);
1165 }
1166
1168 // holding To.
1169 template <typename From, typename To>
1170 static void RegisterSimpleCast() {
1171 _RegisterCast(typeid(From), typeid(To), _SimpleCast<From, To>);
1172 }
1173
1176 template <typename From, typename To>
1181
1189 template <typename T>
1190 static VtValue Cast(VtValue const &val) {
1191 VtValue ret = val;
1192 ret.Cast<T>();
1193 return ret;
1194 }
1195
1203 VT_API static VtValue
1204 CastToTypeOf(VtValue const &val, VtValue const &other);
1205
1213 VT_API static VtValue
1214 CastToTypeid(VtValue const &val, std::type_info const &type);
1215
1219 static bool CanCastFromTypeidToTypeid(std::type_info const &from,
1220 std::type_info const &to) {
1221 return _CanCast(from, to);
1222 }
1223
1231 template <typename T>
1233 if (IsHolding<T>())
1234 return *this;
1235 return *this = _PerformCast(typeid(T), *this);
1236 }
1237
1246 return CastToTypeid(other.GetTypeid());
1247 }
1248
1256 VtValue &CastToTypeid(std::type_info const &type) {
1257 if (!TfSafeTypeCompare(GetTypeid(), type)) {
1258 *this = _PerformCast(type, *this);
1259 }
1260 return *this;
1261 }
1262
1266 template <typename T>
1267 bool CanCast() const {
1268 return _CanCast(GetTypeid(), typeid(T));
1269 }
1270
1274 bool CanCastToTypeOf(VtValue const &other) const {
1275 return _CanCast(GetTypeid(), other.GetTypeid());
1276 }
1277
1281 bool CanCastToTypeid(std::type_info const &type) const {
1282 return _CanCast(GetTypeid(), type);
1283 }
1284
1286 bool IsEmpty() const { return _info.GetLiteral() == 0; }
1287
1291 VT_API VtValueRef Ref() const &;
1292
1296 VT_API VtValueRef Ref() &&;
1297
1299 VT_API operator VtValueRef() const &;
1300
1302 VT_API operator VtValueRef() &&;
1303
1305 VT_API bool CanHash() const;
1306
1308 VT_API size_t GetHash() const;
1309
1310 friend inline size_t hash_value(VtValue const &val) {
1311 return val.GetHash();
1312 }
1313
1319 VT_API bool CanComposeOver() const;
1320
1326 VT_API bool CanTransform() const;
1327
1329 template <typename T>
1330 friend bool operator == (VtValue const &lhs, T const &rhs) {
1331 typedef typename Vt_ValueGetStored<T>::Type Stored;
1332 return lhs.IsHolding<Stored>() && lhs.UncheckedGet<Stored>() == rhs;
1333 }
1334 template <typename T>
1335 friend bool operator == (T const &lhs, VtValue const &rhs) {
1336 return rhs == lhs;
1337 }
1338
1340 template <typename T>
1341 friend bool operator != (VtValue const &lhs, T const &rhs) {
1342 return !(lhs == rhs);
1343 }
1344 template <typename T>
1345 friend bool operator != (T const &lhs, VtValue const &rhs) {
1346 return !(lhs == rhs);
1347 }
1348
1350 bool operator == (const VtValue &rhs) const {
1351 bool empty = IsEmpty(), rhsEmpty = rhs.IsEmpty();
1352 if (empty || rhsEmpty) {
1353 // Either one or both empty -- only equal if both empty.
1354 return empty == rhsEmpty;
1355 }
1356 if (_info.GetLiteral() == rhs._info.GetLiteral()) {
1357 // Holding identical types -- compare directly.
1358 return _info.Get()->Equal(_storage, rhs._storage);
1359 }
1360 return _EqualityImpl(rhs);
1361 }
1362 bool operator != (const VtValue &rhs) const { return !(*this == rhs); }
1363
1365 VT_API friend std::ostream &
1366 operator << (std::ostream &out, const VtValue &self);
1367
1368private:
1369 VT_API const Vt_ShapeData* _GetShapeData() const;
1370 VT_API size_t _GetNumElements() const;
1371 friend struct Vt_ValueShapeDataAccess;
1372
1373 static inline void _Copy(VtValue const &src, VtValue &dst) {
1374 if (src.IsEmpty()) {
1375 dst._Clear();
1376 return;
1377 }
1378
1379 _HoldAside tmp(&dst);
1380 dst._info = src._info;
1381 if (src._IsLocalAndTriviallyCopyable()) {
1382 dst._storage = src._storage;
1383 } else {
1384 dst._info->CopyInit(src._storage, dst._storage);
1385 }
1386 }
1387
1388 static inline void _Move(VtValue &src, VtValue &dst) noexcept {
1389 if (src.IsEmpty()) {
1390 dst._Clear();
1391 return;
1392 }
1393
1394 _HoldAside tmp(&dst);
1395 dst._info = src._info;
1396 if (src._IsLocalAndTriviallyCopyable()) {
1397 dst._storage = src._storage;
1398 } else {
1399 dst._info->Move(src._storage, dst._storage);
1400 }
1401
1402 src._info.Set(nullptr, 0);
1403 }
1404
1405 template <class T>
1406 inline bool
1407 _TypeIs() const {
1408 if constexpr (VtIsKnownValueType_Workaround<T>::value) {
1409 return _info->knownTypeIndex == VtGetKnownValueTypeIndex<T>() ||
1410 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(typeid(T)));
1411 }
1412 else {
1413 std::type_info const &t = typeid(T);
1414 return TfSafeTypeCompare(_info->typeInfo, t) ||
1415 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(t));
1416 }
1417 }
1418
1419 VT_API bool _TypeIsImpl(std::type_info const &queriedType) const;
1420
1421 VT_API bool _EqualityImpl(VtValue const &rhs) const;
1422
1423 template <class T>
1424 T &
1425 _GetMutable() {
1426 using TypeInfo = _TypeInfoFor<T>;
1427 if constexpr (!VtIsValueProxy<T>::value) {
1428 // The request is not for a proxy type, so if we are holding a
1429 // proxy, collapse it out to the proxied value first.
1430 if (ARCH_UNLIKELY(_IsProxy())) {
1431 *this = _info->GetProxiedAsVtValue(_storage);
1432 }
1433 }
1434 return TypeInfo::GetMutableObj(_storage);
1435 }
1436
1437 template <class T>
1438 T const &
1439 _Get() const {
1440 using TypeInfo = _TypeInfoFor<T>;
1441 if constexpr (!VtIsValueProxy<T>::value) {
1442 // The request is not for a proxy type, so if we are holding a
1443 // proxy, fetch the underlying proxied object pointer.
1444 if (ARCH_UNLIKELY(_IsProxy())) {
1445 return *static_cast<T const *>(_GetProxiedObjPtr());
1446 }
1447 }
1448 return TypeInfo::GetObj(_storage);
1449 }
1450
1451 void const *_GetProxiedObjPtr() const {
1452 return _info->GetProxiedObjPtr(_storage);
1453 }
1454
1455 // Helper invoked in case Get fails. Reports an error and returns a default
1456 // value for \a queryType.
1457 VT_API void const *
1458 _FailGet(Vt_DefaultValueHolder (*factory)(),
1459 std::type_info const &queryType) const;
1460
1461 inline void _Clear() {
1462 // optimize for local types not to deref _info.
1463ARCH_PRAGMA_PUSH
1464// XXX: http://bug/DEV-16695
1465ARCH_PRAGMA_MAYBE_UNINITIALIZED
1466 if (_info.GetLiteral() && !_IsLocalAndTriviallyCopyable())
1467 _info.Get()->Destroy(_storage);
1468ARCH_PRAGMA_POP
1469 _info.Set(nullptr, 0);
1470 }
1471
1472 inline bool _IsLocalAndTriviallyCopyable() const {
1473 unsigned int bits = _info.BitsAs<unsigned int>();
1474 return (bits & (_LocalFlag | _TrivialCopyFlag)) ==
1475 (_LocalFlag | _TrivialCopyFlag);
1476 }
1477
1478 inline bool _IsProxy() const {
1479 return _info.BitsAs<unsigned int>() & _ProxyFlag;
1480 }
1481
1482 VT_API static void _RegisterCast(std::type_info const &from,
1483 std::type_info const &to,
1484 VtValue (*castFn)(VtValue const &));
1485
1486 // Cast \p value to the type \p to. Caller must ensure that val's type is
1487 // not already \p to.
1488 VT_API static VtValue
1489 _PerformCast(std::type_info const &to, VtValue const &val);
1490
1491 // Return true if \p from == \p to or if there is a registered cast to
1492 // convert VtValues holding \p from to \p to.
1493 VT_API static bool
1494 _CanCast(std::type_info const &from, std::type_info const &to);
1495
1496 // helper template function for simple casts from From to To.
1497 template <typename From, typename To>
1498 static VtValue _SimpleCast(VtValue const &val) {
1499 return VtValue(To(val.UncheckedGet<From>()));
1500 }
1501
1502 // This grants friend access to a function in the wrapper file for this
1503 // class. This lets the wrapper reach down into a value to get a
1504 // pxr_boost::python wrapped object corresponding to the held type. This
1505 // facility is necessary to get the python API we want.
1506 friend TfPyObjWrapper
1507 Vt_GetPythonObjectFromHeldValue(VtValue const &self);
1508
1509 VT_API TfPyObjWrapper _GetPythonObject() const;
1510
1511 // This grants friend access to tests. This is necessary to test the
1512 // _GetHeldObjectPtrForDebugger method, which is specifically made private
1513 // in order to restrict its usage to debuggers.
1514 friend struct Vt_ValueTestAccess;
1515
1516 // Return the address of the held object or nullptr if empty. This function
1517 // is intended for use within debuggers.
1518 VT_API const void *_GetHeldObjectPtrForDebugger() const;
1519
1520 _Storage _storage;
1522};
1523
1524#ifndef doxygen
1525
1526struct Vt_ValueShapeDataAccess {
1527 static const Vt_ShapeData* _GetShapeData(const VtValue& value) {
1528 return value._GetShapeData();
1529 }
1530
1531 static size_t _GetNumElements(const VtValue& value) {
1532 return value._GetNumElements();
1533 }
1534};
1535
1536//
1537// The Get()/IsHolding routines needs to be special-cased to handle getting a
1538// VtValue *as* a VtValue.
1539//
1540
1541template <>
1542inline const VtValue&
1543VtValue::Get<VtValue>() const & {
1544 return *this;
1545}
1546
1547template <>
1548inline VtValue
1550 return std::move(*this);
1551}
1552
1553template <>
1554inline const VtValue&
1556 return *this;
1557}
1558
1559template <>
1560inline VtValue
1562 return std::move(*this);
1563}
1564
1565template <>
1566inline bool
1568 return true;
1569}
1570
1571// Specialize VtValue::IsHolding<void>() to always return false.
1572template <>
1573inline bool
1575 return false;
1576}
1577
1578#endif // !doxygen
1579
1580PXR_NAMESPACE_CLOSE_SCOPE
1581
1582// This unusual arrangement of closing the namespace, including valueRef.h, then
1583// reopening the namespace exists because value.h and valueRef.h are
1584// interdependent. A similar symmetric construct exists in valueRef.h. If
1585// value.h is included first, then valueRef.h will be included here. Otherwise
1586// if valueRef.h is included first then it will have included value.h. Either
1587// way all the necessary declarations from both types are present prior to the
1588// appearance of the following defintions.
1589
1590#include "pxr/base/vt/valueRef.h"
1591
1592PXR_NAMESPACE_OPEN_SCOPE
1593
1594template <class T>
1595VtValue &
1597{
1598 if constexpr (_TypeInfoFor<T>::IsLocal &&
1599 _TypeInfoFor<T>::HasTrivialCopy) {
1600 _Clear();
1601 _Init<T>::Init(this, obj);
1602 return *this;
1603 }
1604 else {
1605 _HoldAside tmp(this);
1606 _Init<T>::Init(this, obj);
1607 return *this;
1608 }
1609}
1610
1611template <class T, std::enable_if_t<!std::is_lvalue_reference_v<T>, int>>
1612VtValue &
1614{
1615 if constexpr (_TypeInfoFor<T>::IsLocal &&
1616 _TypeInfoFor<T>::HasTrivialCopy) {
1617 _Clear();
1618 _Init<T>::Init(this, std::move(obj));
1619 return *this;
1620 }
1621 else {
1622 _HoldAside tmp(this);
1623 _Init<T>::Init(this, std::move(obj));
1624 return *this;
1625 }
1626}
1627
1628
1630VtValue::_TypeInfo::GetValueRef(_Storage const &storage, bool rvalue) const
1631{
1632 return _getValueRef(storage, rvalue);
1633}
1634
1635template <class T>
1637VtValue::_TypedProxyHelper<T>::GetValueRef(T const &obj)
1638{
1639 return VtGetProxiedObject(obj);
1640}
1641
1642template <class T>
1644VtValue::_ErasedProxyHelper<T>::GetValueRef(T const &obj)
1645{
1646 return *VtGetErasedProxiedVtValue(obj);
1647}
1648
1649template <class T, class C, class D>
1651VtValue::_TypeInfoImpl<T, C, D>
1652::_GetValueRef(_Storage const &storage, bool rvalue)
1653{
1654 if constexpr (!IsProxy) {
1655 // If `rvalue` is true, then this value is not a proxy, and we've been
1656 // called by a non-const member function, so it is safe to cast away
1657 // constness here.
1658 if (rvalue) {
1659 return std::move(GetMutableObj(const_cast<_Storage &>(storage)));
1660 }
1661 }
1662 return ProxyHelper::GetValueRef(GetObj(storage));
1663}
1664
1665PXR_NAMESPACE_CLOSE_SCOPE
1666
1667#endif // PXR_BASE_VT_VALUE_H
Defines all the types "TYPED" for which Vt creates a VtTYPEDArray typedef.
constexpr int VtGetKnownValueTypeIndex()
Provide compile-time value type indexes for types that are "known" to Vt – specifically,...
Definition types.h:284
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.
TfType represents a dynamic runtime type.
Definition type.h:48
static TfType const & Find()
Retrieve the TfType corresponding to type T.
Definition type.h:136
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:1281
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition value.h:1019
VT_API VtValue(VtValueRef const &&ref)
This is an overloaded member function, provided for convenience. It differs from the above function o...
friend bool operator==(VtValue const &lhs, T const &rhs)
Tests for equality.
Definition value.h:1330
int GetKnownValueTypeIndex() const
Return VtKnownValueTypeIndex<T> for the held type T.
Definition value.h:1093
T UncheckedGet() &&
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition value.h:1111
static VT_API VtValue CastToTypeOf(VtValue const &val, VtValue const &other)
Return a VtValue holding val cast to same type that other is holding.
VT_API VtValue & operator=(VtValueRef &&ref)
This is an overloaded member function, provided for convenience. It differs from the above function o...
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:1046
T Remove()
Make this value empty and return the held T instance.
Definition value.h:1008
VT_API VtValue & operator=(VtValueRef const &ref)
Assignment from VtValueRef.
VtValue(T &&obj)
Construct a VtValue by moving from obj (rvalue overload).
Definition value.h:863
VT_API VtValue & operator=(VtValueRef &ref)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static VtValue Take(T &obj)
Create a new VtValue, taking its contents from obj.
Definition value.h:903
static void RegisterSimpleCast()
Register a simple cast from VtValue holding From to VtValue.
Definition value.h:1170
VtValue & Cast()
Return this holding value type cast to T.
Definition value.h:1232
VtValue & CastToTypeOf(VtValue const &other)
Return this holding value type cast to same type that other is holding.
Definition value.h:1245
static void RegisterSimpleBidirectionalCast()
Register a two-way cast from VtValue holding From to VtValue holding To.
Definition value.h:1177
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:1031
VtValue(VtValue const &other)
Copy construct with other.
Definition value.h:837
static void RegisterCast(VtValue(*castFn)(VtValue const &))
Register a cast from VtValue holding From to VtValue holding To.
Definition value.h:1163
size_t GetArraySize() const
Return the number of elements in the held value if IsArrayValued(), return 0 otherwise.
Definition value.h:1073
T Get() &&
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition value.h:1139
bool CanCastToTypeOf(VtValue const &other) const
Return if this can be cast to type.
Definition value.h:1274
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:1157
void UncheckedSwap(T &rhs)
Swap the held value with rhs.
Definition value.h:994
void UncheckedSwap(VtValue &rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition value.h:1002
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:1286
VtValue & operator=(VtValue &&other) noexcept
Move assignment from another VtValue.
Definition value.h:920
VT_API VtValue & operator=(VtValueRef const &&ref)
This is an overloaded member function, provided for convenience. It differs from the above function o...
VtValue & CastToTypeid(std::type_info const &type)
Return this holding value type cast to type.
Definition value.h:1256
VT_API TfType GetType() const
Returns the TfType of the type held by this value.
~VtValue()
Destructor.
Definition value.h:910
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:857
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:960
VT_API VtValue(VtValueRef &ref)
This is an overloaded member function, provided for convenience. It differs from the above function o...
friend void swap(VtValue &lhs, VtValue &rhs)
Overloaded swap() for generic code/stl/etc.
Definition value.h:972
static VtValue Cast(VtValue const &val)
Return a VtValue holding val cast to hold T.
Definition value.h:1190
bool CanCast() const
Return if this can be cast to T.
Definition value.h:1267
T const & Get() const &
Returns a const reference to the held object if the held object is of type T.
Definition value.h:1122
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:834
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:1341
VT_API VtValue(VtValueRef &&ref)
This is an overloaded member function, provided for convenience. It differs from the above function o...
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:1219
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
Definition value.h:1061
VtValue(VtValue &&other) noexcept
Move construct with other.
Definition value.h:842
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:1105
VtValue & operator=(VtValue const &other)
Copy assignment from another VtValue.
Definition value.h:913
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:980
VT_API VtValue(VtValueRef const &ref)
Construct with VtValueRef.
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
VT_API size_t GetHash() const
Return a hash code for the viewed object by calling VtHashValue() on it.
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.
constexpr bool VtIsHashable()
A constexpr function that returns true if T is hashable via VtHashValue(), false otherwise.
Definition hash.h:59
size_t VtHashValue(T const &val)
Compute a hash code for val by invoking TfHash()(val) or when not possible issue a coding error and r...
Definition hash.h:66