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 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 // XXX: Include pyLock.h after pyObjWrapper.h to work around
30 // Python include ordering issues.
32 
33 #include "pxr/base/tf/pyLock.h"
34 
35 #include "pxr/base/arch/demangle.h"
36 #include "pxr/base/arch/hints.h"
37 #include "pxr/base/arch/pragmas.h"
42 #include "pxr/base/tf/tf.h"
43 #include "pxr/base/tf/type.h"
44 
45 #include "pxr/base/vt/api.h"
46 #include "pxr/base/vt/hash.h"
47 #include "pxr/base/vt/streamOut.h"
48 #include "pxr/base/vt/traits.h"
49 #include "pxr/base/vt/types.h"
50 
51 #include <hboost/intrusive_ptr.hpp>
52 #include <hboost/type_traits/has_trivial_assign.hpp>
53 #include <hboost/type_traits/has_trivial_constructor.hpp>
54 #include <hboost/type_traits/has_trivial_copy.hpp>
55 #include <hboost/type_traits/has_trivial_destructor.hpp>
56 
57 #include <iosfwd>
58 #include <typeinfo>
59 #include <type_traits>
60 
62 
63 /// Make a default value.
64 /// VtValue uses this to create values to be returned from failed calls to \a
65 /// Get. Clients may specialize this for their own types.
66 template <class T>
68 
69 // This is a helper class used by Vt_DefaultValueFactory to return a value with
70 // its type erased and only known at runtime via a std::type_info.
72 {
73  // Creates a value-initialized object and stores the type_info for the
74  // static type.
75  template <typename T>
77  return Vt_DefaultValueHolder(TfAnyUniquePtr::New<T>(), typeid(T));
78  }
79 
80  // Creates a copy of the object and stores the type_info for the static
81  // type.
82  template <typename T>
83  static Vt_DefaultValueHolder Create(T const &val) {
84  return Vt_DefaultValueHolder(TfAnyUniquePtr::New(val), typeid(T));
85  }
86 
87  // Return the runtime type of the held object.
88  std::type_info const &GetType() const {
89  return *_type;
90  }
91 
92  // Return a pointer to the held object. This may be safely cast to the
93  // static type corresponding to the type_info returned by GetType.
94  void const *GetPointer() const {
95  return _ptr.Get();
96  }
97 
98 private:
99  Vt_DefaultValueHolder(TfAnyUniquePtr &&ptr, std::type_info const &type)
100  : _ptr(std::move(ptr)), _type(&type) {}
101 
102  TfAnyUniquePtr _ptr;
103  std::type_info const *_type;
104 };
105 
106 class VtValue;
107 
108 // Overload VtStreamOut for vector<VtValue>. Produces output like [value1,
109 // value2, ... valueN].
110 VT_API std::ostream &VtStreamOut(std::vector<VtValue> const &val, std::ostream &);
111 
112 #define VT_VALUE_SET_STORED_TYPE(SRC, DST) \
113  template <> struct Vt_ValueStoredType<SRC> { typedef DST Type; }
114 
115 template <class T> struct Vt_ValueStoredType { typedef T Type; };
118 
119 #ifdef PXR_PYTHON_SUPPORT_ENABLED
121 #endif // PXR_PYTHON_SUPPORT_ENABLED
122 
123 #undef VT_VALUE_SET_STORED_TYPE
124 
125 // A metafunction that gives the type VtValue should store for a given type T.
126 template <class T>
128  : Vt_ValueStoredType<std::decay_t<T>> {};
129 
130 /// Provides a container which may hold any type, and provides introspection
131 /// and iteration over array types. See \a VtIsArray for more info.
132 ///
133 /// \section VtValue_Casting Held-type Conversion with VtValue::Cast
134 ///
135 /// VtValue provides a suite of "Cast" methods that convert or create a
136 /// VtValue holding a requested type (via template parameter, typeid, or
137 /// type-matching to another VtValue) from the type of the currently-held
138 /// value. Clients can add conversions between their own types using the
139 /// RegisterCast(), RegisterSimpleCast(), and
140 /// RegisterSimpleBidirectionalCast() methods. Conversions from plugins can
141 /// be guaranteed to be registered before they are needed by registering them
142 /// from within a
143 /// \code
144 /// TF_REGISTRY_FUNCTION(VtValue) {
145 /// }
146 /// \endcode
147 /// block.
148 ///
149 /// \subsection VtValue_builtin_conversions Builtin Type Conversion
150 ///
151 /// Conversions between most of the basic "value types" that are intrinsically
152 /// convertible are builtin, including all numeric types (including Gf's \c
153 /// half), std::string/TfToken, GfVec* (for vecs of the same dimension), and
154 /// VtArray<T> for floating-point POD and GfVec of the preceding.
155 ///
156 /// \subsection VtValue_numeric_conversion Numeric Conversion Safety
157 ///
158 /// The conversions between all scalar numeric types are performed with range
159 /// checks such as provided by hboost::numeric_cast(), and will fail, returning
160 /// an empty VtValue if the source value is out of range of the destination
161 /// type.
162 ///
163 /// Conversions between GfVec and other compound-numeric types provide no more
164 /// or less safety or checking than the conversion constructors of the types
165 /// themselves. This includes VtArray, even VtArray<T> for T in scalar types
166 /// that are range-checked when held singly.
167 class VtValue
168 {
169  static const unsigned int _LocalFlag = 1 << 0;
170  static const unsigned int _TrivialCopyFlag = 1 << 1;
171  static const unsigned int _ProxyFlag = 1 << 2;
172 
173  template <class T>
174  struct _Counted {
175  explicit _Counted(T const &obj) : _obj(obj) {
176  _refCount = 0;
177  }
178  bool IsUnique() const { return _refCount == 1; }
179  T const &Get() const { return _obj; }
180  T &GetMutable() { return _obj; }
181 
182  private:
183  T _obj;
184  mutable std::atomic<int> _refCount;
185 
186  friend inline void intrusive_ptr_add_ref(_Counted const *d) {
187  d->_refCount.fetch_add(1, std::memory_order_relaxed);
188  }
189  friend inline void intrusive_ptr_release(_Counted const *d) {
190  if (d->_refCount.fetch_sub(1, std::memory_order_release) == 1) {
191  std::atomic_thread_fence(std::memory_order_acquire);
192  delete d;
193  }
194  }
195  };
196 
197  // Hold objects up to 1 word large locally. This makes the total structure
198  // 16 bytes when compiled 64 bit (1 word type-info pointer, 1 word storage
199  // space).
200  static const size_t _MaxLocalSize = sizeof(void*);
201  typedef std::aligned_storage<
202  /* size */_MaxLocalSize, /* alignment */_MaxLocalSize>::type _Storage;
203 
204  template <class T>
205  using _IsTriviallyCopyable = std::integral_constant<bool,
210 
211  // Metafunction that returns true if T should be stored locally, false if it
212  // should be stored remotely.
213  template <class T>
214  using _UsesLocalStore = std::integral_constant<bool,
215  (sizeof(T) <= sizeof(_Storage)) &&
219 
220  // Type information base class.
221  struct _TypeInfo {
222  private:
223  using _CopyInitFunc = void (*)(_Storage const &, _Storage &);
224  using _DestroyFunc = void (*)(_Storage &);
225  using _MoveFunc = void (*)(_Storage &, _Storage &);
226  using _CanHashFunc = bool (*)(_Storage const &);
227  using _HashFunc = size_t (*)(_Storage const &);
228  using _EqualFunc = bool (*)(_Storage const &, _Storage const &);
229  using _EqualPtrFunc = bool (*)(_Storage const &, void const *);
230  using _MakeMutableFunc = void (*)(_Storage &);
231  using _GetPyObjFunc = TfPyObjWrapper (*)(_Storage const &);
232  using _StreamOutFunc =
233  std::ostream & (*)(_Storage const &, std::ostream &);
234  using _GetTypeidFunc = std::type_info const & (*)(_Storage const &);
235  using _IsArrayValuedFunc = bool (*)(_Storage const &);
236  using _GetElementTypeidFunc =
237  std::type_info const & (*)(_Storage const &);
238  using _GetShapeDataFunc = const Vt_ShapeData* (*)(_Storage const &);
239  using _GetNumElementsFunc = size_t (*)(_Storage const &);
240  using _ProxyHoldsTypeFunc = bool (*)(_Storage const &, std::type_info const &);
241  using _GetProxiedTypeFunc = TfType (*)(_Storage const &);
242  using _GetProxiedTypeidFunc =
243  std::type_info const & (*)(_Storage const &);
244  using _GetProxiedObjPtrFunc = void const *(*)(_Storage const &);
245  using _GetProxiedAsVtValueFunc = VtValue (*)(_Storage const &);
246 
247  protected:
248  constexpr _TypeInfo(const std::type_info &ti,
249  const std::type_info &elementTi,
250  int knownTypeIndex,
251  bool isArray,
252  bool isHashable,
253  bool isProxy,
254  _CopyInitFunc copyInit,
255  _DestroyFunc destroy,
256  _MoveFunc move,
257  _CanHashFunc canHash,
258  _HashFunc hash,
259  _EqualFunc equal,
260  _EqualPtrFunc equalPtr,
261  _MakeMutableFunc makeMutable,
262  _GetPyObjFunc getPyObj,
263  _StreamOutFunc streamOut,
264  _GetTypeidFunc getTypeid,
265  _IsArrayValuedFunc isArrayValued,
266  _GetElementTypeidFunc getElementTypeid,
267  _GetShapeDataFunc getShapeData,
268  _GetNumElementsFunc getNumElements,
269  _ProxyHoldsTypeFunc proxyHoldsType,
270  _GetProxiedTypeFunc getProxiedType,
271  _GetProxiedTypeidFunc getProxiedTypeid,
272  _GetProxiedObjPtrFunc getProxiedObjPtr,
273  _GetProxiedAsVtValueFunc getProxiedAsVtValue)
274  : typeInfo(ti)
275  , elementTypeInfo(elementTi)
276  , knownTypeIndex(knownTypeIndex)
277  , isProxy(isProxy)
278  , isArray(isArray)
279  , isHashable(isHashable)
280  // Function table
281  , _copyInit(copyInit)
282  , _destroy(destroy)
283  , _move(move)
284  , _canHash(canHash)
285  , _hash(hash)
286  , _equal(equal)
287  , _equalPtr(equalPtr)
288  , _makeMutable(makeMutable)
289  , _getPyObj(getPyObj)
290  , _streamOut(streamOut)
291  , _getTypeid(getTypeid)
292  , _isArrayValued(isArrayValued)
293  , _getElementTypeid(getElementTypeid)
294  , _getShapeData(getShapeData)
295  , _getNumElements(getNumElements)
296  , _proxyHoldsType(proxyHoldsType)
297  , _getProxiedType(getProxiedType)
298  , _getProxiedTypeid(getProxiedTypeid)
299  , _getProxiedObjPtr(getProxiedObjPtr)
300  , _getProxiedAsVtValue(getProxiedAsVtValue)
301  {}
302 
303  public:
304  void CopyInit(_Storage const &src, _Storage &dst) const {
305  _copyInit(src, dst);
306  }
307  void Destroy(_Storage &storage) const {
308  _destroy(storage);
309  }
310  void Move(_Storage &src, _Storage &dst) const noexcept {
311  _move(src, dst);
312  }
313  bool CanHash(_Storage const &storage) const {
314  return _canHash(storage);
315  }
316  size_t Hash(_Storage const &storage) const {
317  return _hash(storage);
318  }
319  bool Equal(_Storage const &lhs, _Storage const &rhs) const {
320  return _equal(lhs, rhs);
321  }
322  bool EqualPtr(_Storage const &lhs, void const *rhs) const {
323  return _equalPtr(lhs, rhs);
324  }
325  void MakeMutable(_Storage &storage) const {
326  _makeMutable(storage);
327  }
328  TfPyObjWrapper GetPyObj(_Storage const &storage) const {
329  return _getPyObj(storage);
330  }
331  std::ostream &StreamOut(_Storage const &storage,
332  std::ostream &out) const {
333  return _streamOut(storage, out);
334  }
335  bool IsArrayValued(_Storage const &storage) const {
336  return _isArrayValued(storage);
337  }
338  std::type_info const &GetElementTypeid(_Storage const &storage) const {
339  return _getElementTypeid(storage);
340  }
341  std::type_info const &GetTypeid(_Storage const &storage) const {
342  return _getTypeid(storage);
343  }
344  const Vt_ShapeData* GetShapeData(_Storage const &storage) const {
345  return _getShapeData(storage);
346  }
347  size_t GetNumElements(_Storage const &storage) const {
348  return _getNumElements(storage);
349  }
350  bool ProxyHoldsType(_Storage const &storage,
351  std::type_info const &t) const {
352  return _proxyHoldsType(storage, t);
353  }
354  TfType GetProxiedType(_Storage const &storage) const {
355  return _getProxiedType(storage);
356  }
357  std::type_info const &GetProxiedTypeid(_Storage const &storage) const {
358  return _getProxiedTypeid(storage);
359  }
360  VtValue GetProxiedAsVtValue(_Storage const &storage) const {
361  return _getProxiedAsVtValue(storage);
362  }
363  void const *GetProxiedObjPtr(_Storage const &storage) const {
364  return _getProxiedObjPtr(storage);
365  }
366 
367  const std::type_info &typeInfo;
368  const std::type_info &elementTypeInfo;
369  int knownTypeIndex;
370  bool isProxy;
371  bool isArray;
372  bool isHashable;
373 
374  private:
375  _CopyInitFunc _copyInit;
376  _DestroyFunc _destroy;
377  _MoveFunc _move;
378  _CanHashFunc _canHash;
379  _HashFunc _hash;
380  _EqualFunc _equal;
381  _EqualPtrFunc _equalPtr;
382  _MakeMutableFunc _makeMutable;
383  _GetPyObjFunc _getPyObj;
384  _StreamOutFunc _streamOut;
385  _GetTypeidFunc _getTypeid;
386  _IsArrayValuedFunc _isArrayValued;
387  _GetElementTypeidFunc _getElementTypeid;
388  _GetShapeDataFunc _getShapeData;
389  _GetNumElementsFunc _getNumElements;
390  _ProxyHoldsTypeFunc _proxyHoldsType;
391  _GetProxiedTypeFunc _getProxiedType;
392  _GetProxiedTypeidFunc _getProxiedTypeid;
393  _GetProxiedObjPtrFunc _getProxiedObjPtr;
394  _GetProxiedAsVtValueFunc _getProxiedAsVtValue;
395  };
396 
397  // Type-dispatching overloads.
398 
399  // Array type helper.
400  template <class T, class Enable=void>
401  struct _ArrayHelper
402  {
403  static const Vt_ShapeData* GetShapeData(T const &) { return NULL; }
404  static size_t GetNumElements(T const &) { return 0; }
405  constexpr static std::type_info const &GetElementTypeid() {
406  return typeid(void);
407  }
408  };
409  template <class Array>
410  struct _ArrayHelper<
411  Array, typename std::enable_if<VtIsArray<Array>::value>::type>
412  {
413  static const Vt_ShapeData* GetShapeData(Array const &obj) {
414  return obj._GetShapeData();
415  }
416  static size_t GetNumElements(Array const &obj) {
417  return obj.size();
418  }
419  constexpr static std::type_info const &GetElementTypeid() {
420  return typeid(typename Array::ElementType);
421  }
422  };
423 
424  // Function used in case T has equality comparison.
425  template <class T>
426  static inline auto
427  _TypedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
428  return a == b;
429  }
430  // Function used in case T does not have equality comparison.
431  template <class NoEqual>
432  static inline bool
433  _TypedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
434  return VtGetProxiedObject(a) == VtGetProxiedObject(b);
435  }
436 
437  template <class T>
438  static inline auto
439  _ErasedProxyEqualityImpl(T const &a, T const &b, int) -> decltype(a == b) {
440  return a == b;
441  }
442  // Function used in case T does not have equality comparison.
443  template <class NoEqual>
444  static inline bool
445  _ErasedProxyEqualityImpl(NoEqual const &a, NoEqual const &b, long) {
446  return *VtGetErasedProxiedVtValue(a) == *VtGetErasedProxiedVtValue(b);
447  }
448 
449  // Proxy type helper. Base case handles non-proxies and typed proxies.
450  template <class T, class Enable = void>
451  struct _ProxyHelper
452  {
453  using ProxiedType = typename VtGetProxiedType<T>::type;
454 
455  static bool CanHash(T const &) { return VtIsHashable<ProxiedType>(); }
456  static size_t Hash(T const &obj) {
457  return VtHashValue(VtGetProxiedObject(obj));
458  }
459  static bool Equal(T const &a, T const &b) {
460  // We use the traditional int/long = 0 arg technique to disambiguate
461  // overloads, so we can invoke equality comparison on the *proxy*
462  // type if it provides one, or if it doesn't then invoke equality
463  // comparison on the *proxied* type instead.
464  return _TypedProxyEqualityImpl(a, b, 0);
465  }
466  static TfPyObjWrapper GetPyObj(T const &obj) {
467 #ifdef PXR_PYTHON_SUPPORT_ENABLED
468  ProxiedType const &p = VtGetProxiedObject(obj);
469  TfPyLock lock;
470  return hboost::python::api::object(p);
471 #else
472  return {};
473 #endif //PXR_PYTHON_SUPPORT_ENABLED
474  }
475  static std::ostream &StreamOut(T const &obj, std::ostream &out) {
476  return VtStreamOut(VtGetProxiedObject(obj), out);
477  }
478  static Vt_ShapeData const *GetShapeData(T const &obj) {
479  return _ArrayHelper<ProxiedType>::GetShapeData(
480  VtGetProxiedObject(obj));
481  }
482  static size_t GetNumElements(T const &obj) {
483  return _ArrayHelper<ProxiedType>::GetNumElements(
484  VtGetProxiedObject(obj));
485  }
486  static bool IsArrayValued(T const &) {
488  }
489  static std::type_info const &GetTypeid(T const &) {
490  return typeid(ProxiedType);
491  }
492  static std::type_info const &GetElementTypeid(T const &) {
493  return _ArrayHelper<ProxiedType>::GetElementTypeid();
494  }
495  static VtValue GetProxiedAsVtValue(T const &obj) {
496  return VtValue(VtGetProxiedObject(obj));
497  }
498  static bool HoldsType(T const &tp, std::type_info const &query) {
499  return TfSafeTypeCompare(typeid(ProxiedType), query);
500  }
501  static TfType GetTfType(T const &tp) {
502  return TfType::Find<ProxiedType>();
503  }
504  static void const *GetObjPtr(T const &tp) {
505  return static_cast<void const *>(&VtGetProxiedObject(tp));
506  }
507  };
508 
509  template <class ErasedProxy>
510  struct _ProxyHelper<
511  ErasedProxy, typename std::enable_if<
512  VtIsErasedValueProxy<ErasedProxy>::value>::type>
513  {
514  static bool CanHash(ErasedProxy const &proxy) {
515  return VtGetErasedProxiedVtValue(proxy)->CanHash();
516  }
517  static size_t Hash(ErasedProxy const &proxy) {
518  return VtGetErasedProxiedVtValue(proxy)->GetHash();
519  }
520  static bool Equal(ErasedProxy const &a, ErasedProxy const &b) {
521  // We use the traditional int/long = 0 arg technique to disambiguate
522  // overloads, so we can invoke equality comparison on the *proxy*
523  // type if it provides one, or if it doesn't then invoke equality
524  // comparison on the VtValue containing the *proxied* type instead.
525  return _ErasedProxyEqualityImpl(a, b, 0);
526  }
527  static TfPyObjWrapper GetPyObj(ErasedProxy const &obj) {
528 #ifdef PXR_PYTHON_SUPPORT_ENABLED
529  VtValue const *val = VtGetErasedProxiedVtValue(obj);
530  TfPyLock lock;
531  return hboost::python::api::object(*val);
532 #else
533  return {};
534 #endif //PXR_PYTHON_SUPPORT_ENABLED
535  }
536  static std::ostream &
537  StreamOut(ErasedProxy const &obj, std::ostream &out) {
538  return VtStreamOut(obj, out);
539  }
540  static Vt_ShapeData const *GetShapeData(ErasedProxy const &obj) {
541  return VtGetErasedProxiedVtValue(obj)->_GetShapeData();
542  }
543  static size_t GetNumElements(ErasedProxy const &obj) {
544  return VtGetErasedProxiedVtValue(obj)->_GetNumElements();
545  }
546  static bool IsArrayValued(ErasedProxy const &obj) {
547  return VtGetErasedProxiedVtValue(obj)->IsArrayValued();
548  }
549  static std::type_info const &GetTypeid(ErasedProxy const &obj) {
550  return VtGetErasedProxiedVtValue(obj)->GetTypeid();
551  }
552  static std::type_info const &GetElementTypeid(ErasedProxy const &obj) {
553  return VtGetErasedProxiedVtValue(obj)->GetElementTypeid();
554  }
555  static VtValue GetProxiedAsVtValue(ErasedProxy const &ep) {
556  return *VtGetErasedProxiedVtValue(ep);
557  }
558  static bool
559  HoldsType(ErasedProxy const &ep, std::type_info const &query) {
560  return VtErasedProxyHoldsType(ep, query);
561  }
562  static TfType GetTfType(ErasedProxy const &ep) {
563  return VtGetErasedProxiedTfType(ep);
564  }
565  static void const *GetObjPtr(ErasedProxy const &ep) {
566  VtValue const *val = VtGetErasedProxiedVtValue(ep);
567  return val ? val->_GetProxiedObjPtr() : nullptr;
568  }
569  };
570 
571  // _TypeInfo implementation helper. This is a CRTP base that the
572  // _LocalTypeInfo and _RemoteTypeInfo types derive. It wraps their
573  // type-specific implementations with type-generic interfaces.
574  template <class T, class Container, class Derived>
575  struct _TypeInfoImpl : public _TypeInfo
576  {
577  static const bool IsLocal = _UsesLocalStore<T>::value;
578  static const bool HasTrivialCopy = _IsTriviallyCopyable<T>::value;
579  static const bool IsProxy = VtIsValueProxy<T>::value;
580 
581  using ProxyHelper = _ProxyHelper<T>;
582 
583  using This = _TypeInfoImpl;
584 
585  constexpr _TypeInfoImpl()
586  : _TypeInfo(typeid(T),
587  _ArrayHelper<T>::GetElementTypeid(),
588  Vt_KnownValueTypeDetail::GetIndex<T>(),
590  VtIsHashable<T>(),
591  IsProxy,
592  &This::_CopyInit,
593  &This::_Destroy,
594  &This::_Move,
595  &This::_CanHash,
596  &This::_Hash,
597  &This::_Equal,
598  &This::_EqualPtr,
599  &This::_MakeMutable,
600  &This::_GetPyObj,
601  &This::_StreamOut,
602 
603  &This::_GetTypeid,
604 
605  // Array support.
606  &This::_IsArrayValued,
607  &This::_GetElementTypeid,
608  &This::_GetShapeData,
609  &This::_GetNumElements,
610 
611  // Proxy support.
612  &This::_ProxyHoldsType,
613  &This::_GetProxiedType,
614  &This::_GetProxiedTypeid,
615  &This::_GetProxiedObjPtr,
616  &This::_GetProxiedAsVtValue)
617  {}
618 
619  ////////////////////////////////////////////////////////////////////
620  // Typed API for client use.
621  static T const &GetObj(_Storage const &storage) {
622  return Derived::_GetObj(_Container(storage));
623  }
624 
625  static T &GetMutableObj(_Storage &storage) {
626  return Derived::_GetMutableObj(_Container(storage));
627  }
628 
629  static void CopyInitObj(T const &objSrc, _Storage &dst) {
630  Derived::_PlaceCopy(&_Container(dst), objSrc);
631  }
632 
633  private:
634  static_assert(sizeof(Container) <= sizeof(_Storage),
635  "Container size cannot exceed storage size.");
636 
637  ////////////////////////////////////////////////////////////////////
638  // _TypeInfo interface function implementations.
639  static void _CopyInit(_Storage const &src, _Storage &dst) {
640  new (&_Container(dst)) Container(_Container(src));
641  }
642 
643  static void _Destroy(_Storage &storage) {
644  _Container(storage).~Container();
645  }
646 
647  static bool _CanHash(_Storage const &storage) {
648  return ProxyHelper::CanHash(GetObj(storage));
649  }
650 
651  static size_t _Hash(_Storage const &storage) {
652  return ProxyHelper::Hash(GetObj(storage));
653  }
654 
655  static bool _Equal(_Storage const &lhs, _Storage const &rhs) {
656  // Equal is only ever invoked with an object of this specific type.
657  // That is, we only ever ask a proxy to compare to a proxy; we never
658  // ask a proxy to compare to the proxied object.
659  return ProxyHelper::Equal(GetObj(lhs), GetObj(rhs));
660  }
661 
662  static bool _EqualPtr(_Storage const &lhs, void const *rhs) {
663  // Equal is only ever invoked with an object of this specific type.
664  // That is, we only ever ask a proxy to compare to a proxy; we never
665  // ask a proxy to compare to the proxied object.
666  return ProxyHelper::Equal(
667  GetObj(lhs), *static_cast<T const *>(rhs));
668  }
669 
670  static void _Move(_Storage &src, _Storage &dst) noexcept {
671  new (&_Container(dst)) Container(std::move(_Container(src)));
672  _Destroy(src);
673  }
674 
675  static void _MakeMutable(_Storage &storage) {
676  GetMutableObj(storage);
677  }
678 
679  static TfPyObjWrapper _GetPyObj(_Storage const &storage) {
680  return ProxyHelper::GetPyObj(GetObj(storage));
681  }
682 
683  static std::ostream &_StreamOut(
684  _Storage const &storage, std::ostream &out) {
685  return ProxyHelper::StreamOut(GetObj(storage), out);
686  }
687 
688  static std::type_info const &_GetTypeid(_Storage const &storage) {
689  return ProxyHelper::GetTypeid(GetObj(storage));
690  }
691 
692  static bool _IsArrayValued(_Storage const &storage) {
693  return ProxyHelper::IsArrayValued(GetObj(storage));
694  }
695 
696  static std::type_info const &
697  _GetElementTypeid(_Storage const &storage) {
698  return ProxyHelper::GetElementTypeid(GetObj(storage));
699  }
700 
701  static const Vt_ShapeData* _GetShapeData(_Storage const &storage) {
702  return ProxyHelper::GetShapeData(GetObj(storage));
703  }
704 
705  static size_t _GetNumElements(_Storage const &storage) {
706  return ProxyHelper::GetNumElements(GetObj(storage));
707  }
708 
709  static bool
710  _ProxyHoldsType(_Storage const &storage, std::type_info const &t) {
711  return ProxyHelper::HoldsType(GetObj(storage), t);
712  }
713 
714  static TfType
715  _GetProxiedType(_Storage const &storage) {
716  return ProxyHelper::GetTfType(GetObj(storage));
717  }
718 
719  static std::type_info const &
720  _GetProxiedTypeid(_Storage const &storage) {
721  return ProxyHelper::GetTypeid(GetObj(storage));
722  }
723 
724  static void const *
725  _GetProxiedObjPtr(_Storage const &storage) {
726  return ProxyHelper::GetObjPtr(GetObj(storage));
727  }
728 
729  static VtValue
730  _GetProxiedAsVtValue(_Storage const &storage) {
731  return ProxyHelper::GetProxiedAsVtValue(GetObj(storage));
732  }
733 
734  ////////////////////////////////////////////////////////////////////
735  // Internal helper -- cast type-generic storage to type-specific
736  // container.
737  static Container &_Container(_Storage &storage) {
738  // XXX Will need std::launder in c++17.
739  return *reinterpret_cast<Container *>(&storage);
740  }
741  static Container const &_Container(_Storage const &storage) {
742  // XXX Will need std::launder in c++17.
743  return *reinterpret_cast<Container const *>(&storage);
744  }
745  };
746 
747  ////////////////////////////////////////////////////////////////////////
748  // Local-storage type info implementation. The container and the object are
749  // the same -- there is no distinct container.
750  template <class T>
751  struct _LocalTypeInfo : _TypeInfoImpl<
752  T, // type
753  T, // container
754  _LocalTypeInfo<T> // CRTP
755  >
756  {
757  constexpr _LocalTypeInfo()
758  : _TypeInfoImpl<T, T, _LocalTypeInfo<T>>()
759  {}
760 
761  // Get returns object directly.
762  static T &_GetMutableObj(T &obj) { return obj; }
763  static T const &_GetObj(T const &obj) { return obj; }
764  // Place placement new's object directly.
765  static void _PlaceCopy(T *dst, T const &src) { new (dst) T(src); }
766  };
767 
768  ////////////////////////////////////////////////////////////////////////
769  // Remote-storage type info implementation. The container is an
770  // intrusive_ptr to an object holder: _Counted<T>.
771  template <class T>
772  struct _RemoteTypeInfo : _TypeInfoImpl<
773  T, // type
774  hboost::intrusive_ptr<_Counted<T> >, // container
775  _RemoteTypeInfo<T> // CRTP
776  >
777  {
778  constexpr _RemoteTypeInfo()
779  : _TypeInfoImpl<
780  T, hboost::intrusive_ptr<_Counted<T>>, _RemoteTypeInfo<T>>()
781  {}
782 
783  typedef hboost::intrusive_ptr<_Counted<T> > Ptr;
784  // Get returns object stored in the pointed-to _Counted<T>.
785  static T &_GetMutableObj(Ptr &ptr) {
786  if (!ptr->IsUnique())
787  ptr.reset(new _Counted<T>(ptr->Get()));
788  return ptr->GetMutable();
789  }
790  static T const &_GetObj(Ptr const &ptr) { return ptr->Get(); }
791  // PlaceCopy() allocates a new _Counted<T> with a copy of the object.
792  static void _PlaceCopy(Ptr *dst, T const &src) {
793  new (dst) Ptr(new _Counted<T>(src));
794  }
795  };
796 
797  // Metafunction that returns the specific _TypeInfo subclass for T.
798  template <class T>
799  struct _TypeInfoFor {
800  // return _UsesLocalStore(T) ? _LocalTypeInfo<T> : _RemoteTypeInfo<T>;
802  _LocalTypeInfo<T>,
803  _RemoteTypeInfo<T>> Type;
804  };
805 
806  // Make sure char[N] is treated as a string.
807  template <size_t N>
808  struct _TypeInfoFor<char[N]> : _TypeInfoFor<std::string> {};
809 
810  // Runtime function to return a _TypeInfo base pointer to a specific
811  // _TypeInfo subclass for type T.
812  template <class T>
813  static TfPointerAndBits<const _TypeInfo> GetTypeInfo() {
814  typedef typename _TypeInfoFor<T>::Type TI;
815  static const TI ti;
816  static constexpr unsigned int flags =
817  (TI::IsLocal ? _LocalFlag : 0) |
818  (TI::HasTrivialCopy ? _TrivialCopyFlag : 0) |
819  (TI::IsProxy ? _ProxyFlag : 0);
821  }
822 
823  // A helper that moves a held value to temporary storage, but keeps it alive
824  // until the _HoldAside object is destroyed. This is used when assigning
825  // over a VtValue that might own the object being assigned. For instance,
826  // if I have a VtValue holding a map<string, VtValue>, and I reassign this
827  // VtValue with one of the elements from the map, we must ensure that the
828  // map isn't destroyed until after the assignment has taken place.
829  friend struct _HoldAside;
830  struct _HoldAside {
831  explicit _HoldAside(VtValue *val)
832  : info((val->IsEmpty() || val->_IsLocalAndTriviallyCopyable())
833  ? static_cast<_TypeInfo const *>(NULL) : val->_info.Get()) {
834  if (info)
835  info->Move(val->_storage, storage);
836  }
837  ~_HoldAside() {
838  if (info)
839  info->Destroy(storage);
840  }
841  _Storage storage;
842  _TypeInfo const *info;
843  };
844 
845  template <class T>
848  _Init(T const &obj) {
849  _info = GetTypeInfo<T>();
850  typedef typename _TypeInfoFor<T>::Type TypeInfo;
851  TypeInfo::CopyInitObj(obj, _storage);
852  }
853 
854  template <class T>
857  _Init(T const &obj) {
858  _Init(typename Vt_ValueGetStored<T>::Type(obj));
859  }
860 
861 public:
862 
863  /// Default ctor gives empty VtValue.
864  VtValue() {}
865 
866  /// Copy construct with \p other.
867  VtValue(VtValue const &other) {
868  _Copy(other, *this);
869  }
870 
871  /// Move construct with \p other.
872  VtValue(VtValue &&other) noexcept {
873  _Move(other, *this);
874  }
875 
876  /// Construct a VtValue holding a copy of \p obj.
877  ///
878  /// If T is a char pointer or array, produce a VtValue holding a
879  /// std::string. If T is hboost::python::object, produce a VtValue holding
880  /// a TfPyObjWrapper.
881  template <class T>
882  explicit VtValue(T const &obj) {
883  _Init(obj);
884  }
885 
886  /// Create a new VtValue, taking its contents from \p obj.
887  ///
888  /// This is equivalent to creating a VtValue holding a value-initialized
889  /// \p T instance, then invoking swap(<held-value>, obj), leaving obj in a
890  /// default-constructed (value-initialized) state. In the case that \p
891  /// obj is expensive to copy, it may be significantly faster to use this
892  /// idiom when \p obj need not retain its contents:
893  ///
894  /// \code
895  /// MyExpensiveObject obj = CreateObject();
896  /// return VtValue::Take(obj);
897  /// \endcode
898  ///
899  /// Rather than:
900  ///
901  /// \code
902  /// MyExpensiveObject obj = CreateObject();
903  /// return VtValue(obj);
904  /// \endcode
905  template <class T>
906  static VtValue Take(T &obj) {
907  VtValue ret;
908  ret.Swap(obj);
909  return ret;
910  }
911 
912  /// Destructor.
913  ~VtValue() { _Clear(); }
914 
915  /// Copy assignment from another \a VtValue.
916  VtValue &operator=(VtValue const &other) {
917  if (ARCH_LIKELY(this != &other))
918  _Copy(other, *this);
919  return *this;
920  }
921 
922  /// Move assignment from another \a VtValue.
923  VtValue &operator=(VtValue &&other) noexcept {
924  if (ARCH_LIKELY(this != &other))
925  _Move(other, *this);
926  return *this;
927  }
928 
929 #ifndef doxygen
930  template <class T>
931  inline
933  _TypeInfoFor<T>::Type::IsLocal &&
934  _TypeInfoFor<T>::Type::HasTrivialCopy,
935  VtValue &>
936  operator=(T obj) {
937  _Clear();
938  _Init(obj);
939  return *this;
940  }
941 #endif
942 
943  /// Assignment operator from any type.
944 #ifdef doxygen
945  template <class T>
946  VtValue&
947  operator=(T const &obj);
948 #else
949  template <class T>
951  !_TypeInfoFor<T>::Type::IsLocal ||
952  !_TypeInfoFor<T>::Type::HasTrivialCopy,
953  VtValue &>
954  operator=(T const &obj) {
955  _HoldAside tmp(this);
956  _Init(obj);
957  return *this;
958  }
959 #endif
960 
961  /// Assigning a char const * gives a VtValue holding a std::string.
962  VtValue &operator=(char const *cstr) {
963  std::string tmp(cstr);
964  _Clear();
965  _Init(tmp);
966  return *this;
967  }
968 
969  /// Assigning a char * gives a VtValue holding a std::string.
970  VtValue &operator=(char *cstr) {
971  return *this = const_cast<char const *>(cstr);
972  }
973 
974  /// Swap this with \a rhs.
975  VtValue &Swap(VtValue &rhs) noexcept {
976  // Do nothing if both empty. Otherwise general swap.
977  if (!IsEmpty() || !rhs.IsEmpty()) {
978  VtValue tmp;
979  _Move(*this, tmp);
980  _Move(rhs, *this);
981  _Move(tmp, rhs);
982  }
983  return *this;
984  }
985 
986  /// Overloaded swap() for generic code/stl/etc.
987  friend void swap(VtValue &lhs, VtValue &rhs) { lhs.Swap(rhs); }
988 
989  /// Swap the held value with \a rhs. If this value is holding a T,
990  // make an unqualified call to swap(<held-value>, rhs). If this value is
991  // not holding a T, replace the held value with a value-initialized T
992  // instance first, then swap.
993 #ifdef doxygen
994  template <class T>
995  void
996  Swap(T &rhs);
997 #else
998  template <class T>
1001  Swap(T &rhs) {
1002  if (!IsHolding<T>())
1003  *this = T();
1004  UncheckedSwap(rhs);
1005  }
1006 #endif
1007 
1008  /// Swap the held value with \a rhs. This VtValue must be holding an
1009  /// object of type \p T. If it does not, this invokes undefined behavior.
1010  /// Use Swap() if this VtValue is not known to contain an object of type
1011  /// \p T.
1012 #ifdef doxygen
1013  template <class T>
1014  void
1015  UncheckedSwap(T &rhs);
1016 #else
1017  template <class T>
1021  using std::swap;
1022  swap(_GetMutable<T>(), rhs);
1023  }
1024 #endif
1025 
1026  /// \overload
1027  void UncheckedSwap(VtValue &rhs) { Swap(rhs); }
1028 
1029  /// Make this value empty and return the held \p T instance. If
1030  /// this value does not hold a \p T instance, make this value empty and
1031  /// return a default-constructed \p T.
1032  template <class T>
1033  T Remove() {
1034  T result;
1035  Swap(result);
1036  _Clear();
1037  return result;
1038  }
1039 
1040  /// Make this value empty and return the held \p T instance. If this
1041  /// value does not hold a \p T instance, this method invokes undefined
1042  /// behavior.
1043  template <class T>
1045  T result;
1046  UncheckedSwap(result);
1047  _Clear();
1048  return result;
1049  }
1050 
1051  /// Return true if this value is holding an object of type \p T, false
1052  /// otherwise.
1053  template <class T>
1054  bool IsHolding() const {
1055  return _info.GetLiteral() && _TypeIs<T>();
1056  }
1057 
1058  /// Returns true iff this is holding an array type (see VtIsArray<>).
1059  VT_API bool IsArrayValued() const;
1060 
1061  /// Return the number of elements in the held value if IsArrayValued(),
1062  /// return 0 otherwise.
1063  size_t GetArraySize() const { return _GetNumElements(); }
1064 
1065  /// Returns the typeid of the type held by this value.
1066  VT_API std::type_info const &GetTypeid() const;
1067 
1068  /// Return the typeid of elements in a array valued type. If not
1069  /// holding an array valued type, return typeid(void).
1070  VT_API std::type_info const &GetElementTypeid() const;
1071 
1072  /// Returns the TfType of the type held by this value.
1073  VT_API TfType GetType() const;
1074 
1075  /// Return the type name of the held typeid.
1076  VT_API std::string GetTypeName() const;
1077 
1078  /// Return VtKnownValueTypeIndex<T> for the held type T. If this value
1079  /// holds a proxy type, resolve the proxy and return the proxied type's
1080  /// index. If this value is empty or holds a type that is not 'known',
1081  /// return -1.
1083  if (ARCH_UNLIKELY(_IsProxy())) {
1084  return _info->GetProxiedAsVtValue(
1085  _storage).GetKnownValueTypeIndex();
1086  }
1087  return _info.GetLiteral() ? _info->knownTypeIndex : -1;
1088  }
1089 
1090  /// Returns a const reference to the held object if the held object
1091  /// is of type \a T. Invokes undefined behavior otherwise. This is the
1092  /// fastest \a Get() method to use after a successful \a IsHolding() check.
1093  template <class T>
1094  T const &UncheckedGet() const & { return _Get<T>(); }
1095 
1096  /// \overload In case *this is an rvalue, move the held value out and return
1097  /// by value.
1098  template <class T>
1099  T UncheckedGet() && { return UncheckedRemove<T>(); }
1100 
1101  /// Returns a const reference to the held object if the held object
1102  /// is of type \a T. Issues an error and returns a const reference to a
1103  /// default value if the held object is not of type \a T. Use \a IsHolding
1104  /// to verify correct type before calling this function. The default value
1105  /// returned in case of type mismatch is constructed using
1106  /// Vt_DefaultValueFactory<T>. That may be specialized for client types.
1107  /// The default implementation of the default value factory produces a
1108  /// value-initialized T.
1109  template <class T>
1110  T const &Get() const & {
1112 
1113  // In the unlikely case that the types don't match, we obtain a default
1114  // value to return and issue an error via _FailGet.
1115  if (ARCH_UNLIKELY(!IsHolding<T>())) {
1116  return *(static_cast<T const *>(
1117  _FailGet(Factory::Invoke, typeid(T))));
1118  }
1119 
1120  return _Get<T>();
1121  }
1122 
1123  /// \overload In case *this is an rvalue, move the held value out and return
1124  /// by value.
1125  template <class T>
1126  T Get() && {
1128 
1129  // In the unlikely case that the types don't match, we obtain a default
1130  // value to return and issue an error via _FailGet.
1131  if (ARCH_UNLIKELY(!IsHolding<T>())) {
1132  return *(static_cast<T const *>(
1133  _FailGet(Factory::Invoke, typeid(T))));
1134  }
1135 
1136  return UncheckedRemove<T>();
1137  }
1138 
1139  /// Return a copy of the held object if the held object is of type T.
1140  /// Return a copy of the default value \a def otherwise. Note that this
1141  /// always returns a copy, as opposed to \a Get() which always returns a
1142  /// reference.
1143  template <class T>
1144  T GetWithDefault(T const &def = T()) const {
1145  return IsHolding<T>() ? UncheckedGet<T>() : def;
1146  }
1147 
1148  /// Register a cast from VtValue holding From to VtValue holding To.
1149  template <typename From, typename To>
1150  static void RegisterCast(VtValue (*castFn)(VtValue const &)) {
1151  _RegisterCast(typeid(From), typeid(To), castFn);
1152  }
1153 
1154  /// Register a simple cast from VtValue holding From to VtValue
1155  // holding To.
1156  template <typename From, typename To>
1157  static void RegisterSimpleCast() {
1158  _RegisterCast(typeid(From), typeid(To), _SimpleCast<From, To>);
1159  }
1160 
1161  /// Register a two-way cast from VtValue holding From to VtValue
1162  /// holding To.
1163  template <typename From, typename To>
1165  RegisterSimpleCast<From, To>();
1166  RegisterSimpleCast<To, From>();
1167  }
1168 
1169  /// Return a VtValue holding \c val cast to hold T. Return empty VtValue
1170  /// if cast fails.
1171  ///
1172  /// This Cast() function is safe to call in multiple threads as it does
1173  /// not mutate the operant \p val.
1174  ///
1175  /// \sa \ref VtValue_Casting
1176  template <typename T>
1177  static VtValue Cast(VtValue const &val) {
1178  VtValue ret = val;
1179  return ret.Cast<T>();
1180  }
1181 
1182  /// Return a VtValue holding \c val cast to same type that \c other is
1183  /// holding. Return empty VtValue if cast fails.
1184  ///
1185  /// This Cast() function is safe to call in multiple threads as it does not
1186  /// mutate the operant \p val.
1187  ///
1188  /// \sa \ref VtValue_Casting
1189  VT_API static VtValue
1190  CastToTypeOf(VtValue const &val, VtValue const &other);
1191 
1192  /// Return a VtValue holding \a val cast to \a type. Return empty VtValue
1193  /// if cast fails.
1194  ///
1195  /// This Cast() function is safe to call in multiple threads as it does not
1196  /// mutate the operant \p val.
1197  ///
1198  /// \sa \ref VtValue_Casting
1199  VT_API static VtValue
1200  CastToTypeid(VtValue const &val, std::type_info const &type);
1201 
1202  /// Return if a value of type \a from can be cast to type \a to.
1203  ///
1204  /// \sa \ref VtValue_Casting
1205  static bool CanCastFromTypeidToTypeid(std::type_info const &from,
1206  std::type_info const &to) {
1207  return _CanCast(from, to);
1208  }
1209 
1210  /// Return \c this holding value type cast to T. This value is left
1211  /// empty if the cast fails.
1212  ///
1213  /// \note Since this method mutates this value, it is not safe to invoke on
1214  /// the same VtValue in multiple threads simultaneously.
1215  ///
1216  /// \sa \ref VtValue_Casting
1217  template <typename T>
1219  if (IsHolding<T>())
1220  return *this;
1221  return *this = _PerformCast(typeid(T), *this);
1222  }
1223 
1224  /// Return \c this holding value type cast to same type that
1225  /// \c other is holding. This value is left empty if the cast fails.
1226  ///
1227  /// \note Since this method mutates this value, it is not safe to invoke on
1228  /// the same VtValue in multiple threads simultaneously.
1229  ///
1230  /// \sa \ref VtValue_Casting
1231  VtValue &CastToTypeOf(VtValue const &other) {
1232  return CastToTypeid(other.GetTypeid());
1233  }
1234 
1235  /// Return \c this holding value type cast to \a type. This value is
1236  /// left empty if the cast fails.
1237  ///
1238  /// \note Since this method mutates this value, it is not safe to invoke on
1239  /// the same VtValue in multiple threads simultaneously.
1240  ///
1241  /// \sa \ref VtValue_Casting
1242  VtValue &CastToTypeid(std::type_info const &type) {
1243  if (!TfSafeTypeCompare(GetTypeid(), type)) {
1244  *this = _PerformCast(type, *this);
1245  }
1246  return *this;
1247  }
1248 
1249  /// Return if \c this can be cast to \a T.
1250  ///
1251  /// \sa \ref VtValue_Casting
1252  template <typename T>
1253  bool CanCast() const {
1254  return _CanCast(GetTypeid(), typeid(T));
1255  }
1256 
1257  /// Return if \c this can be cast to \a type.
1258  ///
1259  /// \sa \ref VtValue_Casting
1260  bool CanCastToTypeOf(VtValue const &other) const {
1261  return _CanCast(GetTypeid(), other.GetTypeid());
1262  }
1263 
1264  /// Return if \c this can be cast to \a type.
1265  ///
1266  /// \sa \ref VtValue_Casting
1267  bool CanCastToTypeid(std::type_info const &type) const {
1268  return _CanCast(GetTypeid(), type);
1269  }
1270 
1271  /// Returns true iff this value is empty.
1272  bool IsEmpty() const { return _info.GetLiteral() == 0; }
1273 
1274  /// Return true if the held object provides a hash implementation.
1275  VT_API bool CanHash() const;
1276 
1277  /// Return a hash code for the held object by calling VtHashValue() on it.
1278  VT_API size_t GetHash() const;
1279 
1280  friend inline size_t hash_value(VtValue const &val) {
1281  return val.GetHash();
1282  }
1283 
1284  /// Tests for equality.
1285  template <typename T>
1286  friend bool operator == (VtValue const &lhs, T const &rhs) {
1287  typedef typename Vt_ValueGetStored<T>::Type Stored;
1288  return lhs.IsHolding<Stored>() && lhs.UncheckedGet<Stored>() == rhs;
1289  }
1290  template <typename T>
1291  friend bool operator == (T const &lhs, VtValue const &rhs) {
1292  return rhs == lhs;
1293  }
1294 
1295  /// Tests for inequality.
1296  template <typename T>
1297  friend bool operator != (VtValue const &lhs, T const &rhs) {
1298  return !(lhs == rhs);
1299  }
1300  template <typename T>
1301  friend bool operator != (T const &lhs, VtValue const &rhs) {
1302  return !(lhs == rhs);
1303  }
1304 
1305  /// Test two values for equality.
1306  bool operator == (const VtValue &rhs) const {
1307  bool empty = IsEmpty(), rhsEmpty = rhs.IsEmpty();
1308  if (empty || rhsEmpty) {
1309  // Either one or both empty -- only equal if both empty.
1310  return empty == rhsEmpty;
1311  }
1312  if (_info.GetLiteral() == rhs._info.GetLiteral()) {
1313  // Holding identical types -- compare directly.
1314  return _info.Get()->Equal(_storage, rhs._storage);
1315  }
1316  return _EqualityImpl(rhs);
1317  }
1318  bool operator != (const VtValue &rhs) const { return !(*this == rhs); }
1319 
1320  /// Calls through to operator << on the held object.
1321  VT_API friend std::ostream &
1322  operator << (std::ostream &out, const VtValue &self);
1323 
1324 private:
1325  VT_API const Vt_ShapeData* _GetShapeData() const;
1326  VT_API size_t _GetNumElements() const;
1328 
1329  static inline void _Copy(VtValue const &src, VtValue &dst) {
1330  if (src.IsEmpty()) {
1331  dst._Clear();
1332  return;
1333  }
1334 
1335  _HoldAside tmp(&dst);
1336  dst._info = src._info;
1337  if (src._IsLocalAndTriviallyCopyable()) {
1338  dst._storage = src._storage;
1339  } else {
1340  dst._info->CopyInit(src._storage, dst._storage);
1341  }
1342  }
1343 
1344  static inline void _Move(VtValue &src, VtValue &dst) noexcept {
1345  if (src.IsEmpty()) {
1346  dst._Clear();
1347  return;
1348  }
1349 
1350  _HoldAside tmp(&dst);
1351  dst._info = src._info;
1352  if (src._IsLocalAndTriviallyCopyable()) {
1353  dst._storage = src._storage;
1354  } else {
1355  dst._info->Move(src._storage, dst._storage);
1356  }
1357 
1358  src._info.Set(nullptr, 0);
1359  }
1360 
1361  template <class T>
1363  _TypeIs() const {
1364  return _info->knownTypeIndex == VtGetKnownValueTypeIndex<T>() ||
1365  ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(typeid(T)));
1366  }
1367 
1368  template <class T>
1370  _TypeIs() const {
1371  std::type_info const &t = typeid(T);
1372  return TfSafeTypeCompare(_info->typeInfo, t) ||
1373  ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(t));
1374  }
1375 
1376  VT_API bool _TypeIsImpl(std::type_info const &queriedType) const;
1377 
1378  VT_API bool _EqualityImpl(VtValue const &rhs) const;
1379 
1380  template <class Proxy>
1382  _GetMutable() {
1383  typedef typename _TypeInfoFor<Proxy>::Type TypeInfo;
1384  return TypeInfo::GetMutableObj(_storage);
1385  }
1386 
1387  template <class T>
1389  _GetMutable() {
1390  // If we are a proxy, collapse it out to the real value first.
1391  if (ARCH_UNLIKELY(_IsProxy())) {
1392  *this = _info->GetProxiedAsVtValue(_storage);
1393  }
1394  typedef typename _TypeInfoFor<T>::Type TypeInfo;
1395  return TypeInfo::GetMutableObj(_storage);
1396  }
1397 
1398  template <class Proxy>
1400  _Get() const {
1401  typedef typename _TypeInfoFor<Proxy>::Type TypeInfo;
1402  return TypeInfo::GetObj(_storage);
1403  }
1404 
1405  template <class T>
1407  _Get() const {
1408  typedef typename _TypeInfoFor<T>::Type TypeInfo;
1409  if (ARCH_UNLIKELY(_IsProxy())) {
1410  return *static_cast<T const *>(_GetProxiedObjPtr());
1411  }
1412  return TypeInfo::GetObj(_storage);
1413  }
1414 
1415  void const *_GetProxiedObjPtr() const {
1416  return _info->GetProxiedObjPtr(_storage);
1417  }
1418 
1419  // Helper invoked in case Get fails. Reports an error and returns a default
1420  // value for \a queryType.
1421  VT_API void const *
1422  _FailGet(Vt_DefaultValueHolder (*factory)(),
1423  std::type_info const &queryType) const;
1424 
1425  inline void _Clear() {
1426  // optimize for local types not to deref _info.
1428 // XXX: http://bug/DEV-16695
1430  if (_info.GetLiteral() && !_IsLocalAndTriviallyCopyable())
1431  _info.Get()->Destroy(_storage);
1433  _info.Set(nullptr, 0);
1434  }
1435 
1436  inline bool _IsLocalAndTriviallyCopyable() const {
1437  unsigned int bits = _info.BitsAs<unsigned int>();
1438  return (bits & (_LocalFlag | _TrivialCopyFlag)) ==
1439  (_LocalFlag | _TrivialCopyFlag);
1440  }
1441 
1442  inline bool _IsProxy() const {
1443  return _info.BitsAs<unsigned int>() & _ProxyFlag;
1444  }
1445 
1446  VT_API static void _RegisterCast(std::type_info const &from,
1447  std::type_info const &to,
1448  VtValue (*castFn)(VtValue const &));
1449 
1450  // Cast \p value to the type \p to. Caller must ensure that val's type is
1451  // not already \p to.
1452  VT_API static VtValue
1453  _PerformCast(std::type_info const &to, VtValue const &val);
1454 
1455  // Return true if \p from == \p to or if there is a registered cast to
1456  // convert VtValues holding \p from to \p to.
1457  VT_API static bool
1458  _CanCast(std::type_info const &from, std::type_info const &to);
1459 
1460  // helper template function for simple casts from From to To.
1461  template <typename From, typename To>
1462  static VtValue _SimpleCast(VtValue const &val) {
1463  return VtValue(To(val.UncheckedGet<From>()));
1464  }
1465 
1466  // This grants friend access to a function in the wrapper file for this
1467  // class. This lets the wrapper reach down into a value to get a
1468  // hboost::python wrapped object corresponding to the held type. This
1469  // facility is necessary to get the python API we want.
1470  friend TfPyObjWrapper
1472 
1473  VT_API TfPyObjWrapper _GetPythonObject() const;
1474 
1475  _Storage _storage;
1477 };
1478 
1479 #ifndef doxygen
1480 
1482  static const Vt_ShapeData* _GetShapeData(const VtValue& value) {
1483  return value._GetShapeData();
1484  }
1485 
1486  static size_t _GetNumElements(const VtValue& value) {
1487  return value._GetNumElements();
1488  }
1489 };
1490 
1491 /// Make a default value. VtValue uses this to create values to be returned
1492 /// from failed calls to \a Get. Clients may specialize this for their own
1493 /// types.
1494 template <class T>
1495 struct Vt_DefaultValueFactory {
1496  static Vt_DefaultValueHolder Invoke();
1497 };
1498 
1499 template <class T>
1500 inline Vt_DefaultValueHolder
1502  return Vt_DefaultValueHolder::Create<T>();
1503 }
1504 
1505 // For performance reasons, the default constructors for vectors,
1506 // matrices, and quaternions do *not* initialize the data of the
1507 // object. This greatly improves the performance of creating large
1508 // arrays of objects. However, for consistency and to avoid
1509 // errors complaining about uninitialized values, we use VtZero
1510 // to construct zeroed out vectors, matrices, and quaternions by
1511 // explicitly instantiating the factory for these types.
1512 //
1513 #define _VT_DECLARE_ZERO_VALUE_FACTORY(r, unused, elem) \
1514 template <> \
1515 VT_API Vt_DefaultValueHolder Vt_DefaultValueFactory<VT_TYPE(elem)>::Invoke();
1516 
1518  unused,
1523 
1524 #undef _VT_DECLARE_ZERO_VALUE_FACTORY
1525 
1526 //
1527 // The Get()/IsHolding routines needs to be special-cased to handle getting a
1528 // VtValue *as* a VtValue.
1529 //
1530 
1531 template <>
1532 inline const VtValue&
1533 VtValue::Get<VtValue>() const & {
1534  return *this;
1535 }
1536 
1537 template <>
1538 inline VtValue
1539 VtValue::Get<VtValue>() && {
1540  return std::move(*this);
1541 }
1542 
1543 template <>
1544 inline const VtValue&
1545 VtValue::UncheckedGet<VtValue>() const & {
1546  return *this;
1547 }
1548 
1549 template <>
1550 inline VtValue
1551 VtValue::UncheckedGet<VtValue>() && {
1552  return std::move(*this);
1553 }
1554 
1555 template <>
1556 inline bool
1557 VtValue::IsHolding<VtValue>() const {
1558  return true;
1559 }
1560 
1561 // Specialize VtValue::IsHolding<void>() to always return false.
1562 template <>
1563 inline bool
1564 VtValue::IsHolding<void>() const {
1565  return false;
1566 }
1567 
1568 
1569 
1570 #endif // !doxygen
1571 
1573 
1574 #endif // PXR_BASE_VT_VALUE_H
#define ARCH_LIKELY(x)
Definition: hints.h:46
GLenum query
Definition: glad.h:2772
~VtValue()
Destructor.
Definition: value.h:913
bool CanCast() const
Definition: value.h:1253
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:1218
static Vt_DefaultValueHolder Create(T const &val)
Definition: value.h:83
T const & UncheckedGet() const &
Definition: value.h:1094
STATIC_INLINE size_t Hash(const char *s, size_t len)
Definition: farmhash.h:2038
friend TfPyObjWrapper Vt_GetPythonObjectFromHeldValue(VtValue const &self)
static VtValue Take(T &obj)
Definition: value.h:906
void
Definition: png.h:1083
long size() const
Definition: ImfArray.h:88
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:1631
VtValue & CastToTypeOf(VtValue const &other)
Definition: value.h:1231
static void RegisterCast(VtValue(*castFn)(VtValue const &))
Register a cast from VtValue holding From to VtValue holding To.
Definition: value.h:1150
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
GLsizei const GLfloat * value
Definition: glcorearb.h:824
static const Vt_ShapeData * _GetShapeData(const VtValue &value)
Definition: value.h:1482
VtValue & operator=(char const *cstr)
Assigning a char const * gives a VtValue holding a std::string.
Definition: value.h:962
#define ARCH_PRAGMA_POP
Definition: pragmas.h:170
VtValue(T const &obj)
Definition: value.h:882
T Get()&&
Definition: value.h:1126
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:954
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
size_t GetArraySize() const
Definition: value.h:1063
#define VT_API
Definition: api.h:40
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:1001
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:975
T Remove()
Definition: value.h:1033
**But if you need a result
Definition: thread.h:613
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1272
#define VT_DUALQUATERNION_VALUE_TYPES
Definition: types.h:134
friend struct _HoldAside
Definition: value.h:829
VtValue & operator=(char *cstr)
Assigning a char * gives a VtValue holding a std::string.
Definition: value.h:970
T const & VtGetProxiedObject(T const &nonProxy)
Definition: traits.h:120
static size_t _GetNumElements(const VtValue &value)
Definition: value.h:1486
VtValue(VtValue const &other)
Copy construct with other.
Definition: value.h:867
constexpr T * Get() const noexcept
Retrieve the pointer.
bool CanCastToTypeOf(VtValue const &other) const
Definition: value.h:1260
static VT_API VtValue CastToTypeOf(VtValue const &val, VtValue const &other)
T const & Get() const &
Definition: value.h:1110
#define ARCH_UNLIKELY(x)
Definition: hints.h:47
int GetKnownValueTypeIndex() const
Definition: value.h:1082
constexpr uintptr_t GetLiteral() const noexcept
static VT_API VtValue CastToTypeid(VtValue const &val, std::type_info const &type)
void intrusive_ptr_release(T *x)
Definition: refcnt.h:217
VT_API bool IsArrayValued() const
Returns true iff this is holding an array type (see VtIsArray<>).
#define ARCH_PRAGMA_PUSH
Definition: pragmas.h:166
VT_API std::type_info const & GetElementTypeid() const
T UncheckedRemove()
Definition: value.h:1044
std::enable_if_t< _TypeInfoFor< T >::Type::IsLocal &&_TypeInfoFor< T >::Type::HasTrivialCopy, VtValue & > operator=(T obj)
Definition: value.h:936
friend bool operator!=(VtValue const &lhs, T const &rhs)
Tests for inequality.
Definition: value.h:1297
void UncheckedSwap(VtValue &rhs)
Definition: value.h:1027
typename std::decay< decltype(VtGetProxiedObject(std::declval< T >()))>::type type
Definition: traits.h:129
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:1205
friend bool operator==(VtValue const &lhs, T const &rhs)
Tests for equality.
Definition: value.h:1286
#define VT_VEC_VALUE_TYPES
Definition: types.h:91
VT_API std::ostream & VtStreamOut(std::vector< VtValue > const &val, std::ostream &)
#define VT_VALUE_SET_STORED_TYPE(SRC, DST)
Definition: value.h:112
VtValue(VtValue &&other) noexcept
Move construct with other.
Definition: value.h:872
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
#define _VT_DECLARE_ZERO_VALUE_FACTORY(r, unused, elem)
Definition: value.h:1513
void const * GetPointer() const
Definition: value.h:94
VtValue & operator=(VtValue &&other) noexcept
Move assignment from another VtValue.
Definition: value.h:923
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.
Array concept. By default, types are not arrays.
Definition: traits.h:41
T UncheckedGet()&&
Definition: value.h:1099
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:1020
void intrusive_ptr_add_ref(T *x)
Definition: refcnt.h:208
VtValue & operator=(VtValue const &other)
Copy assignment from another VtValue.
Definition: value.h:916
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
friend size_t hash_value(VtValue const &val)
Definition: value.h:1280
#define ARCH_PRAGMA_MAYBE_UNINITIALIZED
Definition: pragmas.h:186
size_t VtHashValue(T const &val)
Definition: hash.h:78
static VtValue Cast(VtValue const &val)
Definition: value.h:1177
bool IsHolding() const
Definition: value.h:1054
std::type_info const & GetType() const
Definition: value.h:88
static Vt_DefaultValueHolder Create()
Definition: value.h:76
auto ptr(T p) -> const void *
Definition: format.h:2448
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:91
friend void swap(VtValue &lhs, VtValue &rhs)
Overloaded swap() for generic code/stl/etc.
Definition: value.h:987
static void RegisterSimpleCast()
Register a simple cast from VtValue holding From to VtValue.
Definition: value.h:1157
Definition: type.h:64
Definition: core.h:1131
static TfAnyUniquePtr New()
Definition: anyUniquePtr.h:47
#define VT_QUATERNION_VALUE_TYPES
Definition: types.h:128
VtValue & CastToTypeid(std::type_info const &type)
Definition: value.h:1242
#define const
Definition: zconf.h:214
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:864
static void RegisterSimpleBidirectionalCast()
Definition: value.h:1164
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:1144
HBOOST_PP_SEQ_FOR_EACH(_VT_DECLARE_ZERO_VALUE_FACTORY, unused, VT_VEC_VALUE_TYPES VT_MATRIX_VALUE_TYPES VT_QUATERNION_VALUE_TYPES VT_DUALQUATERNION_VALUE_TYPES) template<> inline const VtValue &VtValue
Definition: value.h:1517
type
Definition: core.h:1059
static Vt_DefaultValueHolder Invoke()
Definition: value.h:1501
#define VT_MATRIX_VALUE_TYPES
Definition: types.h:107
Definition: value.h:167
bool CanCastToTypeid(std::type_info const &type) const
Definition: value.h:1267
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:86
GLenum src
Definition: glcorearb.h:1793