value.h
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_VT_VALUE_H
25 #define PXR_BASE_VT_VALUE_H
26 
27 #include "pxr/pxr.h"
28 
29 #ifdef PXR_PYTHON_SUPPORT_ENABLED
30 // XXX: Include pyLock.h after pyObjWrapper.h to work around
31 // Python include ordering issues.
32 #include "pxr/base/tf/pyObjWrapper.h"
33 #endif // PXR_PYTHON_SUPPORT_ENABLED
34 
35 #include "pxr/base/tf/pyLock.h"
36 
37 #include "pxr/base/arch/demangle.h"
38 #include "pxr/base/arch/hints.h"
39 #include "pxr/base/tf/anyUniquePtr.h"
40 #include "pxr/base/tf/pointerAndBits.h"
43 #include "pxr/base/tf/tf.h"
44 #include "pxr/base/tf/type.h"
45 
46 #include "pxr/base/vt/api.h"
47 #include "pxr/base/vt/hash.h"
48 #include "pxr/base/vt/streamOut.h"
49 #include "pxr/base/vt/traits.h"
50 #include "pxr/base/vt/types.h"
51 
52 #include <boost/intrusive_ptr.hpp>
53 #include <boost/type_traits/has_trivial_assign.hpp>
54 #include <boost/type_traits/has_trivial_constructor.hpp>
55 #include <boost/type_traits/has_trivial_copy.hpp>
56 #include <boost/type_traits/has_trivial_destructor.hpp>
57 
58 #include <iosfwd>
59 #include <typeinfo>
60 #include <type_traits>
61 
62 PXR_NAMESPACE_OPEN_SCOPE
63 
67 template <class T>
68 struct Vt_DefaultValueFactory;
69 
70 // This is a helper class used by Vt_DefaultValueFactory to return a value with
71 // its type erased and only known at runtime via a std::type_info.
72 struct Vt_DefaultValueHolder
73 {
74  // Creates a value-initialized object and stores the type_info for the
75  // static type.
76  template <typename T>
77  static Vt_DefaultValueHolder Create() {
78  return Vt_DefaultValueHolder(TfAnyUniquePtr::New<T>(), typeid(T));
79  }
80 
81  // Creates a copy of the object and stores the type_info for the static
82  // type.
83  template <typename T>
84  static Vt_DefaultValueHolder Create(T const &val) {
85  return Vt_DefaultValueHolder(TfAnyUniquePtr::New(val), typeid(T));
86  }
87 
88  // Return the runtime type of the held object.
89  std::type_info const &GetType() const {
90  return *_type;
91  }
92 
93  // Return a pointer to the held object. This may be safely cast to the
94  // static type corresponding to the type_info returned by GetType.
95  void const *GetPointer() const {
96  return _ptr.Get();
97  }
98 
99 private:
100  Vt_DefaultValueHolder(TfAnyUniquePtr &&ptr, std::type_info const &type)
101  : _ptr(std::move(ptr)), _type(&type) {}
102 
103  TfAnyUniquePtr _ptr;
104  std::type_info const *_type;
105 };
106 
107 class VtValue;
108 
109 // Overload VtStreamOut for vector<VtValue>. Produces output like [value1,
110 // value2, ... valueN].
111 VT_API std::ostream &VtStreamOut(std::vector<VtValue> const &val, std::ostream &);
112 
113 #define VT_VALUE_SET_STORED_TYPE(SRC, DST) \
114  template <> struct Vt_ValueStoredType<SRC> { typedef DST Type; }
115 
116 template <class T> struct Vt_ValueStoredType { typedef T Type; };
117 VT_VALUE_SET_STORED_TYPE(char const *, std::string);
118 VT_VALUE_SET_STORED_TYPE(char *, std::string);
119 
120 #ifdef PXR_PYTHON_SUPPORT_ENABLED
121 VT_VALUE_SET_STORED_TYPE(boost::python::object, TfPyObjWrapper);
122 #endif // PXR_PYTHON_SUPPORT_ENABLED
123 
124 #undef VT_VALUE_SET_STORED_TYPE
125 
126 // A metafunction that gives the type VtValue should store for a given type T.
127 template <class T>
128 struct Vt_ValueGetStored
129  : Vt_ValueStoredType<std::decay_t<T>> {};
130 
168 class VtValue
169 {
170  static const unsigned int _LocalFlag = 1 << 0;
171  static const unsigned int _TrivialCopyFlag = 1 << 1;
172  static const unsigned int _ProxyFlag = 1 << 2;
173 
174  template <class T>
175  struct _Counted {
176  explicit _Counted(T const &obj) : _obj(obj) {
177  _refCount = 0;
178  }
179  bool IsUnique() const { return _refCount == 1; }
180  T const &Get() const { return _obj; }
181  T &GetMutable() { return _obj; }
182 
183  private:
184  T _obj;
185  mutable std::atomic<int> _refCount;
186 
187  friend inline void intrusive_ptr_add_ref(_Counted const *d) {
188  d->_refCount.fetch_add(1, std::memory_order_relaxed);
189  }
190  friend inline void intrusive_ptr_release(_Counted const *d) {
191  if (d->_refCount.fetch_sub(1, std::memory_order_release) == 1) {
192  std::atomic_thread_fence(std::memory_order_acquire);
193  delete d;
194  }
195  }
196  };
197 
198  // Hold objects up to 1 word large locally. This makes the total structure
199  // 16 bytes when compiled 64 bit (1 word type-info pointer, 1 word storage
200  // space).
201  static const size_t _MaxLocalSize = sizeof(void*);
202  typedef std::aligned_storage<
203  /* size */_MaxLocalSize, /* alignment */_MaxLocalSize>::type _Storage;
204 
205  template <class T>
206  using _IsTriviallyCopyable = std::integral_constant<bool,
207  boost::has_trivial_constructor<T>::value &&
208  boost::has_trivial_copy<T>::value &&
209  boost::has_trivial_assign<T>::value &&
210  boost::has_trivial_destructor<T>::value>;
211 
212  // Metafunction that returns true if T should be stored locally, false if it
213  // should be stored remotely.
214  template <class T>
215  using _UsesLocalStore = std::integral_constant<bool,
216  (sizeof(T) <= sizeof(_Storage)) &&
217  VtValueTypeHasCheapCopy<T>::value &&
218  std::is_nothrow_move_constructible<T>::value &&
219  std::is_nothrow_move_assignable<T>::value>;
220 
221  // Type information base class.
222  struct _TypeInfo {
223  private:
224  using _CopyInitFunc = void (*)(_Storage const &, _Storage &);
225  using _DestroyFunc = void (*)(_Storage &);
226  using _MoveFunc = void (*)(_Storage &, _Storage &);
227  using _CanHashFunc = bool (*)(_Storage const &);
228  using _HashFunc = size_t (*)(_Storage const &);
229  using _EqualFunc = bool (*)(_Storage const &, _Storage const &);
230  using _EqualPtrFunc = bool (*)(_Storage const &, void const *);
231  using _MakeMutableFunc = void (*)(_Storage &);
232 #ifdef PXR_PYTHON_SUPPORT_ENABLED
233  using _GetPyObjFunc = TfPyObjWrapper (*)(_Storage const &);
234 #endif // PXR_PYTHON_SUPPORT_ENABLED
235  using _StreamOutFunc =
236  std::ostream & (*)(_Storage const &, std::ostream &);
237  using _GetTypeidFunc = std::type_info const & (*)(_Storage const &);
238  using _IsArrayValuedFunc = bool (*)(_Storage const &);
239  using _GetElementTypeidFunc =
240  std::type_info const & (*)(_Storage const &);
241  using _GetShapeDataFunc = const Vt_ShapeData* (*)(_Storage const &);
242  using _GetNumElementsFunc = size_t (*)(_Storage const &);
243  using _ProxyHoldsTypeFunc = bool (*)(_Storage const &, std::type_info const &);
244  using _GetProxiedTypeFunc = TfType (*)(_Storage const &);
245  using _GetProxiedTypeidFunc =
246  std::type_info const & (*)(_Storage const &);
247  using _GetProxiedObjPtrFunc = void const *(*)(_Storage const &);
248  using _GetProxiedAsVtValueFunc = VtValue (*)(_Storage const &);
249 
250  protected:
251  constexpr _TypeInfo(const std::type_info &ti,
252  const std::type_info &elementTi,
253  bool isArray,
254  bool isHashable,
255  bool isProxy,
256  _CopyInitFunc copyInit,
257  _DestroyFunc destroy,
258  _MoveFunc move,
259  _CanHashFunc canHash,
260  _HashFunc hash,
261  _EqualFunc equal,
262  _EqualPtrFunc equalPtr,
263  _MakeMutableFunc makeMutable,
264 #ifdef PXR_PYTHON_SUPPORT_ENABLED
265  _GetPyObjFunc getPyObj,
266 #endif // PXR_PYTHON_SUPPORT_ENABLED
267  _StreamOutFunc streamOut,
268  _GetTypeidFunc getTypeid,
269  _IsArrayValuedFunc isArrayValued,
270  _GetElementTypeidFunc getElementTypeid,
271  _GetShapeDataFunc getShapeData,
272  _GetNumElementsFunc getNumElements,
273  _ProxyHoldsTypeFunc proxyHoldsType,
274  _GetProxiedTypeFunc getProxiedType,
275  _GetProxiedTypeidFunc getProxiedTypeid,
276  _GetProxiedObjPtrFunc getProxiedObjPtr,
277  _GetProxiedAsVtValueFunc getProxiedAsVtValue)
278  : typeInfo(ti)
279  , elementTypeInfo(elementTi)
280  , isProxy(isProxy)
281  , isArray(isArray)
282  , isHashable(isHashable)
283  // Function table
284  , _copyInit(copyInit)
285  , _destroy(destroy)
286  , _move(move)
287  , _canHash(canHash)
288  , _hash(hash)
289  , _equal(equal)
290  , _equalPtr(equalPtr)
291  , _makeMutable(makeMutable)
292 #ifdef PXR_PYTHON_SUPPORT_ENABLED
293  , _getPyObj(getPyObj)
294 #endif // PXR_PYTHON_SUPPORT_ENABLED
295  , _streamOut(streamOut)
296  , _getTypeid(getTypeid)
297  , _isArrayValued(isArrayValued)
298  , _getElementTypeid(getElementTypeid)
299  , _getShapeData(getShapeData)
300  , _getNumElements(getNumElements)
301  , _proxyHoldsType(proxyHoldsType)
302  , _getProxiedType(getProxiedType)
303  , _getProxiedTypeid(getProxiedTypeid)
304  , _getProxiedObjPtr(getProxiedObjPtr)
305  , _getProxiedAsVtValue(getProxiedAsVtValue)
306  {}
307 
308  public:
309  void CopyInit(_Storage const &src, _Storage &dst) const {
310  _copyInit(src, dst);
311  }
312  void Destroy(_Storage &storage) const {
313  _destroy(storage);
314  }
315  void Move(_Storage &src, _Storage &dst) const noexcept {
316  _move(src, dst);
317  }
318  bool CanHash(_Storage const &storage) const {
319  return _canHash(storage);
320  }
321  size_t Hash(_Storage const &storage) const {
322  return _hash(storage);
323  }
324  bool Equal(_Storage const &lhs, _Storage const &rhs) const {
325  return _equal(lhs, rhs);
326  }
327  bool EqualPtr(_Storage const &lhs, void const *rhs) const {
328  return _equalPtr(lhs, rhs);
329  }
330  void MakeMutable(_Storage &storage) const {
331  _makeMutable(storage);
332  }
333 #ifdef PXR_PYTHON_SUPPORT_ENABLED
334  TfPyObjWrapper GetPyObj(_Storage const &storage) const {
335  return _getPyObj(storage);
336  }
337 #endif // PXR_PYTHON_SUPPORT_ENABLED
338  std::ostream &StreamOut(_Storage const &storage,
339  std::ostream &out) const {
340  return _streamOut(storage, out);
341  }
342  bool IsArrayValued(_Storage const &storage) const {
343  return _isArrayValued(storage);
344  }
345  std::type_info const &GetElementTypeid(_Storage const &storage) const {
346  return _getElementTypeid(storage);
347  }
348  std::type_info const &GetTypeid(_Storage const &storage) const {
349  return _getTypeid(storage);
350  }
351  const Vt_ShapeData* GetShapeData(_Storage const &storage) const {
352  return _getShapeData(storage);
353  }
354  size_t GetNumElements(_Storage const &storage) const {
355  return _getNumElements(storage);
356  }
357  bool ProxyHoldsType(_Storage const &storage,
358  std::type_info const &t) const {
359  return _proxyHoldsType(storage, t);
360  }
361  TfType GetProxiedType(_Storage const &storage) const {
362  return _getProxiedType(storage);
363  }
364  std::type_info const &GetProxiedTypeid(_Storage const &storage) const {
365  return _getProxiedTypeid(storage);
366  }
367  VtValue GetProxiedAsVtValue(_Storage const &storage) const {
368  return _getProxiedAsVtValue(storage);
369  }
370  void const *GetProxiedObjPtr(_Storage const &storage) const {
371  return _getProxiedObjPtr(storage);
372  }
373 
374  const std::type_info &typeInfo;
375  const std::type_info &elementTypeInfo;
376  bool isProxy;
377  bool isArray;
378  bool isHashable;
379 
380  private:
381  _CopyInitFunc _copyInit;
382  _DestroyFunc _destroy;
383  _MoveFunc _move;
384  _CanHashFunc _canHash;
385  _HashFunc _hash;
386  _EqualFunc _equal;
387  _EqualPtrFunc _equalPtr;
388  _MakeMutableFunc _makeMutable;
389 #ifdef PXR_PYTHON_SUPPORT_ENABLED
390  _GetPyObjFunc _getPyObj;
391 #endif // PXR_PYTHON_SUPPORT_ENABLED
392  _StreamOutFunc _streamOut;
393  _GetTypeidFunc _getTypeid;
394  _IsArrayValuedFunc _isArrayValued;
395  _GetElementTypeidFunc _getElementTypeid;
396  _GetShapeDataFunc _getShapeData;
397  _GetNumElementsFunc _getNumElements;
398  _ProxyHoldsTypeFunc _proxyHoldsType;
399  _GetProxiedTypeFunc _getProxiedType;
400  _GetProxiedTypeidFunc _getProxiedTypeid;
401  _GetProxiedObjPtrFunc _getProxiedObjPtr;
402  _GetProxiedAsVtValueFunc _getProxiedAsVtValue;
403  };
404 
405  // Type-dispatching overloads.
406 
407  // Array type helper.
408  template <class T, class Enable=void>
409  struct _ArrayHelper
410  {
411  static const Vt_ShapeData* GetShapeData(T const &) { return NULL; }
412  static size_t GetNumElements(T const &) { return 0; }
413  constexpr static std::type_info const &GetElementTypeid() {
414  return typeid(void);
415  }
416  };
417  template <class Array>
418  struct _ArrayHelper<
419  Array, typename std::enable_if<VtIsArray<Array>::value>::type>
420  {
421  static const Vt_ShapeData* GetShapeData(Array const &obj) {
422  return obj._GetShapeData();
423  }
424  static size_t GetNumElements(Array const &obj) {
425  return obj.size();
426  }
427  constexpr static std::type_info const &GetElementTypeid() {
428  return typeid(typename Array::ElementType);
429  }
430  };
431 
432  // Function used in case T has equality comparison.
433  template <class T>
434  static inline auto
435  _TypedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
436  return a == b;
437  }
438  // Function used in case T does not have equality comparison.
439  template <class NoEqual>
440  static inline bool
441  _TypedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
442  return VtGetProxiedObject(a) == VtGetProxiedObject(b);
443  }
444 
445  template <class T>
446  static inline auto
447  _ErasedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
448  return a == b;
449  }
450  // Function used in case T does not have equality comparison.
451  template <class NoEqual>
452  static inline bool
453  _ErasedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
454  return *VtGetErasedProxiedVtValue(a) == *VtGetErasedProxiedVtValue(b);
455  }
456 
457  // Proxy type helper. Base case handles non-proxies and typed proxies.
458  template <class T, class Enable = void>
459  struct _ProxyHelper
460  {
461  using ProxiedType = typename VtGetProxiedType<T>::type;
462 
463  static bool CanHash(T const &) { return VtIsHashable<ProxiedType>(); }
464  static size_t Hash(T const &obj) {
465  return VtHashValue(VtGetProxiedObject(obj));
466  }
467  static bool Equal(T const &a, T const &b) {
468  // We use the traditional int/long = 0 arg technique to disambiguate
469  // overloads, so we can invoke equality comparison on the *proxy*
470  // type if it provides one, or if it doesn't then invoke equality
471  // comparison on the *proxied* type instead.
472  return _TypedProxyEqualityImpl(a, b, 0);
473  }
474 #ifdef PXR_PYTHON_SUPPORT_ENABLED
475  static TfPyObjWrapper GetPyObj(T const &obj) {
476  ProxiedType const &p = VtGetProxiedObject(obj);
477  TfPyLock lock;
478  return boost::python::api::object(p);
479  }
480 #endif //PXR_PYTHON_SUPPORT_ENABLED
481  static std::ostream &StreamOut(T const &obj, std::ostream &out) {
482  return VtStreamOut(VtGetProxiedObject(obj), out);
483  }
484  static Vt_ShapeData const *GetShapeData(T const &obj) {
485  return _ArrayHelper<ProxiedType>::GetShapeData(
486  VtGetProxiedObject(obj));
487  }
488  static size_t GetNumElements(T const &obj) {
489  return _ArrayHelper<ProxiedType>::GetNumElements(
490  VtGetProxiedObject(obj));
491  }
492  static bool IsArrayValued(T const &) {
494  }
495  static std::type_info const &GetTypeid(T const &) {
496  return typeid(ProxiedType);
497  }
498  static std::type_info const &GetElementTypeid(T const &) {
499  return _ArrayHelper<ProxiedType>::GetElementTypeid();
500  }
501  static VtValue GetProxiedAsVtValue(T const &obj) {
502  return VtValue(VtGetProxiedObject(obj));
503  }
504  static bool HoldsType(T const &tp, std::type_info const &query) {
505  return TfSafeTypeCompare(typeid(ProxiedType), query);
506  }
507  static TfType GetTfType(T const &tp) {
508  return TfType::Find<ProxiedType>();
509  }
510  static void const *GetObjPtr(T const &tp) {
511  return static_cast<void const *>(&VtGetProxiedObject(tp));
512  }
513  };
514 
515  template <class ErasedProxy>
516  struct _ProxyHelper<
517  ErasedProxy, typename std::enable_if<
518  VtIsErasedValueProxy<ErasedProxy>::value>::type>
519  {
520  static bool CanHash(ErasedProxy const &proxy) {
521  return VtGetErasedProxiedVtValue(proxy)->CanHash();
522  }
523  static size_t Hash(ErasedProxy const &proxy) {
524  return VtGetErasedProxiedVtValue(proxy)->GetHash();
525  }
526  static bool Equal(ErasedProxy const &a, ErasedProxy const &b) {
527  // We use the traditional int/long = 0 arg technique to disambiguate
528  // overloads, so we can invoke equality comparison on the *proxy*
529  // type if it provides one, or if it doesn't then invoke equality
530  // comparison on the VtValue containing the *proxied* type instead.
531  return _ErasedProxyEqualityImpl(a, b, 0);
532  }
533 #ifdef PXR_PYTHON_SUPPORT_ENABLED
534  static TfPyObjWrapper GetPyObj(ErasedProxy const &obj) {
535  VtValue const *val = VtGetErasedProxiedVtValue(obj);
536  TfPyLock lock;
537  return boost::python::api::object(*val);
538  }
539 #endif //PXR_PYTHON_SUPPORT_ENABLED
540 
541  static std::ostream &
542  StreamOut(ErasedProxy const &obj, std::ostream &out) {
543  return VtStreamOut(obj, out);
544  }
545  static Vt_ShapeData const *GetShapeData(ErasedProxy const &obj) {
546  return VtGetErasedProxiedVtValue(obj)->_GetShapeData();
547  }
548  static size_t GetNumElements(ErasedProxy const &obj) {
549  return VtGetErasedProxiedVtValue(obj)->_GetNumElements();
550  }
551  static bool IsArrayValued(ErasedProxy const &obj) {
552  return VtGetErasedProxiedVtValue(obj)->IsArrayValued();
553  }
554  static std::type_info const &GetTypeid(ErasedProxy const &obj) {
555  return VtGetErasedProxiedVtValue(obj)->GetTypeid();
556  }
557  static std::type_info const &GetElementTypeid(ErasedProxy const &obj) {
558  return VtGetErasedProxiedVtValue(obj)->GetElementTypeid();
559  }
560  static VtValue GetProxiedAsVtValue(ErasedProxy const &ep) {
561  return *VtGetErasedProxiedVtValue(ep);
562  }
563  static bool
564  HoldsType(ErasedProxy const &ep, std::type_info const &query) {
565  return VtErasedProxyHoldsType(ep, query);
566  }
567  static TfType GetTfType(ErasedProxy const &ep) {
568  return VtGetErasedProxiedTfType(ep);
569  }
570  static void const *GetObjPtr(ErasedProxy const &ep) {
571  VtValue const *val = VtGetErasedProxiedVtValue(ep);
572  return val ? val->_GetProxiedObjPtr() : nullptr;
573  }
574  };
575 
576  // _TypeInfo implementation helper. This is a CRTP base that the
577  // _LocalTypeInfo and _RemoteTypeInfo types derive. It wraps their
578  // type-specific implementations with type-generic interfaces.
579  template <class T, class Container, class Derived>
580  struct _TypeInfoImpl : public _TypeInfo
581  {
582  static const bool IsLocal = _UsesLocalStore<T>::value;
583  static const bool HasTrivialCopy = _IsTriviallyCopyable<T>::value;
584  static const bool IsProxy = VtIsValueProxy<T>::value;
585 
586  using ProxyHelper = _ProxyHelper<T>;
587 
588  using This = _TypeInfoImpl;
589 
590  constexpr _TypeInfoImpl()
591  : _TypeInfo(typeid(T),
592  _ArrayHelper<T>::GetElementTypeid(),
594  VtIsHashable<T>(),
595  IsProxy,
596  &This::_CopyInit,
597  &This::_Destroy,
598  &This::_Move,
599  &This::_CanHash,
600  &This::_Hash,
601  &This::_Equal,
602  &This::_EqualPtr,
603  &This::_MakeMutable,
604 #ifdef PXR_PYTHON_SUPPORT_ENABLED
605  &This::_GetPyObj,
606 #endif // PXR_PYTHON_SUPPORT_ENABLED
607  &This::_StreamOut,
608 
609  &This::_GetTypeid,
610 
611  // Array support.
612  &This::_IsArrayValued,
613  &This::_GetElementTypeid,
614  &This::_GetShapeData,
615  &This::_GetNumElements,
616 
617  // Proxy support.
618  &This::_ProxyHoldsType,
619  &This::_GetProxiedType,
620  &This::_GetProxiedTypeid,
621  &This::_GetProxiedObjPtr,
622  &This::_GetProxiedAsVtValue)
623  {}
624 
626  // Typed API for client use.
627  static T const &GetObj(_Storage const &storage) {
628  return Derived::_GetObj(_Container(storage));
629  }
630 
631  static T &GetMutableObj(_Storage &storage) {
632  return Derived::_GetMutableObj(_Container(storage));
633  }
634 
635  static void CopyInitObj(T const &objSrc, _Storage &dst) {
636  Derived::_PlaceCopy(&_Container(dst), objSrc);
637  }
638 
639  private:
640  static_assert(sizeof(Container) <= sizeof(_Storage),
641  "Container size cannot exceed storage size.");
642 
644  // _TypeInfo interface function implementations.
645  static void _CopyInit(_Storage const &src, _Storage &dst) {
646  new (&_Container(dst)) Container(_Container(src));
647  }
648 
649  static void _Destroy(_Storage &storage) {
650  _Container(storage).~Container();
651  }
652 
653  static bool _CanHash(_Storage const &storage) {
654  return ProxyHelper::CanHash(GetObj(storage));
655  }
656 
657  static size_t _Hash(_Storage const &storage) {
658  return ProxyHelper::Hash(GetObj(storage));
659  }
660 
661  static bool _Equal(_Storage const &lhs, _Storage const &rhs) {
662  // Equal is only ever invoked with an object of this specific type.
663  // That is, we only ever ask a proxy to compare to a proxy; we never
664  // ask a proxy to compare to the proxied object.
665  return ProxyHelper::Equal(GetObj(lhs), GetObj(rhs));
666  }
667 
668  static bool _EqualPtr(_Storage const &lhs, void const *rhs) {
669  // Equal is only ever invoked with an object of this specific type.
670  // That is, we only ever ask a proxy to compare to a proxy; we never
671  // ask a proxy to compare to the proxied object.
672  return ProxyHelper::Equal(
673  GetObj(lhs), *static_cast<T const *>(rhs));
674  }
675 
676  static void _Move(_Storage &src, _Storage &dst) noexcept {
677  new (&_Container(dst)) Container(std::move(_Container(src)));
678  _Destroy(src);
679  }
680 
681  static void _MakeMutable(_Storage &storage) {
682  GetMutableObj(storage);
683  }
684 
685 #ifdef PXR_PYTHON_SUPPORT_ENABLED
686  static TfPyObjWrapper _GetPyObj(_Storage const &storage) {
687  return ProxyHelper::GetPyObj(GetObj(storage));
688  }
689 #endif // PXR_PYTHON_SUPPORT_ENABLED
690 
691  static std::ostream &_StreamOut(
692  _Storage const &storage, std::ostream &out) {
693  return ProxyHelper::StreamOut(GetObj(storage), out);
694  }
695 
696  static std::type_info const &_GetTypeid(_Storage const &storage) {
697  return ProxyHelper::GetTypeid(GetObj(storage));
698  }
699 
700  static bool _IsArrayValued(_Storage const &storage) {
701  return ProxyHelper::IsArrayValued(GetObj(storage));
702  }
703 
704  static std::type_info const &
705  _GetElementTypeid(_Storage const &storage) {
706  return ProxyHelper::GetElementTypeid(GetObj(storage));
707  }
708 
709  static const Vt_ShapeData* _GetShapeData(_Storage const &storage) {
710  return ProxyHelper::GetShapeData(GetObj(storage));
711  }
712 
713  static size_t _GetNumElements(_Storage const &storage) {
714  return ProxyHelper::GetNumElements(GetObj(storage));
715  }
716 
717  static bool
718  _ProxyHoldsType(_Storage const &storage, std::type_info const &t) {
719  return ProxyHelper::HoldsType(GetObj(storage), t);
720  }
721 
722  static TfType
723  _GetProxiedType(_Storage const &storage) {
724  return ProxyHelper::GetTfType(GetObj(storage));
725  }
726 
727  static std::type_info const &
728  _GetProxiedTypeid(_Storage const &storage) {
729  return ProxyHelper::GetTypeid(GetObj(storage));
730  }
731 
732  static void const *
733  _GetProxiedObjPtr(_Storage const &storage) {
734  return ProxyHelper::GetObjPtr(GetObj(storage));
735  }
736 
737  static VtValue
738  _GetProxiedAsVtValue(_Storage const &storage) {
739  return ProxyHelper::GetProxiedAsVtValue(GetObj(storage));
740  }
741 
743  // Internal helper -- cast type-generic storage to type-specific
744  // container.
745  static Container &_Container(_Storage &storage) {
746  // XXX Will need std::launder in c++17.
747  return *reinterpret_cast<Container *>(&storage);
748  }
749  static Container const &_Container(_Storage const &storage) {
750  // XXX Will need std::launder in c++17.
751  return *reinterpret_cast<Container const *>(&storage);
752  }
753  };
754 
756  // Local-storage type info implementation. The container and the object are
757  // the same -- there is no distinct container.
758  template <class T>
759  struct _LocalTypeInfo : _TypeInfoImpl<
760  T, // type
761  T, // container
762  _LocalTypeInfo<T> // CRTP
763  >
764  {
765  constexpr _LocalTypeInfo()
766  : _TypeInfoImpl<T, T, _LocalTypeInfo<T>>()
767  {}
768 
769  // Get returns object directly.
770  static T &_GetMutableObj(T &obj) { return obj; }
771  static T const &_GetObj(T const &obj) { return obj; }
772  // Place placement new's object directly.
773  static void _PlaceCopy(T *dst, T const &src) { new (dst) T(src); }
774  };
775 
777  // Remote-storage type info implementation. The container is an
778  // intrusive_ptr to an object holder: _Counted<T>.
779  template <class T>
780  struct _RemoteTypeInfo : _TypeInfoImpl<
781  T, // type
782  boost::intrusive_ptr<_Counted<T> >, // container
783  _RemoteTypeInfo<T> // CRTP
784  >
785  {
786  constexpr _RemoteTypeInfo()
787  : _TypeInfoImpl<
788  T, boost::intrusive_ptr<_Counted<T>>, _RemoteTypeInfo<T>>()
789  {}
790 
791  typedef boost::intrusive_ptr<_Counted<T> > Ptr;
792  // Get returns object stored in the pointed-to _Counted<T>.
793  static T &_GetMutableObj(Ptr &ptr) {
794  if (!ptr->IsUnique())
795  ptr.reset(new _Counted<T>(ptr->Get()));
796  return ptr->GetMutable();
797  }
798  static T const &_GetObj(Ptr const &ptr) { return ptr->Get(); }
799  // PlaceCopy() allocates a new _Counted<T> with a copy of the object.
800  static void _PlaceCopy(Ptr *dst, T const &src) {
801  new (dst) Ptr(new _Counted<T>(src));
802  }
803  };
804 
805  // Metafunction that returns the specific _TypeInfo subclass for T.
806  template <class T>
807  struct _TypeInfoFor {
808  // return _UsesLocalStore(T) ? _LocalTypeInfo<T> : _RemoteTypeInfo<T>;
809  typedef std::conditional_t<_UsesLocalStore<T>::value,
810  _LocalTypeInfo<T>,
811  _RemoteTypeInfo<T>> Type;
812  };
813 
814  // Make sure char[N] is treated as a string.
815  template <size_t N>
816  struct _TypeInfoFor<char[N]> : _TypeInfoFor<std::string> {};
817 
818  // Runtime function to return a _TypeInfo base pointer to a specific
819  // _TypeInfo subclass for type T.
820  template <class T>
821  static TfPointerAndBits<const _TypeInfo> GetTypeInfo() {
822  typedef typename _TypeInfoFor<T>::Type TI;
823  static const TI ti;
824  static constexpr unsigned int flags =
825  (TI::IsLocal ? _LocalFlag : 0) |
826  (TI::HasTrivialCopy ? _TrivialCopyFlag : 0) |
827  (TI::IsProxy ? _ProxyFlag : 0);
828  return TfPointerAndBits<const _TypeInfo>(&ti, flags);
829  }
830 
831  // A helper that moves a held value to temporary storage, but keeps it alive
832  // until the _HoldAside object is destroyed. This is used when assigning
833  // over a VtValue that might own the object being assigned. For instance,
834  // if I have a VtValue holding a map<string, VtValue>, and I reassign this
835  // VtValue with one of the elements from the map, we must ensure that the
836  // map isn't destroyed until after the assignment has taken place.
837  friend struct _HoldAside;
838  struct _HoldAside {
839  explicit _HoldAside(VtValue *val)
840  : info((val->IsEmpty() || val->_IsLocalAndTriviallyCopyable())
841  ? static_cast<_TypeInfo const *>(NULL) : val->_info.Get()) {
842  if (info)
843  info->Move(val->_storage, storage);
844  }
845  ~_HoldAside() {
846  if (info)
847  info->Destroy(storage);
848  }
849  _Storage storage;
850  _TypeInfo const *info;
851  };
852 
853  template <class T>
854  std::enable_if_t<
855  std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
856  _Init(T const &obj) {
857  _info = GetTypeInfo<T>();
858  typedef typename _TypeInfoFor<T>::Type TypeInfo;
859  TypeInfo::CopyInitObj(obj, _storage);
860  }
861 
862  template <class T>
863  std::enable_if_t<
864  !std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
865  _Init(T const &obj) {
866  _Init(typename Vt_ValueGetStored<T>::Type(obj));
867  }
868 
869 public:
870 
872  VtValue() {}
873 
875  VtValue(VtValue const &other) {
876  _Copy(other, *this);
877  }
878 
880  VtValue(VtValue &&other) noexcept {
881  _Move(other, *this);
882  }
883 
889  template <class T>
890  explicit VtValue(T const &obj) {
891  _Init(obj);
892  }
893 
913  template <class T>
914  static VtValue Take(T &obj) {
915  VtValue ret;
916  ret.Swap(obj);
917  return ret;
918  }
919 
921  ~VtValue() { _Clear(); }
922 
924  VtValue &operator=(VtValue const &other) {
925  if (ARCH_LIKELY(this != &other))
926  _Copy(other, *this);
927  return *this;
928  }
929 
931  VtValue &operator=(VtValue &&other) noexcept {
932  if (ARCH_LIKELY(this != &other))
933  _Move(other, *this);
934  return *this;
935  }
936 
937 #ifndef doxygen
938  template <class T>
939  inline
940  std::enable_if_t<
941  _TypeInfoFor<T>::Type::IsLocal &&
942  _TypeInfoFor<T>::Type::HasTrivialCopy,
943  VtValue &>
944  operator=(T obj) {
945  _Clear();
946  _Init(obj);
947  return *this;
948  }
949 #endif
950 
952 #ifdef doxygen
953  template <class T>
954  VtValue&
955  operator=(T const &obj);
956 #else
957  template <class T>
958  std::enable_if_t<
959  !_TypeInfoFor<T>::Type::IsLocal ||
960  !_TypeInfoFor<T>::Type::HasTrivialCopy,
961  VtValue &>
962  operator=(T const &obj) {
963  _HoldAside tmp(this);
964  _Init(obj);
965  return *this;
966  }
967 #endif
968 
970  VtValue &operator=(char const *cstr) {
971  std::string tmp(cstr);
972  _Clear();
973  _Init(tmp);
974  return *this;
975  }
976 
978  VtValue &operator=(char *cstr) {
979  return *this = const_cast<char const *>(cstr);
980  }
981 
983  VtValue &Swap(VtValue &rhs) noexcept {
984  // Do nothing if both empty. Otherwise general swap.
985  if (!IsEmpty() || !rhs.IsEmpty()) {
986  VtValue tmp;
987  _Move(*this, tmp);
988  _Move(rhs, *this);
989  _Move(tmp, rhs);
990  }
991  return *this;
992  }
993 
995  friend void swap(VtValue &lhs, VtValue &rhs) { lhs.Swap(rhs); }
996 
998  // make an unqualified call to swap(<held-value>, rhs). If this value is
999  // not holding a T, replace the held value with a value-initialized T
1000  // instance first, then swap.
1001 #ifdef doxygen
1002  template <class T>
1003  void
1004  Swap(T &rhs);
1005 #else
1006  template <class T>
1007  std::enable_if_t<
1008  std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
1009  Swap(T &rhs) {
1010  if (!IsHolding<T>())
1011  *this = T();
1012  UncheckedSwap(rhs);
1013  }
1014 #endif
1015 
1020 #ifdef doxygen
1021  template <class T>
1022  void
1023  UncheckedSwap(T &rhs);
1024 #else
1025  template <class T>
1026  std::enable_if_t<
1027  std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
1028  UncheckedSwap(T &rhs) {
1029  using std::swap;
1030  swap(_GetMutable<T>(), rhs);
1031  }
1032 #endif
1033 
1035  void UncheckedSwap(VtValue &rhs) { Swap(rhs); }
1036 
1040  template <class T>
1041  T Remove() {
1042  T result;
1043  Swap(result);
1044  _Clear();
1045  return result;
1046  }
1047 
1051  template <class T>
1053  T result;
1054  UncheckedSwap(result);
1055  _Clear();
1056  return result;
1057  }
1058 
1061  template <class T>
1062  bool IsHolding() const {
1063  return _info.GetLiteral() && _TypeIs<T>();
1064  }
1065 
1067  VT_API bool IsArrayValued() const;
1068 
1071  size_t GetArraySize() const { return _GetNumElements(); }
1072 
1074  VT_API std::type_info const &GetTypeid() const;
1075 
1078  VT_API std::type_info const &GetElementTypeid() const;
1079 
1081  VT_API TfType GetType() const;
1082 
1084  VT_API std::string GetTypeName() const;
1085 
1089  template <class T>
1090  T const &UncheckedGet() const { return _Get<T>(); }
1091 
1100  template <class T>
1101  T const &Get() const {
1102  typedef Vt_DefaultValueFactory<T> Factory;
1103 
1104  // In the unlikely case that the types don't match, we obtain a default
1105  // value to return and issue an error via _FailGet.
1106  if (ARCH_UNLIKELY(!IsHolding<T>())) {
1107  return *(static_cast<T const *>(
1108  _FailGet(Factory::Invoke, typeid(T))));
1109  }
1110 
1111  return _Get<T>();
1112  }
1113 
1118  template <class T>
1119  T GetWithDefault(T const &def = T()) const {
1120  return IsHolding<T>() ? UncheckedGet<T>() : def;
1121  }
1122 
1124  template <typename From, typename To>
1125  static void RegisterCast(VtValue (*castFn)(VtValue const &)) {
1126  _RegisterCast(typeid(From), typeid(To), castFn);
1127  }
1128 
1130  // holding To.
1131  template <typename From, typename To>
1132  static void RegisterSimpleCast() {
1133  _RegisterCast(typeid(From), typeid(To), _SimpleCast<From, To>);
1134  }
1135 
1138  template <typename From, typename To>
1140  RegisterSimpleCast<From, To>();
1141  RegisterSimpleCast<To, From>();
1142  }
1143 
1151  template <typename T>
1152  static VtValue Cast(VtValue const &val) {
1153  VtValue ret = val;
1154  return ret.Cast<T>();
1155  }
1156 
1164  VT_API static VtValue
1165  CastToTypeOf(VtValue const &val, VtValue const &other);
1166 
1174  VT_API static VtValue
1175  CastToTypeid(VtValue const &val, std::type_info const &type);
1176 
1180  static bool CanCastFromTypeidToTypeid(std::type_info const &from,
1181  std::type_info const &to) {
1182  return _CanCast(from, to);
1183  }
1184 
1192  template <typename T>
1194  if (IsHolding<T>())
1195  return *this;
1196  return *this = _PerformCast(typeid(T), *this);
1197  }
1198 
1206  VtValue &CastToTypeOf(VtValue const &other) {
1207  return *this = _PerformCast(other.GetTypeid(), *this);
1208  }
1209 
1217  VtValue &CastToTypeid(std::type_info const &type) {
1218  return *this = _PerformCast(type, *this);
1219  }
1220 
1224  template <typename T>
1225  bool CanCast() const {
1226  return _CanCast(GetTypeid(), typeid(T));
1227  }
1228 
1232  bool CanCastToTypeOf(VtValue const &other) const {
1233  return _CanCast(GetTypeid(), other.GetTypeid());
1234  }
1235 
1239  bool CanCastToTypeid(std::type_info const &type) const {
1240  return _CanCast(GetTypeid(), type);
1241  }
1242 
1244  bool IsEmpty() const { return _info.GetLiteral() == 0; }
1245 
1247  VT_API bool CanHash() const;
1248 
1250  VT_API size_t GetHash() const;
1251 
1252  friend inline size_t hash_value(VtValue const &val) {
1253  return val.GetHash();
1254  }
1255 
1257  template <typename T>
1258  friend bool operator == (VtValue const &lhs, T const &rhs) {
1259  typedef typename Vt_ValueGetStored<T>::Type Stored;
1260  return lhs.IsHolding<Stored>() && lhs.UncheckedGet<Stored>() == rhs;
1261  }
1262  template <typename T>
1263  friend bool operator == (T const &lhs, VtValue const &rhs) {
1264  return rhs == lhs;
1265  }
1266 
1268  template <typename T>
1269  friend bool operator != (VtValue const &lhs, T const &rhs) {
1270  return !(lhs == rhs);
1271  }
1272  template <typename T>
1273  friend bool operator != (T const &lhs, VtValue const &rhs) {
1274  return !(lhs == rhs);
1275  }
1276 
1278  bool operator == (const VtValue &rhs) const {
1279  bool empty = IsEmpty(), rhsEmpty = rhs.IsEmpty();
1280  if (empty || rhsEmpty) {
1281  // Either one or both empty -- only equal if both empty.
1282  return empty == rhsEmpty;
1283  }
1284  if (_info.GetLiteral() == rhs._info.GetLiteral()) {
1285  // Holding identical types -- compare directly.
1286  return _info.Get()->Equal(_storage, rhs._storage);
1287  }
1288  return _EqualityImpl(rhs);
1289  }
1290  bool operator != (const VtValue &rhs) const { return !(*this == rhs); }
1291 
1293  VT_API friend std::ostream &
1294  operator << (std::ostream &out, const VtValue &self);
1295 
1296 private:
1297  VT_API const Vt_ShapeData* _GetShapeData() const;
1298  VT_API size_t _GetNumElements() const;
1299  friend struct Vt_ValueShapeDataAccess;
1300 
1301  static inline void _Copy(VtValue const &src, VtValue &dst) {
1302  if (src.IsEmpty()) {
1303  dst._Clear();
1304  return;
1305  }
1306 
1307  _HoldAside tmp(&dst);
1308  dst._info = src._info;
1309  if (src._IsLocalAndTriviallyCopyable()) {
1310  dst._storage = src._storage;
1311  } else {
1312  dst._info->CopyInit(src._storage, dst._storage);
1313  }
1314  }
1315 
1316  static inline void _Move(VtValue &src, VtValue &dst) noexcept {
1317  if (src.IsEmpty()) {
1318  dst._Clear();
1319  return;
1320  }
1321 
1322  _HoldAside tmp(&dst);
1323  dst._info = src._info;
1324  if (src._IsLocalAndTriviallyCopyable()) {
1325  dst._storage = src._storage;
1326  } else {
1327  dst._info->Move(src._storage, dst._storage);
1328  }
1329 
1330  src._info.Set(nullptr, 0);
1331  }
1332 
1333  template <class T>
1334  inline bool _TypeIs() const {
1335  std::type_info const &t = typeid(T);
1336  bool cmp = TfSafeTypeCompare(_info->typeInfo, t);
1337  return ARCH_UNLIKELY(_IsProxy() && !cmp) ? _TypeIsImpl(t) : cmp;
1338  }
1339 
1340  VT_API bool _TypeIsImpl(std::type_info const &queriedType) const;
1341 
1342  VT_API bool _EqualityImpl(VtValue const &rhs) const;
1343 
1344  template <class Proxy>
1345  std::enable_if_t<VtIsValueProxy<Proxy>::value, Proxy &>
1346  _GetMutable() {
1347  typedef typename _TypeInfoFor<Proxy>::Type TypeInfo;
1348  return TypeInfo::GetMutableObj(_storage);
1349  }
1350 
1351  template <class T>
1352  std::enable_if_t<!VtIsValueProxy<T>::value, T &>
1353  _GetMutable() {
1354  // If we are a proxy, collapse it out to the real value first.
1355  if (ARCH_UNLIKELY(_IsProxy())) {
1356  *this = _info->GetProxiedAsVtValue(_storage);
1357  }
1358  typedef typename _TypeInfoFor<T>::Type TypeInfo;
1359  return TypeInfo::GetMutableObj(_storage);
1360  }
1361 
1362  template <class Proxy>
1363  std::enable_if_t<VtIsValueProxy<Proxy>::value, Proxy const &>
1364  _Get() const {
1365  typedef typename _TypeInfoFor<Proxy>::Type TypeInfo;
1366  return TypeInfo::GetObj(_storage);
1367  }
1368 
1369  template <class T>
1370  std::enable_if_t<!VtIsValueProxy<T>::value, T const &>
1371  _Get() const {
1372  typedef typename _TypeInfoFor<T>::Type TypeInfo;
1373  if (ARCH_UNLIKELY(_IsProxy())) {
1374  return *static_cast<T const *>(_GetProxiedObjPtr());
1375  }
1376  return TypeInfo::GetObj(_storage);
1377  }
1378 
1379  void const *_GetProxiedObjPtr() const {
1380  return _info->GetProxiedObjPtr(_storage);
1381  }
1382 
1383  // Helper invoked in case Get fails. Reports an error and returns a default
1384  // value for \a queryType.
1385  VT_API void const *
1386  _FailGet(Vt_DefaultValueHolder (*factory)(),
1387  std::type_info const &queryType) const;
1388 
1389  inline void _Clear() {
1390  // optimize for local types not to deref _info.
1391  if (_info.GetLiteral() && !_IsLocalAndTriviallyCopyable())
1392  _info.Get()->Destroy(_storage);
1393  _info.Set(nullptr, 0);
1394  }
1395 
1396  inline bool _IsLocalAndTriviallyCopyable() const {
1397  unsigned int bits = _info.BitsAs<unsigned int>();
1398  return (bits & (_LocalFlag | _TrivialCopyFlag)) ==
1399  (_LocalFlag | _TrivialCopyFlag);
1400  }
1401 
1402  inline bool _IsProxy() const {
1403  return _info.BitsAs<unsigned int>() & _ProxyFlag;
1404  }
1405 
1406  VT_API static void _RegisterCast(std::type_info const &from,
1407  std::type_info const &to,
1408  VtValue (*castFn)(VtValue const &));
1409 
1410  VT_API static VtValue
1411  _PerformCast(std::type_info const &to, VtValue const &val);
1412 
1413  VT_API static bool
1414  _CanCast(std::type_info const &from, std::type_info const &to);
1415 
1416  // helper template function for simple casts from From to To.
1417  template <typename From, typename To>
1418  static VtValue _SimpleCast(VtValue const &val) {
1419  return VtValue(To(val.UncheckedGet<From>()));
1420  }
1421 
1422 #ifdef PXR_PYTHON_SUPPORT_ENABLED
1423  // This grants friend access to a function in the wrapper file for this
1424  // class. This lets the wrapper reach down into a value to get a
1425  // boost::python wrapped object corresponding to the held type. This
1426  // facility is necessary to get the python API we want.
1427  friend TfPyObjWrapper
1428  Vt_GetPythonObjectFromHeldValue(VtValue const &self);
1429 
1430  VT_API TfPyObjWrapper _GetPythonObject() const;
1431 #endif // PXR_PYTHON_SUPPORT_ENABLED
1432 
1433  _Storage _storage;
1435 };
1436 
1437 #ifndef doxygen
1438 
1442 template <class T>
1443 struct Vt_DefaultValueFactory {
1445  static Vt_DefaultValueHolder Invoke() {
1446  return Vt_DefaultValueHolder::Create<T>();
1447  }
1448 };
1449 
1450 struct Vt_ValueShapeDataAccess {
1451  static const Vt_ShapeData* _GetShapeData(const VtValue& value) {
1452  return value._GetShapeData();
1453  }
1454 
1455  static size_t _GetNumElements(const VtValue& value) {
1456  return value._GetNumElements();
1457  }
1458 };
1459 
1460 // For performance reasons, the default constructors for vectors,
1461 // matrices, and quaternions do *not* initialize the data of the
1462 // object. This greatly improves the performance of creating large
1463 // arrays of objects. However, boost::value_initialized<T>() no
1464 // longer fills the memory of the object with 0 bytes before invoking
1465 // the constructor so we started getting errors complaining about
1466 // uninitialized values. So, we now use VtZero to construct zeroed
1467 // out vectors, matrices, and quaternions by explicitly instantiating
1468 // the factory for these types.
1469 //
1470 #define _VT_DECLARE_ZERO_VALUE_FACTORY(r, unused, elem) \
1471 template <> \
1472 VT_API Vt_DefaultValueHolder Vt_DefaultValueFactory<VT_TYPE(elem)>::Invoke();
1473 
1474 BOOST_PP_SEQ_FOR_EACH(_VT_DECLARE_ZERO_VALUE_FACTORY,
1475  unused,
1476  VT_VEC_VALUE_TYPES
1477  VT_MATRIX_VALUE_TYPES
1478  VT_QUATERNION_VALUE_TYPES)
1479 
1480 #undef _VT_DECLARE_ZERO_VALUE_FACTORY
1481 
1482 //
1483 // The Get()/IsHolding routines needs to be special-cased to handle getting a
1484 // VtValue *as* a VtValue.
1485 //
1486 
1487 template <>
1488 inline const VtValue&
1489 VtValue::Get<VtValue>() const {
1490  return *this;
1491 }
1492 
1493 template <>
1494 inline const VtValue&
1495 VtValue::UncheckedGet<VtValue>() const {
1496  return *this;
1497 }
1498 
1499 template <>
1500 inline bool
1501 VtValue::IsHolding<VtValue>() const {
1502  return true;
1503 }
1504 
1505 // Specialize VtValue::IsHolding<void>() to always return false.
1506 template <>
1507 inline bool
1508 VtValue::IsHolding<void>() const {
1509  return false;
1510 }
1511 
1512 
1513 
1514 #endif // !doxygen
1515 
1516 PXR_NAMESPACE_CLOSE_SCOPE
1517 
1518 #endif // PXR_BASE_VT_VALUE_H
size_t GetArraySize() const
Return the number of elements in the held value if IsArrayValued(), return 0 otherwise.
Definition: value.h:1071
static void RegisterSimpleBidirectionalCast()
Register a two-way cast from VtValue holding From to VtValue holding To.
Definition: value.h:1139
constexpr T * Get() const noexcept
Retrieve the pointer.
Safely compare C++ RTTI type structures.
VtValue(VtValue &&other) noexcept
Move construct with other.
Definition: value.h:880
~VtValue()
Destructor.
Definition: value.h:921
VtValue & operator=(char const *cstr)
Assigning a char const * gives a VtValue holding a std::string.
Definition: value.h:970
VtValue & Cast()
Return this holding value type cast to T.
Definition: value.h:1193
Definitions of basic string utilities in tf.
VT_API std::string GetTypeName() const
Return the type name of the held typeid.
bool CanCastToTypeOf(VtValue const &other) const
Return if this can be cast to type.
Definition: value.h:1232
void UncheckedSwap(T &rhs)
Swap the held value with rhs.
constexpr uintptr_t GetLiteral() const noexcept
Retrieve the raw underlying value.
Compiler hints.
VtValue(VtValue const &other)
Copy construct with other.
Definition: value.h:875
VT_API bool CanHash() const
Return true if the held object provides a hash implementation.
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition: value.h:1052
Demangle C++ typenames generated by the typeid() facility.
static void RegisterSimpleCast()
Register a simple cast from VtValue holding From to VtValue.
Definition: value.h:1132
static VT_API VtValue CastToTypeOf(VtValue const &val, VtValue const &other)
Return a VtValue holding val cast to same type that other is holding.
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:1180
VtValue & CastToTypeOf(VtValue const &other)
Return this holding value type cast to same type that other is holding.
Definition: value.h:1206
static VtValue Take(T &obj)
Create a new VtValue, taking its contents from obj.
Definition: value.h:914
VT_API std::type_info const & GetTypeid() const
Returns the typeid of the type held by this value.
void swap(UsdStageLoadRules &l, UsdStageLoadRules &r)
Swap the contents of rules l and r.
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1244
friend bool operator==(VtValue const &lhs, T const &rhs)
Tests for equality.
Definition: value.h:1258
VT_API bool IsArrayValued() const
Returns true iff this is holding an array type (see VtIsArray<>).
T const & UncheckedGet() const
Returns a const reference to the held object if the held object is of type T.
Definition: value.h:1090
static VtValue Cast(VtValue const &val)
Return a VtValue holding val cast to hold T.
Definition: value.h:1152
VtValue & operator=(VtValue &&other) noexcept
Move assignment from another VtValue.
Definition: value.h:931
static VT_API VtValue CastToTypeid(VtValue const &val, std::type_info const &type)
Return a VtValue holding val cast to type.
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:43
Array concept. By default, types are not arrays.
Definition: traits.h:41
static void RegisterCast(VtValue(*castFn)(VtValue const &))
Register a cast from VtValue holding From to VtValue holding To.
Definition: value.h:1125
VtValue & operator=(char *cstr)
Assigning a char * gives a VtValue holding a std::string.
Definition: value.h:978
Boost Python object wrapper.
Definition: pyObjWrapper.h:66
VT_API std::type_info const & GetElementTypeid() const
Return the typeid of elements in a array valued type.
VtValue(T const &obj)
Construct a VtValue holding a copy of obj.
Definition: value.h:890
bool CanCast() const
Return if this can be cast to T.
Definition: value.h:1225
VtValue & Swap(VtValue &rhs) noexcept
Swap this with rhs.
Definition: value.h:983
VT_API size_t GetHash() const
Return a hash code for the held object by calling VtHashValue() on it.
void UncheckedSwap(VtValue &rhs)
Definition: value.h:1035
friend void swap(VtValue &lhs, VtValue &rhs)
Overloaded swap() for generic code/stl/etc.
Definition: value.h:995
bool CanCastToTypeid(std::type_info const &type) const
Return if this can be cast to type.
Definition: value.h:1239
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:1119
TfType represents a dynamic runtime type.
Definition: type.h:64
constexpr Integral BitsAs() const noexcept
Retrieve the stored bits as the integral type Integral.
friend bool operator !=(VtValue const &lhs, T const &rhs)
Tests for inequality.
Definition: value.h:1269
void Set(T *ptr) noexcept
Set the pointer value to ptr.
VtValue & CastToTypeid(std::type_info const &type)
Return this holding value type cast to type.
Definition: value.h:1217
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:872
T Remove()
Make this value empty and return the held T instance.
Definition: value.h:1041
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
Definition: value.h:1062
VT_API TfType GetType() const
Returns the TfType of the type held by this value.
T const & Get() const
Returns a const reference to the held object if the held object is of type T.
Definition: value.h:1101
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:168
A file containing basic constants and definitions.
VtValue & operator=(VtValue const &other)
Copy assignment from another VtValue.
Definition: value.h:924
bool TfSafeTypeCompare(const std::type_info &t1, const std::type_info &t2)
Safely compare std::type_info structures.