HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
value.h
Go to the documentation of this file.
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.
15 
16 #include "pxr/base/tf/pyLock.h"
17 
18 #include "pxr/base/arch/demangle.h"
19 #include "pxr/base/arch/hints.h"
20 #include "pxr/base/arch/pragmas.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 
41 
42 /// Make a default value.
43 /// VtValue uses this to create values to be returned from failed calls to \a
44 /// Get. Clients may specialize this for their own types.
45 template <class T>
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.
51 {
52  // Creates a value-initialized object and stores the type_info for the
53  // static type.
54  template <typename T>
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 
77 private:
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 
85 class VtValue;
86 
87 // Overload VtStreamOut for vector<VtValue>. Produces output like [value1,
88 // value2, ... valueN].
89 VT_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 
94 template <class T> struct Vt_ValueStoredType { typedef T Type; };
95 VT_VALUE_SET_STORED_TYPE(char const *, std::string);
96 VT_VALUE_SET_STORED_TYPE(char *, std::string);
97 
98 #ifdef PXR_PYTHON_SUPPORT_ENABLED
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.
105 template <class T>
107  : Vt_ValueStoredType<std::decay_t<T>> {};
108 
109 /// Provides a container which may hold any type, and provides introspection
110 /// and iteration over array types. See \a VtIsArray for more info.
111 ///
112 /// \section VtValue_Casting Held-type Conversion with VtValue::Cast
113 ///
114 /// VtValue provides a suite of "Cast" methods that convert or create a
115 /// VtValue holding a requested type (via template parameter, typeid, or
116 /// type-matching to another VtValue) from the type of the currently-held
117 /// value. Clients can add conversions between their own types using the
118 /// RegisterCast(), RegisterSimpleCast(), and
119 /// RegisterSimpleBidirectionalCast() methods. Conversions from plugins can
120 /// be guaranteed to be registered before they are needed by registering them
121 /// from within a
122 /// \code
123 /// TF_REGISTRY_FUNCTION(VtValue) {
124 /// }
125 /// \endcode
126 /// block.
127 ///
128 /// \subsection VtValue_builtin_conversions Builtin Type Conversion
129 ///
130 /// Conversions between most of the basic "value types" that are intrinsically
131 /// convertible are builtin, including all numeric types (including Gf's \c
132 /// half), std::string/TfToken, GfVec* (for vecs of the same dimension), and
133 /// VtArray<T> for floating-point POD and GfVec of the preceding.
134 ///
135 /// \subsection VtValue_numeric_conversion Numeric Conversion Safety
136 ///
137 /// The conversions between all scalar numeric types are performed with range
138 /// checks such as provided by boost::numeric_cast(), and will fail, returning
139 /// an empty VtValue if the source value is out of range of the destination
140 /// type.
141 ///
142 /// Conversions between GfVec and other compound-numeric types provide no more
143 /// or less safety or checking than the conversion constructors of the types
144 /// themselves. This includes VtArray, even VtArray<T> for T in scalar types
145 /// that are range-checked when held singly.
146 class VtValue
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)) &&
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;
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 
598  ////////////////////////////////////////////////////////////////////
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 
616  ////////////////////////////////////////////////////////////////////
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 
713  ////////////////////////////////////////////////////////////////////
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 
726  ////////////////////////////////////////////////////////////////////////
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 
747  ////////////////////////////////////////////////////////////////////////
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 
762  using Ptr = TfDelegatedCountPtr<_Counted<T>>;
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>;
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);
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>
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>
837  _Init(T const &obj) {
838  _Init(typename Vt_ValueGetStored<T>::Type(obj));
839  }
840 
841 public:
842 
843  /// Default ctor gives empty VtValue.
844  VtValue() {}
845 
846  /// Copy construct with \p other.
847  VtValue(VtValue const &other) {
848  _Copy(other, *this);
849  }
850 
851  /// Move construct with \p other.
852  VtValue(VtValue &&other) noexcept {
853  _Move(other, *this);
854  }
855 
856  /// Construct a VtValue holding a copy of \p obj.
857  ///
858  /// If T is a char pointer or array, produce a VtValue holding a
859  /// std::string. If T is pxr_boost::python::object, produce a VtValue holding
860  /// a TfPyObjWrapper.
861  template <class T>
862  explicit VtValue(T const &obj) {
863  _Init(obj);
864  }
865 
866  /// Create a new VtValue, taking its contents from \p obj.
867  ///
868  /// This is equivalent to creating a VtValue holding a value-initialized
869  /// \p T instance, then invoking swap(<held-value>, obj), leaving obj in a
870  /// default-constructed (value-initialized) state. In the case that \p
871  /// obj is expensive to copy, it may be significantly faster to use this
872  /// idiom when \p obj need not retain its contents:
873  ///
874  /// \code
875  /// MyExpensiveObject obj = CreateObject();
876  /// return VtValue::Take(obj);
877  /// \endcode
878  ///
879  /// Rather than:
880  ///
881  /// \code
882  /// MyExpensiveObject obj = CreateObject();
883  /// return VtValue(obj);
884  /// \endcode
885  template <class T>
886  static VtValue Take(T &obj) {
887  VtValue ret;
888  ret.Swap(obj);
889  return ret;
890  }
891 
892  /// Destructor.
893  ~VtValue() { _Clear(); }
894 
895  /// Copy assignment from another \a VtValue.
896  VtValue &operator=(VtValue const &other) {
897  if (ARCH_LIKELY(this != &other))
898  _Copy(other, *this);
899  return *this;
900  }
901 
902  /// Move assignment from another \a VtValue.
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
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 
923  /// Assignment operator from any type.
924 #ifdef doxygen
925  template <class T>
926  VtValue&
927  operator=(T const &obj);
928 #else
929  template <class 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 
941  /// Assigning a char const * gives a VtValue holding a std::string.
942  VtValue &operator=(char const *cstr) {
943  std::string tmp(cstr);
944  _Clear();
945  _Init(tmp);
946  return *this;
947  }
948 
949  /// Assigning a char * gives a VtValue holding a std::string.
950  VtValue &operator=(char *cstr) {
951  return *this = const_cast<char const *>(cstr);
952  }
953 
954  /// Swap this with \a rhs.
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 
966  /// Overloaded swap() for generic code/stl/etc.
967  friend void swap(VtValue &lhs, VtValue &rhs) { lhs.Swap(rhs); }
968 
969  /// Swap the held value with \a rhs. If this value is holding a T,
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>
981  Swap(T &rhs) {
982  if (!IsHolding<T>())
983  *this = T();
984  UncheckedSwap(rhs);
985  }
986 #endif
987 
988  /// Swap the held value with \a rhs. This VtValue must be holding an
989  /// object of type \p T. If it does not, this invokes undefined behavior.
990  /// Use Swap() if this VtValue is not known to contain an object of type
991  /// \p T.
992 #ifdef doxygen
993  template <class T>
994  void
995  UncheckedSwap(T &rhs);
996 #else
997  template <class T>
1001  using std::swap;
1002  swap(_GetMutable<T>(), rhs);
1003  }
1004 #endif
1005 
1006  /// \overload
1007  void UncheckedSwap(VtValue &rhs) { Swap(rhs); }
1008 
1009  /// Make this value empty and return the held \p T instance. If
1010  /// this value does not hold a \p T instance, make this value empty and
1011  /// return a default-constructed \p T.
1012  template <class T>
1013  T Remove() {
1014  T result;
1015  Swap(result);
1016  _Clear();
1017  return result;
1018  }
1019 
1020  /// Make this value empty and return the held \p T instance. If this
1021  /// value does not hold a \p T instance, this method invokes undefined
1022  /// behavior.
1023  template <class T>
1025  T result;
1026  UncheckedSwap(result);
1027  _Clear();
1028  return result;
1029  }
1030 
1031  /// If this value holds an object of type \p T, invoke \p mutateFn, passing
1032  /// it a non-const reference to the held object and return true. Otherwise
1033  /// do nothing and return false.
1034  template <class T, class Fn>
1037  Mutate(Fn &&mutateFn) {
1038  if (!IsHolding<T>()) {
1039  return false;
1040  }
1041  UncheckedMutate<T>(std::forward<Fn>(mutateFn));
1042  return true;
1043  }
1044 
1045  /// Invoke \p mutateFn, it a non-const reference to the held object which
1046  /// must be of type \p T. If the held object is not of type \p T, this
1047  /// function invokes undefined behavior.
1048  template <class T, class Fn>
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 
1061  /// Return true if this value is holding an object of type \p T, false
1062  /// otherwise.
1063  template <class T>
1064  bool IsHolding() const {
1065  return _info.GetLiteral() && _TypeIs<T>();
1066  }
1067 
1068  /// Returns true iff this is holding an array type (see VtIsArray<>).
1069  VT_API bool IsArrayValued() const;
1070 
1071  /// Return the number of elements in the held value if IsArrayValued(),
1072  /// return 0 otherwise.
1073  size_t GetArraySize() const { return _GetNumElements(); }
1074 
1075  /// Returns the typeid of the type held by this value.
1076  VT_API std::type_info const &GetTypeid() const;
1077 
1078  /// Return the typeid of elements in a array valued type. If not
1079  /// holding an array valued type, return typeid(void).
1080  VT_API std::type_info const &GetElementTypeid() const;
1081 
1082  /// Returns the TfType of the type held by this value.
1083  VT_API TfType GetType() const;
1084 
1085  /// Return the type name of the held typeid.
1086  VT_API std::string GetTypeName() const;
1087 
1088  /// Return VtKnownValueTypeIndex<T> for the held type T. If this value
1089  /// holds a proxy type, resolve the proxy and return the proxied type's
1090  /// index. If this value is empty or holds a type that is not 'known',
1091  /// return -1.
1093  if (ARCH_UNLIKELY(_IsProxy())) {
1094  return _info->GetProxiedAsVtValue(
1095  _storage).GetKnownValueTypeIndex();
1096  }
1097  return _info.GetLiteral() ? _info->knownTypeIndex : -1;
1098  }
1099 
1100  /// Returns a const reference to the held object if the held object
1101  /// is of type \a T. Invokes undefined behavior otherwise. This is the
1102  /// fastest \a Get() method to use after a successful \a IsHolding() check.
1103  template <class T>
1104  T const &UncheckedGet() const & { return _Get<T>(); }
1105 
1106  /// \overload
1107  /// In case *this is an rvalue, move the held value out and return
1108  /// by value.
1109  template <class T>
1110  T UncheckedGet() && { return UncheckedRemove<T>(); }
1111 
1112  /// Returns a const reference to the held object if the held object
1113  /// is of type \a T. Issues an error and returns a const reference to a
1114  /// default value if the held object is not of type \a T. Use \a IsHolding
1115  /// to verify correct type before calling this function. The default value
1116  /// returned in case of type mismatch is constructed using
1117  /// Vt_DefaultValueFactory<T>. That may be specialized for client types.
1118  /// The default implementation of the default value factory produces a
1119  /// value-initialized T.
1120  template <class T>
1121  T const &Get() const & {
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 
1134  /// \overload
1135  /// In case *this is an rvalue, move the held value out and return
1136  /// by value.
1137  template <class T>
1138  T Get() && {
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 
1151  /// Return a copy of the held object if the held object is of type T.
1152  /// Return a copy of the default value \a def otherwise. Note that this
1153  /// always returns a copy, as opposed to \a Get() which always returns a
1154  /// reference.
1155  template <class T>
1156  T GetWithDefault(T const &def = T()) const {
1157  return IsHolding<T>() ? UncheckedGet<T>() : def;
1158  }
1159 
1160  /// Register a cast from VtValue holding From to VtValue holding To.
1161  template <typename From, typename To>
1162  static void RegisterCast(VtValue (*castFn)(VtValue const &)) {
1163  _RegisterCast(typeid(From), typeid(To), castFn);
1164  }
1165 
1166  /// Register a simple cast from VtValue holding From to VtValue
1167  // holding To.
1168  template <typename From, typename To>
1169  static void RegisterSimpleCast() {
1170  _RegisterCast(typeid(From), typeid(To), _SimpleCast<From, To>);
1171  }
1172 
1173  /// Register a two-way cast from VtValue holding From to VtValue
1174  /// holding To.
1175  template <typename From, typename To>
1177  RegisterSimpleCast<From, To>();
1178  RegisterSimpleCast<To, From>();
1179  }
1180 
1181  /// Return a VtValue holding \c val cast to hold T. Return empty VtValue
1182  /// if cast fails.
1183  ///
1184  /// This Cast() function is safe to call in multiple threads as it does
1185  /// not mutate the operant \p val.
1186  ///
1187  /// \sa \ref VtValue_Casting
1188  template <typename T>
1189  static VtValue Cast(VtValue const &val) {
1190  VtValue ret = val;
1191  ret.Cast<T>();
1192  return ret;
1193  }
1194 
1195  /// Return a VtValue holding \c val cast to same type that \c other is
1196  /// holding. Return empty VtValue if cast fails.
1197  ///
1198  /// This Cast() function is safe to call in multiple threads as it does not
1199  /// mutate the operant \p val.
1200  ///
1201  /// \sa \ref VtValue_Casting
1202  VT_API static VtValue
1203  CastToTypeOf(VtValue const &val, VtValue const &other);
1204 
1205  /// Return a VtValue holding \a val cast to \a type. Return empty VtValue
1206  /// if cast fails.
1207  ///
1208  /// This Cast() function is safe to call in multiple threads as it does not
1209  /// mutate the operant \p val.
1210  ///
1211  /// \sa \ref VtValue_Casting
1212  VT_API static VtValue
1213  CastToTypeid(VtValue const &val, std::type_info const &type);
1214 
1215  /// Return if a value of type \a from can be cast to type \a to.
1216  ///
1217  /// \sa \ref VtValue_Casting
1218  static bool CanCastFromTypeidToTypeid(std::type_info const &from,
1219  std::type_info const &to) {
1220  return _CanCast(from, to);
1221  }
1222 
1223  /// Return \c this holding value type cast to T. This value is left
1224  /// empty if the cast fails.
1225  ///
1226  /// \note Since this method mutates this value, it is not safe to invoke on
1227  /// the same VtValue in multiple threads simultaneously.
1228  ///
1229  /// \sa \ref VtValue_Casting
1230  template <typename T>
1232  if (IsHolding<T>())
1233  return *this;
1234  return *this = _PerformCast(typeid(T), *this);
1235  }
1236 
1237  /// Return \c this holding value type cast to same type that
1238  /// \c other is holding. This value is left empty if the cast fails.
1239  ///
1240  /// \note Since this method mutates this value, it is not safe to invoke on
1241  /// the same VtValue in multiple threads simultaneously.
1242  ///
1243  /// \sa \ref VtValue_Casting
1244  VtValue &CastToTypeOf(VtValue const &other) {
1245  return CastToTypeid(other.GetTypeid());
1246  }
1247 
1248  /// Return \c this holding value type cast to \a type. This value is
1249  /// left empty if the cast fails.
1250  ///
1251  /// \note Since this method mutates this value, it is not safe to invoke on
1252  /// the same VtValue in multiple threads simultaneously.
1253  ///
1254  /// \sa \ref VtValue_Casting
1255  VtValue &CastToTypeid(std::type_info const &type) {
1256  if (!TfSafeTypeCompare(GetTypeid(), type)) {
1257  *this = _PerformCast(type, *this);
1258  }
1259  return *this;
1260  }
1261 
1262  /// Return if \c this can be cast to \a T.
1263  ///
1264  /// \sa \ref VtValue_Casting
1265  template <typename T>
1266  bool CanCast() const {
1267  return _CanCast(GetTypeid(), typeid(T));
1268  }
1269 
1270  /// Return if \c this can be cast to \a type.
1271  ///
1272  /// \sa \ref VtValue_Casting
1273  bool CanCastToTypeOf(VtValue const &other) const {
1274  return _CanCast(GetTypeid(), other.GetTypeid());
1275  }
1276 
1277  /// Return if \c this can be cast to \a type.
1278  ///
1279  /// \sa \ref VtValue_Casting
1280  bool CanCastToTypeid(std::type_info const &type) const {
1281  return _CanCast(GetTypeid(), type);
1282  }
1283 
1284  /// Returns true iff this value is empty.
1285  bool IsEmpty() const { return _info.GetLiteral() == 0; }
1286 
1287  /// Return true if the held object provides a hash implementation.
1288  VT_API bool CanHash() const;
1289 
1290  /// Return a hash code for the held object by calling VtHashValue() on it.
1291  VT_API size_t GetHash() const;
1292 
1293  friend inline size_t hash_value(VtValue const &val) {
1294  return val.GetHash();
1295  }
1296 
1297  /// Tests for equality.
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 
1308  /// Tests for inequality.
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 
1318  /// Test two values for equality.
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 
1333  /// Calls through to operator << on the held object.
1334  VT_API friend std::ostream &
1335  operator << (std::ostream &out, const VtValue &self);
1336 
1337 private:
1338  VT_API const Vt_ShapeData* _GetShapeData() const;
1339  VT_API size_t _GetNumElements() const;
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 {
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>
1393  _GetMutable() {
1394  typedef typename _TypeInfoFor<Proxy>::Type TypeInfo;
1395  return TypeInfo::GetMutableObj(_storage);
1396  }
1397 
1398  template <class 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>
1411  _Get() const {
1412  typedef typename _TypeInfoFor<Proxy>::Type TypeInfo;
1413  return TypeInfo::GetObj(_storage);
1414  }
1415 
1416  template <class T>
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.
1439 // XXX: http://bug/DEV-16695
1441  if (_info.GetLiteral() && !_IsLocalAndTriviallyCopyable())
1442  _info.Get()->Destroy(_storage);
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
1483 
1484  VT_API TfPyObjWrapper _GetPythonObject() const;
1485 
1486  _Storage _storage;
1488 };
1489 
1490 #ifndef doxygen
1491 
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 
1502 /// Make a default value. VtValue uses this to create values to be returned
1503 /// from failed calls to \a Get. Clients may specialize this for their own
1504 /// types.
1505 template <class T>
1506 struct Vt_DefaultValueFactory {
1507  static Vt_DefaultValueHolder Invoke();
1508 };
1509 
1510 template <class T>
1511 inline Vt_DefaultValueHolder
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) \
1525 template <> \
1526 VT_API Vt_DefaultValueHolder Vt_DefaultValueFactory<VT_TYPE(elem)>::Invoke();
1527 
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 
1541 template <>
1542 inline const VtValue&
1543 VtValue::Get<VtValue>() const & {
1544  return *this;
1545 }
1546 
1547 template <>
1548 inline VtValue
1549 VtValue::Get<VtValue>() && {
1550  return std::move(*this);
1551 }
1552 
1553 template <>
1554 inline const VtValue&
1555 VtValue::UncheckedGet<VtValue>() const & {
1556  return *this;
1557 }
1558 
1559 template <>
1560 inline VtValue
1561 VtValue::UncheckedGet<VtValue>() && {
1562  return std::move(*this);
1563 }
1564 
1565 template <>
1566 inline bool
1567 VtValue::IsHolding<VtValue>() const {
1568  return true;
1569 }
1570 
1571 // Specialize VtValue::IsHolding<void>() to always return false.
1572 template <>
1573 inline bool
1574 VtValue::IsHolding<void>() const {
1575  return false;
1576 }
1577 
1578 
1579 
1580 #endif // !doxygen
1581 
1583 
1584 #endif // PXR_BASE_VT_VALUE_H
#define ARCH_LIKELY(x)
Definition: hints.h:29
GLenum query
Definition: glad.h:2772
~VtValue()
Destructor.
Definition: value.h:893
bool CanCast() const
Definition: value.h:1266
typename std::enable_if< B, T >::type enable_if_t
Define Imath::enable_if_t to be std for C++14, equivalent for C++11.
GLbitfield flags
Definition: glcorearb.h:1596
VtValue & Cast()
Definition: value.h:1231
static Vt_DefaultValueHolder Create(T const &val)
Definition: value.h:62
T const & UncheckedGet() const &
Definition: value.h:1104
STATIC_INLINE size_t Hash(const char *s, size_t len)
Definition: farmhash.h:2099
friend TfPyObjWrapper Vt_GetPythonObjectFromHeldValue(VtValue const &self)
static VtValue Take(T &obj)
Definition: value.h:886
void
Definition: png.h:1083
long size() const
Definition: ImfArray.h:90
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
Definition: UT_ArraySet.h:1699
VtValue & CastToTypeOf(VtValue const &other)
Definition: value.h:1244
static void RegisterCast(VtValue(*castFn)(VtValue const &))
Register a cast from VtValue holding From to VtValue holding To.
Definition: value.h:1162
GLsizei const GLfloat * value
Definition: glcorearb.h:824
static const Vt_ShapeData * _GetShapeData(const VtValue &value)
Definition: value.h:1493
VtValue & operator=(char const *cstr)
Assigning a char const * gives a VtValue holding a std::string.
Definition: value.h:942
#define ARCH_PRAGMA_POP
Definition: pragmas.h:159
VtValue(T const &obj)
Definition: value.h:862
T Get()&&
Definition: value.h:1138
std::enable_if_t< !_TypeInfoFor< T >::Type::IsLocal||!_TypeInfoFor< T >::Type::HasTrivialCopy, VtValue & > operator=(T const &obj)
Assignment operator from any type.
Definition: value.h:934
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
size_t GetArraySize() const
Definition: value.h:1073
#define VT_API
Definition: api.h:23
std::enable_if_t< std::is_same< T, typename Vt_ValueGetStored< T >::Type >::value > Swap(T &rhs)
Swap the held value with rhs. If this value is holding a T,.
Definition: value.h:981
IMATH_HOSTDEVICE constexpr bool equal(T1 a, T2 b, T3 t) IMATH_NOEXCEPT
Definition: ImathFun.h:105
VtValue & Swap(VtValue &rhs) noexcept
Swap this with rhs.
Definition: value.h:955
T Remove()
Definition: value.h:1013
**But if you need a result
Definition: thread.h:622
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1285
#define VT_DUALQUATERNION_VALUE_TYPES
Definition: types.h:114
friend struct _HoldAside
Definition: value.h:809
VtValue & operator=(char *cstr)
Assigning a char * gives a VtValue holding a std::string.
Definition: value.h:950
T const & VtGetProxiedObject(T const &nonProxy)
Definition: traits.h:101
static size_t _GetNumElements(const VtValue &value)
Definition: value.h:1497
VtValue(VtValue const &other)
Copy construct with other.
Definition: value.h:847
OutGridT const XformOp bool bool
constexpr T * Get() const noexcept
Retrieve the pointer.
bool CanCastToTypeOf(VtValue const &other) const
Definition: value.h:1273
static VT_API VtValue CastToTypeOf(VtValue const &val, VtValue const &other)
T const & Get() const &
Definition: value.h:1121
#define ARCH_UNLIKELY(x)
Definition: hints.h:30
int GetKnownValueTypeIndex() const
Definition: value.h:1092
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
constexpr uintptr_t GetLiteral() const noexcept
static VT_API VtValue CastToTypeid(VtValue const &val, std::type_info const &type)
std::enable_if_t< std::is_same< T, typename Vt_ValueGetStored< T >::Type >::value > UncheckedMutate(Fn &&mutateFn)
Definition: value.h:1051
VT_API bool IsArrayValued() const
Returns true iff this is holding an array type (see VtIsArray<>).
#define ARCH_PRAGMA_PUSH
Definition: pragmas.h:155
TF_PP_SEQ_FOR_EACH(_VT_DECLARE_ZERO_VALUE_FACTORY,~, VT_VEC_VALUE_TYPES VT_MATRIX_VALUE_TYPES VT_QUATERNION_VALUE_TYPES VT_DUALQUATERNION_VALUE_TYPES) template<> inline const VtValue &VtValue
Definition: value.h:1528
VT_API std::type_info const & GetElementTypeid() const
#define _VT_DECLARE_ZERO_VALUE_FACTORY(unused, elem)
Definition: value.h:1524
T UncheckedRemove()
Definition: value.h:1024
std::enable_if_t< _TypeInfoFor< T >::Type::IsLocal &&_TypeInfoFor< T >::Type::HasTrivialCopy, VtValue & > operator=(T obj)
Definition: value.h:916
friend bool operator!=(VtValue const &lhs, T const &rhs)
Tests for inequality.
Definition: value.h:1310
void UncheckedSwap(VtValue &rhs)
Definition: value.h:1007
typename std::decay< decltype(VtGetProxiedObject(std::declval< T >()))>::type type
Definition: traits.h:110
constexpr Integral BitsAs() const noexcept
Retrieve the stored bits as the integral type Integral.
static bool CanCastFromTypeidToTypeid(std::type_info const &from, std::type_info const &to)
Definition: value.h:1218
friend bool operator==(VtValue const &lhs, T const &rhs)
Tests for equality.
Definition: value.h:1299
#define VT_VEC_VALUE_TYPES
Definition: types.h:71
VT_API std::ostream & VtStreamOut(std::vector< VtValue > const &val, std::ostream &)
#define VT_VALUE_SET_STORED_TYPE(SRC, DST)
Definition: value.h:91
VtValue(VtValue &&other) noexcept
Move construct with other.
Definition: value.h:852
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
void const * GetPointer() const
Definition: value.h:73
VtValue & operator=(VtValue &&other) noexcept
Move assignment from another VtValue.
Definition: value.h:903
GLdouble t
Definition: glad.h:2397
void Set(T *ptr) noexcept
Set the pointer value to ptr.
VT_API std::type_info const & GetTypeid() const
Returns the typeid of the type held by this value.
void TfDelegatedCountDecrement(PXR_NS::Sdf_Identity *p) noexcept
Definition: identity.h:68
Array concept. By default, types are not arrays.
Definition: traits.h:22
T UncheckedGet()&&
Definition: value.h:1110
GLenum GLenum dst
Definition: glcorearb.h:1793
VT_API size_t GetHash() const
Return a hash code for the held object by calling VtHashValue() on it.
std::enable_if_t< std::is_same< T, typename Vt_ValueGetStored< T >::Type >::value > UncheckedSwap(T &rhs)
Definition: value.h:1000
VtValue & operator=(VtValue const &other)
Copy assignment from another VtValue.
Definition: value.h:896
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
friend size_t hash_value(VtValue const &val)
Definition: value.h:1293
#define ARCH_PRAGMA_MAYBE_UNINITIALIZED
Definition: pragmas.h:175
size_t VtHashValue(T const &val)
Definition: hash.h:61
std::enable_if_t< std::is_same< T, typename Vt_ValueGetStored< T >::Type >::value, bool > Mutate(Fn &&mutateFn)
Definition: value.h:1037
static VtValue Cast(VtValue const &val)
Definition: value.h:1189
bool IsHolding() const
Definition: value.h:1064
std::type_info const & GetType() const
Definition: value.h:67
static Vt_DefaultValueHolder Create()
Definition: value.h:55
auto ptr(T p) -> const void *
Definition: format.h:4331
GLuint GLfloat * val
Definition: glcorearb.h:1608
VT_API std::string GetTypeName() const
Return the type name of the held typeid.
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
friend void swap(VtValue &lhs, VtValue &rhs)
Overloaded swap() for generic code/stl/etc.
Definition: value.h:967
static void RegisterSimpleCast()
Register a simple cast from VtValue holding From to VtValue.
Definition: value.h:1169
Definition: type.h:47
static TfAnyUniquePtr New()
Definition: anyUniquePtr.h:30
#define VT_QUATERNION_VALUE_TYPES
Definition: types.h:108
VtValue & CastToTypeid(std::type_info const &type)
Definition: value.h:1255
PXR_NAMESPACE_OPEN_SCOPE bool TfSafeTypeCompare(const std::type_info &t1, const std::type_info &t2)
VtValue()
Default ctor gives empty VtValue.
Definition: value.h:844
static void RegisterSimpleBidirectionalCast()
Definition: value.h:1176
VT_API friend std::ostream & operator<<(std::ostream &out, const VtValue &self)
Calls through to operator << on the held object.
T GetWithDefault(T const &def=T()) const
Definition: value.h:1156
static Vt_DefaultValueHolder Invoke()
Definition: value.h:1512
#define VT_MATRIX_VALUE_TYPES
Definition: types.h:87
PXR_NAMESPACE_OPEN_SCOPE constexpr struct TfDelegatedCountIncrementTagType TfDelegatedCountIncrementTag
Definition: value.h:146
bool CanCastToTypeid(std::type_info const &type) const
Definition: value.h:1280
void TfDelegatedCountIncrement(PXR_NS::Sdf_Identity *p)
Definition: identity.h:65
VT_API TfType GetType() const
Returns the TfType of the type held by this value.
VT_API bool CanHash() const
Return true if the held object provides a hash implementation.
void const * Get() const
Return a pointer to the owned object.
Definition: anyUniquePtr.h:69
GLenum src
Definition: glcorearb.h:1793