All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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/pointerAndBits.h"
24#include "pxr/base/tf/preprocessorUtilsLite.h"
27#include "pxr/base/tf/tf.h"
28#include "pxr/base/tf/type.h"
29
30#include "pxr/base/vt/api.h"
31#include "pxr/base/vt/hash.h"
32#include "pxr/base/vt/streamOut.h"
33#include "pxr/base/vt/traits.h"
34#include "pxr/base/vt/types.h"
35
36#include <iosfwd>
37#include <typeinfo>
38#include <type_traits>
39
40PXR_NAMESPACE_OPEN_SCOPE
41
45template <class T>
46struct Vt_DefaultValueFactory;
47
48// This is a helper class used by Vt_DefaultValueFactory to return a value with
49// its type erased and only known at runtime via a std::type_info.
50struct Vt_DefaultValueHolder
51{
52 // Creates a value-initialized object and stores the type_info for the
53 // static type.
54 template <typename T>
55 static Vt_DefaultValueHolder Create() {
56 return Vt_DefaultValueHolder(TfAnyUniquePtr::New<T>(), typeid(T));
57 }
58
59 // Creates a copy of the object and stores the type_info for the static
60 // type.
61 template <typename T>
62 static Vt_DefaultValueHolder Create(T const &val) {
63 return Vt_DefaultValueHolder(TfAnyUniquePtr::New(val), typeid(T));
64 }
65
66 // Return the runtime type of the held object.
67 std::type_info const &GetType() const {
68 return *_type;
69 }
70
71 // Return a pointer to the held object. This may be safely cast to the
72 // static type corresponding to the type_info returned by GetType.
73 void const *GetPointer() const {
74 return _ptr.Get();
75 }
76
77private:
78 Vt_DefaultValueHolder(TfAnyUniquePtr &&ptr, std::type_info const &type)
79 : _ptr(std::move(ptr)), _type(&type) {}
80
81 TfAnyUniquePtr _ptr;
82 std::type_info const *_type;
83};
84
85class VtValue;
86
87// Overload VtStreamOut for vector<VtValue>. Produces output like [value1,
88// value2, ... valueN].
89VT_API std::ostream &VtStreamOut(std::vector<VtValue> const &val, std::ostream &);
90
91#define VT_VALUE_SET_STORED_TYPE(SRC, DST) \
92 template <> struct Vt_ValueStoredType<SRC> { typedef DST Type; }
93
94template <class T> struct Vt_ValueStoredType { typedef T Type; };
95VT_VALUE_SET_STORED_TYPE(char const *, std::string);
96VT_VALUE_SET_STORED_TYPE(char *, std::string);
97
98#ifdef PXR_PYTHON_SUPPORT_ENABLED
99VT_VALUE_SET_STORED_TYPE(pxr_boost::python::object, TfPyObjWrapper);
100#endif // PXR_PYTHON_SUPPORT_ENABLED
101
102#undef VT_VALUE_SET_STORED_TYPE
103
104// A metafunction that gives the type VtValue should store for a given type T.
105template <class T>
106struct Vt_ValueGetStored
107 : Vt_ValueStoredType<std::decay_t<T>> {};
108
147{
148 static const unsigned int _LocalFlag = 1 << 0;
149 static const unsigned int _TrivialCopyFlag = 1 << 1;
150 static const unsigned int _ProxyFlag = 1 << 2;
151
152 template <class T>
153 struct _Counted {
154 explicit _Counted(T const &obj) : _obj(obj) {
155 _refCount = 0;
156 }
157 bool IsUnique() const { return _refCount == 1; }
158 T const &Get() const { return _obj; }
159 T &GetMutable() { return _obj; }
160
161 private:
162 T _obj;
163 mutable std::atomic<int> _refCount;
164
165 friend inline void TfDelegatedCountIncrement(_Counted const *d) {
166 d->_refCount.fetch_add(1, std::memory_order_relaxed);
167 }
168 friend inline void TfDelegatedCountDecrement(_Counted const *d) noexcept {
169 if (d->_refCount.fetch_sub(1, std::memory_order_release) == 1) {
170 std::atomic_thread_fence(std::memory_order_acquire);
171 delete d;
172 }
173 }
174 };
175
176 // Hold objects up to 1 word large locally. This makes the total structure
177 // 16 bytes when compiled 64 bit (1 word type-info pointer, 1 word storage
178 // space).
179 static const size_t _MaxLocalSize = sizeof(void*);
180 typedef std::aligned_storage<
181 /* size */_MaxLocalSize, /* alignment */_MaxLocalSize>::type _Storage;
182
183 template <class T>
184 using _IsTriviallyCopyable = std::integral_constant<bool,
185 std::is_trivially_default_constructible_v<T> &&
186 std::is_trivially_copyable_v<T> &&
187 std::is_trivially_copy_assignable_v<T> &&
188 std::is_trivially_destructible_v<T>>;
189
190 // Metafunction that returns true if T should be stored locally, false if it
191 // should be stored remotely.
192 template <class T>
193 using _UsesLocalStore = std::integral_constant<bool,
194 (sizeof(T) <= sizeof(_Storage)) &&
195 VtValueTypeHasCheapCopy<T>::value &&
196 std::is_nothrow_move_constructible<T>::value &&
197 std::is_nothrow_move_assignable<T>::value>;
198
199 // Type information base class.
200 struct _TypeInfo {
201 private:
202 using _CopyInitFunc = void (*)(_Storage const &, _Storage &);
203 using _DestroyFunc = void (*)(_Storage &);
204 using _MoveFunc = void (*)(_Storage &, _Storage &);
205 using _CanHashFunc = bool (*)(_Storage const &);
206 using _HashFunc = size_t (*)(_Storage const &);
207 using _EqualFunc = bool (*)(_Storage const &, _Storage const &);
208 using _EqualPtrFunc = bool (*)(_Storage const &, void const *);
209 using _MakeMutableFunc = void (*)(_Storage &);
210 using _GetPyObjFunc = TfPyObjWrapper (*)(_Storage const &);
211 using _StreamOutFunc =
212 std::ostream & (*)(_Storage const &, std::ostream &);
213 using _GetTypeidFunc = std::type_info const & (*)(_Storage const &);
214 using _IsArrayValuedFunc = bool (*)(_Storage const &);
215 using _GetElementTypeidFunc =
216 std::type_info const & (*)(_Storage const &);
217 using _GetShapeDataFunc = const Vt_ShapeData* (*)(_Storage const &);
218 using _GetNumElementsFunc = size_t (*)(_Storage const &);
219 using _ProxyHoldsTypeFunc = bool (*)(_Storage const &, std::type_info const &);
220 using _GetProxiedTypeFunc = TfType (*)(_Storage const &);
221 using _GetProxiedTypeidFunc =
222 std::type_info const & (*)(_Storage const &);
223 using _GetProxiedObjPtrFunc = void const *(*)(_Storage const &);
224 using _GetProxiedAsVtValueFunc = VtValue (*)(_Storage const &);
225
226 protected:
227 constexpr _TypeInfo(const std::type_info &ti,
228 const std::type_info &elementTi,
229 int knownTypeIndex,
230 bool isArray,
231 bool isHashable,
232 bool isProxy,
233 _CopyInitFunc copyInit,
234 _DestroyFunc destroy,
235 _MoveFunc move,
236 _CanHashFunc canHash,
237 _HashFunc hash,
238 _EqualFunc equal,
239 _EqualPtrFunc equalPtr,
240 _MakeMutableFunc makeMutable,
241 _GetPyObjFunc getPyObj,
242 _StreamOutFunc streamOut,
243 _GetTypeidFunc getTypeid,
244 _IsArrayValuedFunc isArrayValued,
245 _GetElementTypeidFunc getElementTypeid,
246 _GetShapeDataFunc getShapeData,
247 _GetNumElementsFunc getNumElements,
248 _ProxyHoldsTypeFunc proxyHoldsType,
249 _GetProxiedTypeFunc getProxiedType,
250 _GetProxiedTypeidFunc getProxiedTypeid,
251 _GetProxiedObjPtrFunc getProxiedObjPtr,
252 _GetProxiedAsVtValueFunc getProxiedAsVtValue)
253 : typeInfo(ti)
254 , elementTypeInfo(elementTi)
255 , knownTypeIndex(knownTypeIndex)
256 , isProxy(isProxy)
257 , isArray(isArray)
258 , isHashable(isHashable)
259 // Function table
260 , _copyInit(copyInit)
261 , _destroy(destroy)
262 , _move(move)
263 , _canHash(canHash)
264 , _hash(hash)
265 , _equal(equal)
266 , _equalPtr(equalPtr)
267 , _makeMutable(makeMutable)
268 , _getPyObj(getPyObj)
269 , _streamOut(streamOut)
270 , _getTypeid(getTypeid)
271 , _isArrayValued(isArrayValued)
272 , _getElementTypeid(getElementTypeid)
273 , _getShapeData(getShapeData)
274 , _getNumElements(getNumElements)
275 , _proxyHoldsType(proxyHoldsType)
276 , _getProxiedType(getProxiedType)
277 , _getProxiedTypeid(getProxiedTypeid)
278 , _getProxiedObjPtr(getProxiedObjPtr)
279 , _getProxiedAsVtValue(getProxiedAsVtValue)
280 {}
281
282 public:
283 void CopyInit(_Storage const &src, _Storage &dst) const {
284 _copyInit(src, dst);
285 }
286 void Destroy(_Storage &storage) const {
287 _destroy(storage);
288 }
289 void Move(_Storage &src, _Storage &dst) const noexcept {
290 _move(src, dst);
291 }
292 bool CanHash(_Storage const &storage) const {
293 return _canHash(storage);
294 }
295 size_t Hash(_Storage const &storage) const {
296 return _hash(storage);
297 }
298 bool Equal(_Storage const &lhs, _Storage const &rhs) const {
299 return _equal(lhs, rhs);
300 }
301 bool EqualPtr(_Storage const &lhs, void const *rhs) const {
302 return _equalPtr(lhs, rhs);
303 }
304 void MakeMutable(_Storage &storage) const {
305 _makeMutable(storage);
306 }
307 TfPyObjWrapper GetPyObj(_Storage const &storage) const {
308 return _getPyObj(storage);
309 }
310 std::ostream &StreamOut(_Storage const &storage,
311 std::ostream &out) const {
312 return _streamOut(storage, out);
313 }
314 bool IsArrayValued(_Storage const &storage) const {
315 return _isArrayValued(storage);
316 }
317 std::type_info const &GetElementTypeid(_Storage const &storage) const {
318 return _getElementTypeid(storage);
319 }
320 std::type_info const &GetTypeid(_Storage const &storage) const {
321 return _getTypeid(storage);
322 }
323 const Vt_ShapeData* GetShapeData(_Storage const &storage) const {
324 return _getShapeData(storage);
325 }
326 size_t GetNumElements(_Storage const &storage) const {
327 return _getNumElements(storage);
328 }
329 bool ProxyHoldsType(_Storage const &storage,
330 std::type_info const &t) const {
331 return _proxyHoldsType(storage, t);
332 }
333 TfType GetProxiedType(_Storage const &storage) const {
334 return _getProxiedType(storage);
335 }
336 std::type_info const &GetProxiedTypeid(_Storage const &storage) const {
337 return _getProxiedTypeid(storage);
338 }
339 VtValue GetProxiedAsVtValue(_Storage const &storage) const {
340 return _getProxiedAsVtValue(storage);
341 }
342 void const *GetProxiedObjPtr(_Storage const &storage) const {
343 return _getProxiedObjPtr(storage);
344 }
345
346 const std::type_info &typeInfo;
347 const std::type_info &elementTypeInfo;
348 int knownTypeIndex;
349 bool isProxy;
350 bool isArray;
351 bool isHashable;
352
353 private:
354 _CopyInitFunc _copyInit;
355 _DestroyFunc _destroy;
356 _MoveFunc _move;
357 _CanHashFunc _canHash;
358 _HashFunc _hash;
359 _EqualFunc _equal;
360 _EqualPtrFunc _equalPtr;
361 _MakeMutableFunc _makeMutable;
362 _GetPyObjFunc _getPyObj;
363 _StreamOutFunc _streamOut;
364 _GetTypeidFunc _getTypeid;
365 _IsArrayValuedFunc _isArrayValued;
366 _GetElementTypeidFunc _getElementTypeid;
367 _GetShapeDataFunc _getShapeData;
368 _GetNumElementsFunc _getNumElements;
369 _ProxyHoldsTypeFunc _proxyHoldsType;
370 _GetProxiedTypeFunc _getProxiedType;
371 _GetProxiedTypeidFunc _getProxiedTypeid;
372 _GetProxiedObjPtrFunc _getProxiedObjPtr;
373 _GetProxiedAsVtValueFunc _getProxiedAsVtValue;
374 };
375
376 // Type-dispatching overloads.
377
378 // Array type helper.
379 template <class T, class Enable=void>
380 struct _ArrayHelper
381 {
382 static const Vt_ShapeData* GetShapeData(T const &) { return NULL; }
383 static size_t GetNumElements(T const &) { return 0; }
384 constexpr static std::type_info const &GetElementTypeid() {
385 return typeid(void);
386 }
387 };
388 template <class Array>
389 struct _ArrayHelper<
390 Array, typename std::enable_if<VtIsArray<Array>::value>::type>
391 {
392 static const Vt_ShapeData* GetShapeData(Array const &obj) {
393 return obj._GetShapeData();
394 }
395 static size_t GetNumElements(Array const &obj) {
396 return obj.size();
397 }
398 constexpr static std::type_info const &GetElementTypeid() {
399 return typeid(typename Array::ElementType);
400 }
401 };
402
403 // Function used in case T has equality comparison.
404 template <class T>
405 static inline auto
406 _TypedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
407 return a == b;
408 }
409 // Function used in case T does not have equality comparison.
410 template <class NoEqual>
411 static inline bool
412 _TypedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
413 return VtGetProxiedObject(a) == VtGetProxiedObject(b);
414 }
415
416 template <class T>
417 static inline auto
418 _ErasedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
419 return a == b;
420 }
421 // Function used in case T does not have equality comparison.
422 template <class NoEqual>
423 static inline bool
424 _ErasedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
425 return *VtGetErasedProxiedVtValue(a) == *VtGetErasedProxiedVtValue(b);
426 }
427
428 // Proxy type helper. Base case handles non-proxies and typed proxies.
429 template <class T, class Enable = void>
430 struct _ProxyHelper
431 {
432 using ProxiedType = typename VtGetProxiedType<T>::type;
433
434 static bool CanHash(T const &) { return VtIsHashable<ProxiedType>(); }
435 static size_t Hash(T const &obj) {
436 return VtHashValue(VtGetProxiedObject(obj));
437 }
438 static bool Equal(T const &a, T const &b) {
439 // We use the traditional int/long = 0 arg technique to disambiguate
440 // overloads, so we can invoke equality comparison on the *proxy*
441 // type if it provides one, or if it doesn't then invoke equality
442 // comparison on the *proxied* type instead.
443 return _TypedProxyEqualityImpl(a, b, 0);
444 }
445 static TfPyObjWrapper GetPyObj(T const &obj) {
446#ifdef PXR_PYTHON_SUPPORT_ENABLED
447 ProxiedType const &p = VtGetProxiedObject(obj);
448 TfPyLock lock;
449 return pxr_boost::python::api::object(p);
450#else
451 return {};
452#endif //PXR_PYTHON_SUPPORT_ENABLED
453 }
454 static std::ostream &StreamOut(T const &obj, std::ostream &out) {
455 return VtStreamOut(VtGetProxiedObject(obj), out);
456 }
457 static Vt_ShapeData const *GetShapeData(T const &obj) {
458 return _ArrayHelper<ProxiedType>::GetShapeData(
459 VtGetProxiedObject(obj));
460 }
461 static size_t GetNumElements(T const &obj) {
462 return _ArrayHelper<ProxiedType>::GetNumElements(
463 VtGetProxiedObject(obj));
464 }
465 static bool IsArrayValued(T const &) {
467 }
468 static std::type_info const &GetTypeid(T const &) {
469 return typeid(ProxiedType);
470 }
471 static std::type_info const &GetElementTypeid(T const &) {
472 return _ArrayHelper<ProxiedType>::GetElementTypeid();
473 }
474 static VtValue GetProxiedAsVtValue(T const &obj) {
475 return VtValue(VtGetProxiedObject(obj));
476 }
477 static bool HoldsType(T const &tp, std::type_info const &query) {
478 return TfSafeTypeCompare(typeid(ProxiedType), query);
479 }
480 static TfType GetTfType(T const &tp) {
481 return TfType::Find<ProxiedType>();
482 }
483 static void const *GetObjPtr(T const &tp) {
484 return static_cast<void const *>(&VtGetProxiedObject(tp));
485 }
486 };
487
488 template <class ErasedProxy>
489 struct _ProxyHelper<
490 ErasedProxy, typename std::enable_if<
491 VtIsErasedValueProxy<ErasedProxy>::value>::type>
492 {
493 static bool CanHash(ErasedProxy const &proxy) {
494 return VtGetErasedProxiedVtValue(proxy)->CanHash();
495 }
496 static size_t Hash(ErasedProxy const &proxy) {
497 return VtGetErasedProxiedVtValue(proxy)->GetHash();
498 }
499 static bool Equal(ErasedProxy const &a, ErasedProxy const &b) {
500 // We use the traditional int/long = 0 arg technique to disambiguate
501 // overloads, so we can invoke equality comparison on the *proxy*
502 // type if it provides one, or if it doesn't then invoke equality
503 // comparison on the VtValue containing the *proxied* type instead.
504 return _ErasedProxyEqualityImpl(a, b, 0);
505 }
506 static TfPyObjWrapper GetPyObj(ErasedProxy const &obj) {
507#ifdef PXR_PYTHON_SUPPORT_ENABLED
508 VtValue const *val = VtGetErasedProxiedVtValue(obj);
509 TfPyLock lock;
510 return pxr_boost::python::api::object(*val);
511#else
512 return {};
513#endif //PXR_PYTHON_SUPPORT_ENABLED
514 }
515 static std::ostream &
516 StreamOut(ErasedProxy const &obj, std::ostream &out) {
517 return VtStreamOut(obj, out);
518 }
519 static Vt_ShapeData const *GetShapeData(ErasedProxy const &obj) {
520 return VtGetErasedProxiedVtValue(obj)->_GetShapeData();
521 }
522 static size_t GetNumElements(ErasedProxy const &obj) {
523 return VtGetErasedProxiedVtValue(obj)->_GetNumElements();
524 }
525 static bool IsArrayValued(ErasedProxy const &obj) {
526 return VtGetErasedProxiedVtValue(obj)->IsArrayValued();
527 }
528 static std::type_info const &GetTypeid(ErasedProxy const &obj) {
529 return VtGetErasedProxiedVtValue(obj)->GetTypeid();
530 }
531 static std::type_info const &GetElementTypeid(ErasedProxy const &obj) {
532 return VtGetErasedProxiedVtValue(obj)->GetElementTypeid();
533 }
534 static VtValue GetProxiedAsVtValue(ErasedProxy const &ep) {
535 return *VtGetErasedProxiedVtValue(ep);
536 }
537 static bool
538 HoldsType(ErasedProxy const &ep, std::type_info const &query) {
539 return VtErasedProxyHoldsType(ep, query);
540 }
541 static TfType GetTfType(ErasedProxy const &ep) {
542 return VtGetErasedProxiedTfType(ep);
543 }
544 static void const *GetObjPtr(ErasedProxy const &ep) {
545 VtValue const *val = VtGetErasedProxiedVtValue(ep);
546 return val ? val->_GetProxiedObjPtr() : nullptr;
547 }
548 };
549
550 // _TypeInfo implementation helper. This is a CRTP base that the
551 // _LocalTypeInfo and _RemoteTypeInfo types derive. It wraps their
552 // type-specific implementations with type-generic interfaces.
553 template <class T, class Container, class Derived>
554 struct _TypeInfoImpl : public _TypeInfo
555 {
556 static const bool IsLocal = _UsesLocalStore<T>::value;
557 static const bool HasTrivialCopy = _IsTriviallyCopyable<T>::value;
558 static const bool IsProxy = VtIsValueProxy<T>::value;
559
560 using ProxyHelper = _ProxyHelper<T>;
561
562 using This = _TypeInfoImpl;
563
564 constexpr _TypeInfoImpl()
565 : _TypeInfo(typeid(T),
566 _ArrayHelper<T>::GetElementTypeid(),
567 Vt_KnownValueTypeDetail::GetIndex<T>(),
569 VtIsHashable<T>(),
570 IsProxy,
571 &This::_CopyInit,
572 &This::_Destroy,
573 &This::_Move,
574 &This::_CanHash,
575 &This::_Hash,
576 &This::_Equal,
577 &This::_EqualPtr,
578 &This::_MakeMutable,
579 &This::_GetPyObj,
580 &This::_StreamOut,
581
582 &This::_GetTypeid,
583
584 // Array support.
585 &This::_IsArrayValued,
586 &This::_GetElementTypeid,
587 &This::_GetShapeData,
588 &This::_GetNumElements,
589
590 // Proxy support.
591 &This::_ProxyHoldsType,
592 &This::_GetProxiedType,
593 &This::_GetProxiedTypeid,
594 &This::_GetProxiedObjPtr,
595 &This::_GetProxiedAsVtValue)
596 {}
597
599 // Typed API for client use.
600 static T const &GetObj(_Storage const &storage) {
601 return Derived::_GetObj(_Container(storage));
602 }
603
604 static T &GetMutableObj(_Storage &storage) {
605 return Derived::_GetMutableObj(_Container(storage));
606 }
607
608 static void CopyInitObj(T const &objSrc, _Storage &dst) {
609 Derived::_PlaceCopy(&_Container(dst), objSrc);
610 }
611
612 private:
613 static_assert(sizeof(Container) <= sizeof(_Storage),
614 "Container size cannot exceed storage size.");
615
617 // _TypeInfo interface function implementations.
618 static void _CopyInit(_Storage const &src, _Storage &dst) {
619 new (&_Container(dst)) Container(_Container(src));
620 }
621
622 static void _Destroy(_Storage &storage) {
623 _Container(storage).~Container();
624 }
625
626 static bool _CanHash(_Storage const &storage) {
627 return ProxyHelper::CanHash(GetObj(storage));
628 }
629
630 static size_t _Hash(_Storage const &storage) {
631 return ProxyHelper::Hash(GetObj(storage));
632 }
633
634 static bool _Equal(_Storage const &lhs, _Storage const &rhs) {
635 // Equal is only ever invoked with an object of this specific type.
636 // That is, we only ever ask a proxy to compare to a proxy; we never
637 // ask a proxy to compare to the proxied object.
638 return ProxyHelper::Equal(GetObj(lhs), GetObj(rhs));
639 }
640
641 static bool _EqualPtr(_Storage const &lhs, void const *rhs) {
642 // Equal is only ever invoked with an object of this specific type.
643 // That is, we only ever ask a proxy to compare to a proxy; we never
644 // ask a proxy to compare to the proxied object.
645 return ProxyHelper::Equal(
646 GetObj(lhs), *static_cast<T const *>(rhs));
647 }
648
649 static void _Move(_Storage &src, _Storage &dst) noexcept {
650 new (&_Container(dst)) Container(std::move(_Container(src)));
651 _Destroy(src);
652 }
653
654 static void _MakeMutable(_Storage &storage) {
655 GetMutableObj(storage);
656 }
657
658 static TfPyObjWrapper _GetPyObj(_Storage const &storage) {
659 return ProxyHelper::GetPyObj(GetObj(storage));
660 }
661
662 static std::ostream &_StreamOut(
663 _Storage const &storage, std::ostream &out) {
664 return ProxyHelper::StreamOut(GetObj(storage), out);
665 }
666
667 static std::type_info const &_GetTypeid(_Storage const &storage) {
668 return ProxyHelper::GetTypeid(GetObj(storage));
669 }
670
671 static bool _IsArrayValued(_Storage const &storage) {
672 return ProxyHelper::IsArrayValued(GetObj(storage));
673 }
674
675 static std::type_info const &
676 _GetElementTypeid(_Storage const &storage) {
677 return ProxyHelper::GetElementTypeid(GetObj(storage));
678 }
679
680 static const Vt_ShapeData* _GetShapeData(_Storage const &storage) {
681 return ProxyHelper::GetShapeData(GetObj(storage));
682 }
683
684 static size_t _GetNumElements(_Storage const &storage) {
685 return ProxyHelper::GetNumElements(GetObj(storage));
686 }
687
688 static bool
689 _ProxyHoldsType(_Storage const &storage, std::type_info const &t) {
690 return ProxyHelper::HoldsType(GetObj(storage), t);
691 }
692
693 static TfType
694 _GetProxiedType(_Storage const &storage) {
695 return ProxyHelper::GetTfType(GetObj(storage));
696 }
697
698 static std::type_info const &
699 _GetProxiedTypeid(_Storage const &storage) {
700 return ProxyHelper::GetTypeid(GetObj(storage));
701 }
702
703 static void const *
704 _GetProxiedObjPtr(_Storage const &storage) {
705 return ProxyHelper::GetObjPtr(GetObj(storage));
706 }
707
708 static VtValue
709 _GetProxiedAsVtValue(_Storage const &storage) {
710 return ProxyHelper::GetProxiedAsVtValue(GetObj(storage));
711 }
712
714 // Internal helper -- cast type-generic storage to type-specific
715 // container.
716 static Container &_Container(_Storage &storage) {
717 // XXX Will need std::launder in c++17.
718 return *reinterpret_cast<Container *>(&storage);
719 }
720 static Container const &_Container(_Storage const &storage) {
721 // XXX Will need std::launder in c++17.
722 return *reinterpret_cast<Container const *>(&storage);
723 }
724 };
725
727 // Local-storage type info implementation. The container and the object are
728 // the same -- there is no distinct container.
729 template <class T>
730 struct _LocalTypeInfo : _TypeInfoImpl<
731 T, // type
732 T, // container
733 _LocalTypeInfo<T> // CRTP
734 >
735 {
736 constexpr _LocalTypeInfo()
737 : _TypeInfoImpl<T, T, _LocalTypeInfo<T>>()
738 {}
739
740 // Get returns object directly.
741 static T &_GetMutableObj(T &obj) { return obj; }
742 static T const &_GetObj(T const &obj) { return obj; }
743 // Place placement new's object directly.
744 static void _PlaceCopy(T *dst, T const &src) { new (dst) T(src); }
745 };
746
748 // Remote-storage type info implementation. The container is an
749 // TfDelegatedCountPtr to an object holder: _Counted<T>.
750 template <class T>
751 struct _RemoteTypeInfo : _TypeInfoImpl<
752 T, // type
753 TfDelegatedCountPtr<_Counted<T>>, // container
754 _RemoteTypeInfo<T> // CRTP
755 >
756 {
757 constexpr _RemoteTypeInfo()
758 : _TypeInfoImpl<
759 T, TfDelegatedCountPtr<_Counted<T>>, _RemoteTypeInfo<T>>()
760 {}
761
763 // Get returns object stored in the pointed-to _Counted<T>.
764 static T &_GetMutableObj(Ptr &ptr) {
765 if (!ptr->IsUnique()) {
766 ptr = TfMakeDelegatedCountPtr<_Counted<T>>(ptr->Get());
767 }
768 return ptr->GetMutable();
769 }
770 static T const &_GetObj(Ptr const &ptr) { return ptr->Get(); }
771 // PlaceCopy() allocates a new _Counted<T> with a copy of the object.
772 static void _PlaceCopy(Ptr *dst, T const &src) {
773 new (dst) Ptr(TfDelegatedCountIncrementTag, new _Counted<T>(src));
774 }
775 };
776
777 // Metafunction that returns the specific _TypeInfo subclass for T.
778 template <class T>
779 struct _TypeInfoFor {
780 // return _UsesLocalStore(T) ? _LocalTypeInfo<T> : _RemoteTypeInfo<T>;
781 typedef std::conditional_t<_UsesLocalStore<T>::value,
782 _LocalTypeInfo<T>,
783 _RemoteTypeInfo<T>> Type;
784 };
785
786 // Make sure char[N] is treated as a string.
787 template <size_t N>
788 struct _TypeInfoFor<char[N]> : _TypeInfoFor<std::string> {};
789
790 // Runtime function to return a _TypeInfo base pointer to a specific
791 // _TypeInfo subclass for type T.
792 template <class T>
793 static TfPointerAndBits<const _TypeInfo> GetTypeInfo() {
794 typedef typename _TypeInfoFor<T>::Type TI;
795 static const TI ti;
796 static constexpr unsigned int flags =
797 (TI::IsLocal ? _LocalFlag : 0) |
798 (TI::HasTrivialCopy ? _TrivialCopyFlag : 0) |
799 (TI::IsProxy ? _ProxyFlag : 0);
800 return TfPointerAndBits<const _TypeInfo>(&ti, flags);
801 }
802
803 // A helper that moves a held value to temporary storage, but keeps it alive
804 // until the _HoldAside object is destroyed. This is used when assigning
805 // over a VtValue that might own the object being assigned. For instance,
806 // if I have a VtValue holding a map<string, VtValue>, and I reassign this
807 // VtValue with one of the elements from the map, we must ensure that the
808 // map isn't destroyed until after the assignment has taken place.
809 friend struct _HoldAside;
810 struct _HoldAside {
811 explicit _HoldAside(VtValue *val)
812 : info((val->IsEmpty() || val->_IsLocalAndTriviallyCopyable())
813 ? static_cast<_TypeInfo const *>(NULL) : val->_info.Get()) {
814 if (info)
815 info->Move(val->_storage, storage);
816 }
817 ~_HoldAside() {
818 if (info)
819 info->Destroy(storage);
820 }
821 _Storage storage;
822 _TypeInfo const *info;
823 };
824
825 template <class T>
826 std::enable_if_t<
827 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
828 _Init(T const &obj) {
829 _info = GetTypeInfo<T>();
830 typedef typename _TypeInfoFor<T>::Type TypeInfo;
831 TypeInfo::CopyInitObj(obj, _storage);
832 }
833
834 template <class T>
835 std::enable_if_t<
836 !std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
837 _Init(T const &obj) {
838 _Init(typename Vt_ValueGetStored<T>::Type(obj));
839 }
840
841public:
842
845
847 VtValue(VtValue const &other) {
848 _Copy(other, *this);
849 }
850
852 VtValue(VtValue &&other) noexcept {
853 _Move(other, *this);
854 }
855
861 template <class T>
862 explicit VtValue(T const &obj) {
863 _Init(obj);
864 }
865
885 template <class T>
886 static VtValue Take(T &obj) {
887 VtValue ret;
888 ret.Swap(obj);
889 return ret;
890 }
891
893 ~VtValue() { _Clear(); }
894
896 VtValue &operator=(VtValue const &other) {
897 if (ARCH_LIKELY(this != &other))
898 _Copy(other, *this);
899 return *this;
900 }
901
903 VtValue &operator=(VtValue &&other) noexcept {
904 if (ARCH_LIKELY(this != &other))
905 _Move(other, *this);
906 return *this;
907 }
908
909#ifndef doxygen
910 template <class T>
911 inline
912 std::enable_if_t<
913 _TypeInfoFor<T>::Type::IsLocal &&
914 _TypeInfoFor<T>::Type::HasTrivialCopy,
915 VtValue &>
916 operator=(T obj) {
917 _Clear();
918 _Init(obj);
919 return *this;
920 }
921#endif
922
924#ifdef doxygen
925 template <class T>
926 VtValue&
927 operator=(T const &obj);
928#else
929 template <class T>
930 std::enable_if_t<
931 !_TypeInfoFor<T>::Type::IsLocal ||
932 !_TypeInfoFor<T>::Type::HasTrivialCopy,
933 VtValue &>
934 operator=(T const &obj) {
935 _HoldAside tmp(this);
936 _Init(obj);
937 return *this;
938 }
939#endif
940
942 VtValue &operator=(char const *cstr) {
943 std::string tmp(cstr);
944 _Clear();
945 _Init(tmp);
946 return *this;
947 }
948
950 VtValue &operator=(char *cstr) {
951 return *this = const_cast<char const *>(cstr);
952 }
953
955 VtValue &Swap(VtValue &rhs) noexcept {
956 // Do nothing if both empty. Otherwise general swap.
957 if (!IsEmpty() || !rhs.IsEmpty()) {
958 VtValue tmp;
959 _Move(*this, tmp);
960 _Move(rhs, *this);
961 _Move(tmp, rhs);
962 }
963 return *this;
964 }
965
967 friend void swap(VtValue &lhs, VtValue &rhs) { lhs.Swap(rhs); }
968
970 // make an unqualified call to swap(<held-value>, rhs). If this value is
971 // not holding a T, replace the held value with a value-initialized T
972 // instance first, then swap.
973#ifdef doxygen
974 template <class T>
975 void
976 Swap(T &rhs);
977#else
978 template <class T>
979 std::enable_if_t<
980 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
981 Swap(T &rhs) {
982 if (!IsHolding<T>())
983 *this = T();
984 UncheckedSwap(rhs);
985 }
986#endif
987
992#ifdef doxygen
993 template <class T>
994 void
996#else
997 template <class T>
998 std::enable_if_t<
999 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
1000 UncheckedSwap(T &rhs) {
1001 using std::swap;
1002 swap(_GetMutable<T>(), rhs);
1003 }
1004#endif
1005
1007 void UncheckedSwap(VtValue &rhs) { Swap(rhs); }
1008
1012 template <class T>
1014 T result;
1015 Swap(result);
1016 _Clear();
1017 return result;
1018 }
1019
1023 template <class T>
1025 T result;
1026 UncheckedSwap(result);
1027 _Clear();
1028 return result;
1029 }
1030
1034 template <class T, class Fn>
1035 std::enable_if_t<
1036 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value, bool>
1037 Mutate(Fn &&mutateFn) {
1038 if (!IsHolding<T>()) {
1039 return false;
1040 }
1041 UncheckedMutate<T>(std::forward<Fn>(mutateFn));
1042 return true;
1043 }
1044
1048 template <class T, class Fn>
1049 std::enable_if_t<
1050 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
1051 UncheckedMutate(Fn &&mutateFn) {
1052 // We move to a temporary, mutate the temporary, then move back. This
1053 // prevents callers from escaping a mutable reference to the held object
1054 // via a side-effect of mutateFn.
1055 T &stored =_GetMutable<T>();
1056 T tmp = std::move(stored);
1057 std::forward<Fn>(mutateFn)(tmp);
1058 stored = std::move(tmp);
1059 }
1060
1063 template <class T>
1064 bool IsHolding() const {
1065 return _info.GetLiteral() && _TypeIs<T>();
1066 }
1067
1069 VT_API bool IsArrayValued() const;
1070
1073 size_t GetArraySize() const { return _GetNumElements(); }
1074
1076 VT_API std::type_info const &GetTypeid() const;
1077
1080 VT_API std::type_info const &GetElementTypeid() const;
1081
1083 VT_API TfType GetType() const;
1084
1086 VT_API std::string GetTypeName() const;
1087
1093 if (ARCH_UNLIKELY(_IsProxy())) {
1094 return _info->GetProxiedAsVtValue(
1095 _storage).GetKnownValueTypeIndex();
1096 }
1097 return _info.GetLiteral() ? _info->knownTypeIndex : -1;
1098 }
1099
1103 template <class T>
1104 T const &UncheckedGet() const & { return _Get<T>(); }
1105
1109 template <class T>
1110 T UncheckedGet() && { return UncheckedRemove<T>(); }
1111
1120 template <class T>
1121 T const &Get() const & {
1122 typedef Vt_DefaultValueFactory<T> Factory;
1123
1124 // In the unlikely case that the types don't match, we obtain a default
1125 // value to return and issue an error via _FailGet.
1126 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1127 return *(static_cast<T const *>(
1128 _FailGet(Factory::Invoke, typeid(T))));
1129 }
1130
1131 return _Get<T>();
1132 }
1133
1137 template <class T>
1138 T Get() && {
1139 typedef Vt_DefaultValueFactory<T> Factory;
1140
1141 // In the unlikely case that the types don't match, we obtain a default
1142 // value to return and issue an error via _FailGet.
1143 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1144 return *(static_cast<T const *>(
1145 _FailGet(Factory::Invoke, typeid(T))));
1146 }
1147
1148 return UncheckedRemove<T>();
1149 }
1150
1155 template <class T>
1156 T GetWithDefault(T const &def = T()) const {
1157 return IsHolding<T>() ? UncheckedGet<T>() : def;
1158 }
1159
1161 template <typename From, typename To>
1162 static void RegisterCast(VtValue (*castFn)(VtValue const &)) {
1163 _RegisterCast(typeid(From), typeid(To), castFn);
1164 }
1165
1167 // holding To.
1168 template <typename From, typename To>
1169 static void RegisterSimpleCast() {
1170 _RegisterCast(typeid(From), typeid(To), _SimpleCast<From, To>);
1171 }
1172
1175 template <typename From, typename To>
1177 RegisterSimpleCast<From, To>();
1178 RegisterSimpleCast<To, From>();
1179 }
1180
1188 template <typename T>
1189 static VtValue Cast(VtValue const &val) {
1190 VtValue ret = val;
1191 ret.Cast<T>();
1192 return ret;
1193 }
1194
1202 VT_API static VtValue
1203 CastToTypeOf(VtValue const &val, VtValue const &other);
1204
1212 VT_API static VtValue
1213 CastToTypeid(VtValue const &val, std::type_info const &type);
1214
1218 static bool CanCastFromTypeidToTypeid(std::type_info const &from,
1219 std::type_info const &to) {
1220 return _CanCast(from, to);
1221 }
1222
1230 template <typename T>
1232 if (IsHolding<T>())
1233 return *this;
1234 return *this = _PerformCast(typeid(T), *this);
1235 }
1236
1245 return CastToTypeid(other.GetTypeid());
1246 }
1247
1255 VtValue &CastToTypeid(std::type_info const &type) {
1256 if (!TfSafeTypeCompare(GetTypeid(), type)) {
1257 *this = _PerformCast(type, *this);
1258 }
1259 return *this;
1260 }
1261
1265 template <typename T>
1266 bool CanCast() const {
1267 return _CanCast(GetTypeid(), typeid(T));
1268 }
1269
1273 bool CanCastToTypeOf(VtValue const &other) const {
1274 return _CanCast(GetTypeid(), other.GetTypeid());
1275 }
1276
1280 bool CanCastToTypeid(std::type_info const &type) const {
1281 return _CanCast(GetTypeid(), type);
1282 }
1283
1285 bool IsEmpty() const { return _info.GetLiteral() == 0; }
1286
1288 VT_API bool CanHash() const;
1289
1291 VT_API size_t GetHash() const;
1292
1293 friend inline size_t hash_value(VtValue const &val) {
1294 return val.GetHash();
1295 }
1296
1298 template <typename T>
1299 friend bool operator == (VtValue const &lhs, T const &rhs) {
1300 typedef typename Vt_ValueGetStored<T>::Type Stored;
1301 return lhs.IsHolding<Stored>() && lhs.UncheckedGet<Stored>() == rhs;
1302 }
1303 template <typename T>
1304 friend bool operator == (T const &lhs, VtValue const &rhs) {
1305 return rhs == lhs;
1306 }
1307
1309 template <typename T>
1310 friend bool operator != (VtValue const &lhs, T const &rhs) {
1311 return !(lhs == rhs);
1312 }
1313 template <typename T>
1314 friend bool operator != (T const &lhs, VtValue const &rhs) {
1315 return !(lhs == rhs);
1316 }
1317
1319 bool operator == (const VtValue &rhs) const {
1320 bool empty = IsEmpty(), rhsEmpty = rhs.IsEmpty();
1321 if (empty || rhsEmpty) {
1322 // Either one or both empty -- only equal if both empty.
1323 return empty == rhsEmpty;
1324 }
1325 if (_info.GetLiteral() == rhs._info.GetLiteral()) {
1326 // Holding identical types -- compare directly.
1327 return _info.Get()->Equal(_storage, rhs._storage);
1328 }
1329 return _EqualityImpl(rhs);
1330 }
1331 bool operator != (const VtValue &rhs) const { return !(*this == rhs); }
1332
1334 VT_API friend std::ostream &
1335 operator << (std::ostream &out, const VtValue &self);
1336
1337private:
1338 VT_API const Vt_ShapeData* _GetShapeData() const;
1339 VT_API size_t _GetNumElements() const;
1340 friend struct Vt_ValueShapeDataAccess;
1341
1342 static inline void _Copy(VtValue const &src, VtValue &dst) {
1343 if (src.IsEmpty()) {
1344 dst._Clear();
1345 return;
1346 }
1347
1348 _HoldAside tmp(&dst);
1349 dst._info = src._info;
1350 if (src._IsLocalAndTriviallyCopyable()) {
1351 dst._storage = src._storage;
1352 } else {
1353 dst._info->CopyInit(src._storage, dst._storage);
1354 }
1355 }
1356
1357 static inline void _Move(VtValue &src, VtValue &dst) noexcept {
1358 if (src.IsEmpty()) {
1359 dst._Clear();
1360 return;
1361 }
1362
1363 _HoldAside tmp(&dst);
1364 dst._info = src._info;
1365 if (src._IsLocalAndTriviallyCopyable()) {
1366 dst._storage = src._storage;
1367 } else {
1368 dst._info->Move(src._storage, dst._storage);
1369 }
1370
1371 src._info.Set(nullptr, 0);
1372 }
1373
1374 template <class T>
1375 inline bool
1376 _TypeIs() const {
1377 if constexpr (VtIsKnownValueType_Workaround<T>::value) {
1378 return _info->knownTypeIndex == VtGetKnownValueTypeIndex<T>() ||
1379 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(typeid(T)));
1380 } else {
1381 std::type_info const &t = typeid(T);
1382 return TfSafeTypeCompare(_info->typeInfo, t) ||
1383 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(t));
1384 }
1385 }
1386
1387 VT_API bool _TypeIsImpl(std::type_info const &queriedType) const;
1388
1389 VT_API bool _EqualityImpl(VtValue const &rhs) const;
1390
1391 template <class Proxy>
1392 std::enable_if_t<VtIsValueProxy<Proxy>::value, Proxy &>
1393 _GetMutable() {
1394 typedef typename _TypeInfoFor<Proxy>::Type TypeInfo;
1395 return TypeInfo::GetMutableObj(_storage);
1396 }
1397
1398 template <class T>
1399 std::enable_if_t<!VtIsValueProxy<T>::value, T &>
1400 _GetMutable() {
1401 // If we are a proxy, collapse it out to the real value first.
1402 if (ARCH_UNLIKELY(_IsProxy())) {
1403 *this = _info->GetProxiedAsVtValue(_storage);
1404 }
1405 typedef typename _TypeInfoFor<T>::Type TypeInfo;
1406 return TypeInfo::GetMutableObj(_storage);
1407 }
1408
1409 template <class Proxy>
1410 std::enable_if_t<VtIsValueProxy<Proxy>::value, Proxy const &>
1411 _Get() const {
1412 typedef typename _TypeInfoFor<Proxy>::Type TypeInfo;
1413 return TypeInfo::GetObj(_storage);
1414 }
1415
1416 template <class T>
1417 std::enable_if_t<!VtIsValueProxy<T>::value, T const &>
1418 _Get() const {
1419 typedef typename _TypeInfoFor<T>::Type TypeInfo;
1420 if (ARCH_UNLIKELY(_IsProxy())) {
1421 return *static_cast<T const *>(_GetProxiedObjPtr());
1422 }
1423 return TypeInfo::GetObj(_storage);
1424 }
1425
1426 void const *_GetProxiedObjPtr() const {
1427 return _info->GetProxiedObjPtr(_storage);
1428 }
1429
1430 // Helper invoked in case Get fails. Reports an error and returns a default
1431 // value for \a queryType.
1432 VT_API void const *
1433 _FailGet(Vt_DefaultValueHolder (*factory)(),
1434 std::type_info const &queryType) const;
1435
1436 inline void _Clear() {
1437 // optimize for local types not to deref _info.
1438ARCH_PRAGMA_PUSH
1439// XXX: http://bug/DEV-16695
1440ARCH_PRAGMA_MAYBE_UNINITIALIZED
1441 if (_info.GetLiteral() && !_IsLocalAndTriviallyCopyable())
1442 _info.Get()->Destroy(_storage);
1443ARCH_PRAGMA_POP
1444 _info.Set(nullptr, 0);
1445 }
1446
1447 inline bool _IsLocalAndTriviallyCopyable() const {
1448 unsigned int bits = _info.BitsAs<unsigned int>();
1449 return (bits & (_LocalFlag | _TrivialCopyFlag)) ==
1450 (_LocalFlag | _TrivialCopyFlag);
1451 }
1452
1453 inline bool _IsProxy() const {
1454 return _info.BitsAs<unsigned int>() & _ProxyFlag;
1455 }
1456
1457 VT_API static void _RegisterCast(std::type_info const &from,
1458 std::type_info const &to,
1459 VtValue (*castFn)(VtValue const &));
1460
1461 // Cast \p value to the type \p to. Caller must ensure that val's type is
1462 // not already \p to.
1463 VT_API static VtValue
1464 _PerformCast(std::type_info const &to, VtValue const &val);
1465
1466 // Return true if \p from == \p to or if there is a registered cast to
1467 // convert VtValues holding \p from to \p to.
1468 VT_API static bool
1469 _CanCast(std::type_info const &from, std::type_info const &to);
1470
1471 // helper template function for simple casts from From to To.
1472 template <typename From, typename To>
1473 static VtValue _SimpleCast(VtValue const &val) {
1474 return VtValue(To(val.UncheckedGet<From>()));
1475 }
1476
1477 // This grants friend access to a function in the wrapper file for this
1478 // class. This lets the wrapper reach down into a value to get a
1479 // pxr_boost::python wrapped object corresponding to the held type. This
1480 // facility is necessary to get the python API we want.
1481 friend TfPyObjWrapper
1482 Vt_GetPythonObjectFromHeldValue(VtValue const &self);
1483
1484 VT_API TfPyObjWrapper _GetPythonObject() const;
1485
1486 _Storage _storage;
1488};
1489
1490#ifndef doxygen
1491
1492struct Vt_ValueShapeDataAccess {
1493 static const Vt_ShapeData* _GetShapeData(const VtValue& value) {
1494 return value._GetShapeData();
1495 }
1496
1497 static size_t _GetNumElements(const VtValue& value) {
1498 return value._GetNumElements();
1499 }
1500};
1501
1505template <class T>
1506struct Vt_DefaultValueFactory {
1507 static Vt_DefaultValueHolder Invoke();
1508};
1509
1510template <class T>
1511inline Vt_DefaultValueHolder
1512Vt_DefaultValueFactory<T>::Invoke() {
1513 return Vt_DefaultValueHolder::Create<T>();
1514}
1515
1516// For performance reasons, the default constructors for vectors,
1517// matrices, and quaternions do *not* initialize the data of the
1518// object. This greatly improves the performance of creating large
1519// arrays of objects. However, for consistency and to avoid
1520// errors complaining about uninitialized values, we use VtZero
1521// to construct zeroed out vectors, matrices, and quaternions by
1522// explicitly instantiating the factory for these types.
1523//
1524#define _VT_DECLARE_ZERO_VALUE_FACTORY(unused, elem) \
1525template <> \
1526VT_API Vt_DefaultValueHolder Vt_DefaultValueFactory<VT_TYPE(elem)>::Invoke();
1527
1528TF_PP_SEQ_FOR_EACH(_VT_DECLARE_ZERO_VALUE_FACTORY, ~,
1529 VT_VEC_VALUE_TYPES
1530 VT_MATRIX_VALUE_TYPES
1531 VT_QUATERNION_VALUE_TYPES
1532 VT_DUALQUATERNION_VALUE_TYPES)
1533
1534#undef _VT_DECLARE_ZERO_VALUE_FACTORY
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
1549VtValue::Get<VtValue>() && {
1550 return std::move(*this);
1551}
1552
1553template <>
1554inline const VtValue&
1555VtValue::UncheckedGet<VtValue>() const & {
1556 return *this;
1557}
1558
1559template <>
1560inline VtValue
1561VtValue::UncheckedGet<VtValue>() && {
1562 return std::move(*this);
1563}
1564
1565template <>
1566inline bool
1567VtValue::IsHolding<VtValue>() const {
1568 return true;
1569}
1570
1571// Specialize VtValue::IsHolding<void>() to always return false.
1572template <>
1573inline bool
1574VtValue::IsHolding<void>() const {
1575 return false;
1576}
1577
1578
1579
1580#endif // !doxygen
1581
1582PXR_NAMESPACE_CLOSE_SCOPE
1583
1584#endif // PXR_BASE_VT_VALUE_H
Defines all the types "TYPED" for which Vt creates a VtTYPEDArray typedef.
A simple type-erased container that provides only destruction, moves and immutable,...
Definition: anyUniquePtr.h:27
Stores a pointer to a ValueType which uses TfDelegatedCountIncrement and TfDelegatedCountDecrement to...
This class stores a T * and a small integer in the space of a T *.
void Set(T *ptr) noexcept
Set the pointer value to ptr.
constexpr uintptr_t GetLiteral() const noexcept
Retrieve the raw underlying value.
constexpr T * Get() const noexcept
Retrieve the pointer.
constexpr Integral BitsAs() const noexcept
Retrieve the stored bits as the integral type Integral.
Convenience class for accessing the Python Global Interpreter Lock.
Definition: pyLock.h:105
Boost Python object wrapper.
Definition: pyObjWrapper.h:79
TfType represents a dynamic runtime type.
Definition: type.h:48
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:147
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:1280
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition: value.h:1024
friend bool operator==(VtValue const &lhs, T const &rhs)
Tests for equality.
Definition: value.h:1299
int GetKnownValueTypeIndex() const
Return VtKnownValueTypeIndex<T> for the held type T.
Definition: value.h:1092
T UncheckedGet() &&
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: value.h:1110
static VT_API VtValue CastToTypeOf(VtValue const &val, VtValue const &other)
Return a VtValue holding val cast to same type that other is holding.
T Remove()
Make this value empty and return the held T instance.
Definition: value.h:1013
static VtValue Take(T &obj)
Create a new VtValue, taking its contents from obj.
Definition: value.h:886
static void RegisterSimpleCast()
Register a simple cast from VtValue holding From to VtValue.
Definition: value.h:1169
VtValue & Cast()
Return this holding value type cast to T.
Definition: value.h:1231
VtValue & CastToTypeOf(VtValue const &other)
Return this holding value type cast to same type that other is holding.
Definition: value.h:1244
static void RegisterSimpleBidirectionalCast()
Register a two-way cast from VtValue holding From to VtValue holding To.
Definition: value.h:1176
VtValue(VtValue const &other)
Copy construct with other.
Definition: value.h:847
static void RegisterCast(VtValue(*castFn)(VtValue const &))
Register a cast from VtValue holding From to VtValue holding To.
Definition: value.h:1162
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:1138
VtValue & operator=(char *cstr)
Assigning a char * gives a VtValue holding a std::string.
Definition: value.h:950
bool CanCastToTypeOf(VtValue const &other) const
Return if this can be cast to type.
Definition: value.h:1273
std::enable_if_t< std::is_same< T, typename Vt_ValueGetStored< T >::Type >::value > UncheckedMutate(Fn &&mutateFn)
Invoke mutateFn, it a non-const reference to the held object which must be of type T.
Definition: value.h:1051
VtValue & operator=(char const *cstr)
Assigning a char const * gives a VtValue holding a std::string.
Definition: value.h:942
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:1156
void UncheckedSwap(T &rhs)
Swap the held value with rhs.
void UncheckedSwap(VtValue &rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: value.h:1007
std::enable_if_t< std::is_same< T, typename Vt_ValueGetStored< T >::Type >::value, 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:1037
VT_API bool IsArrayValued() const
Returns true iff this is holding an array type (see VtIsArray<>).
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1285
VtValue & operator=(VtValue &&other) noexcept
Move assignment from another VtValue.
Definition: value.h:903
VtValue & CastToTypeid(std::type_info const &type)
Return this holding value type cast to type.
Definition: value.h:1255
VT_API TfType GetType() const
Returns the TfType of the type held by this value.
~VtValue()
Destructor.
Definition: value.h:893
VT_API std::type_info const & GetElementTypeid() const
Return the typeid of elements in a array valued type.
VtValue & operator=(T const &obj)
Assignment operator from any type.
VtValue(T const &obj)
Construct a VtValue holding a copy of obj.
Definition: value.h:862
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:955
friend void swap(VtValue &lhs, VtValue &rhs)
Overloaded swap() for generic code/stl/etc.
Definition: value.h:967
static VtValue Cast(VtValue const &val)
Return a VtValue holding val cast to hold T.
Definition: value.h:1189
bool CanCast() const
Return if this can be cast to T.
Definition: value.h:1266
T const & Get() const &
Returns a const reference to the held object if the held object is of type T.
Definition: value.h:1121
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:844
friend bool operator!=(VtValue const &lhs, T const &rhs)
Tests for inequality.
Definition: value.h:1310
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:1218
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
Definition: value.h:1064
VtValue(VtValue &&other) noexcept
Move construct with other.
Definition: value.h:852
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:1104
VtValue & operator=(VtValue const &other)
Copy assignment from another VtValue.
Definition: value.h:896
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. If this value is holding a T,.
VT_API std::type_info const & GetTypeid() const
Returns the typeid of the type held by this value.
Demangle C++ typenames generated by the typeid() facility.
Compiler hints.
STL namespace.
Pragmas for controlling compiler-specific behaviors.
Safely compare C++ RTTI type structures.
bool TfSafeTypeCompare(const std::type_info &t1, const std::type_info &t2)
Safely compare std::type_info structures.
Definitions of basic string utilities in tf.
Array concept. By default, types are not arrays.
Definition: traits.h:22
A file containing basic constants and definitions.