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