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/pointerAndBits.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 <boost/intrusive_ptr.hpp>
52#include <boost/type_traits/has_trivial_assign.hpp>
53#include <boost/type_traits/has_trivial_constructor.hpp>
54#include <boost/type_traits/has_trivial_copy.hpp>
55#include <boost/type_traits/has_trivial_destructor.hpp>
56
57#include <iosfwd>
58#include <typeinfo>
59#include <type_traits>
60
61PXR_NAMESPACE_OPEN_SCOPE
62
66template <class T>
67struct Vt_DefaultValueFactory;
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.
71struct Vt_DefaultValueHolder
72{
73 // Creates a value-initialized object and stores the type_info for the
74 // static type.
75 template <typename T>
76 static Vt_DefaultValueHolder Create() {
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
98private:
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
106class VtValue;
107
108// Overload VtStreamOut for vector<VtValue>. Produces output like [value1,
109// value2, ... valueN].
110VT_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
115template <class T> struct Vt_ValueStoredType { typedef T Type; };
116VT_VALUE_SET_STORED_TYPE(char const *, std::string);
117VT_VALUE_SET_STORED_TYPE(char *, std::string);
118
119#ifdef PXR_PYTHON_SUPPORT_ENABLED
120VT_VALUE_SET_STORED_TYPE(boost::python::object, TfPyObjWrapper);
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.
126template <class T>
127struct Vt_ValueGetStored
128 : Vt_ValueStoredType<std::decay_t<T>> {};
129
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,
206 boost::has_trivial_constructor<T>::value &&
207 boost::has_trivial_copy<T>::value &&
208 boost::has_trivial_assign<T>::value &&
209 boost::has_trivial_destructor<T>::value>;
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)) &&
216 VtValueTypeHasCheapCopy<T>::value &&
217 std::is_nothrow_move_constructible<T>::value &&
218 std::is_nothrow_move_assignable<T>::value>;
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 boost::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 boost::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
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
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
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
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
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 boost::intrusive_ptr<_Counted<T> >, // container
775 _RemoteTypeInfo<T> // CRTP
776 >
777 {
778 constexpr _RemoteTypeInfo()
779 : _TypeInfoImpl<
780 T, boost::intrusive_ptr<_Counted<T>>, _RemoteTypeInfo<T>>()
781 {}
782
783 typedef boost::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>;
801 typedef std::conditional_t<_UsesLocalStore<T>::value,
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);
820 return TfPointerAndBits<const _TypeInfo>(&ti, flags);
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>
846 std::enable_if_t<
847 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
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>
855 std::enable_if_t<
856 !std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
857 _Init(T const &obj) {
858 _Init(typename Vt_ValueGetStored<T>::Type(obj));
859 }
860
861public:
862
865
867 VtValue(VtValue const &other) {
868 _Copy(other, *this);
869 }
870
872 VtValue(VtValue &&other) noexcept {
873 _Move(other, *this);
874 }
875
881 template <class T>
882 explicit VtValue(T const &obj) {
883 _Init(obj);
884 }
885
905 template <class T>
906 static VtValue Take(T &obj) {
907 VtValue ret;
908 ret.Swap(obj);
909 return ret;
910 }
911
913 ~VtValue() { _Clear(); }
914
916 VtValue &operator=(VtValue const &other) {
917 if (ARCH_LIKELY(this != &other))
918 _Copy(other, *this);
919 return *this;
920 }
921
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
932 std::enable_if_t<
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
944#ifdef doxygen
945 template <class T>
946 VtValue&
947 operator=(T const &obj);
948#else
949 template <class T>
950 std::enable_if_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
962 VtValue &operator=(char const *cstr) {
963 std::string tmp(cstr);
964 _Clear();
965 _Init(tmp);
966 return *this;
967 }
968
970 VtValue &operator=(char *cstr) {
971 return *this = const_cast<char const *>(cstr);
972 }
973
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
987 friend void swap(VtValue &lhs, VtValue &rhs) { lhs.Swap(rhs); }
988
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>
999 std::enable_if_t<
1000 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
1001 Swap(T &rhs) {
1002 if (!IsHolding<T>())
1003 *this = T();
1004 UncheckedSwap(rhs);
1005 }
1006#endif
1007
1012#ifdef doxygen
1013 template <class T>
1014 void
1016#else
1017 template <class T>
1018 std::enable_if_t<
1019 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
1020 UncheckedSwap(T &rhs) {
1021 using std::swap;
1022 swap(_GetMutable<T>(), rhs);
1023 }
1024#endif
1025
1027 void UncheckedSwap(VtValue &rhs) { Swap(rhs); }
1028
1032 template <class T>
1034 T result;
1035 Swap(result);
1036 _Clear();
1037 return result;
1038 }
1039
1043 template <class T>
1045 T result;
1046 UncheckedSwap(result);
1047 _Clear();
1048 return result;
1049 }
1050
1053 template <class T>
1054 bool IsHolding() const {
1055 return _info.GetLiteral() && _TypeIs<T>();
1056 }
1057
1059 VT_API bool IsArrayValued() const;
1060
1063 size_t GetArraySize() const { return _GetNumElements(); }
1064
1066 VT_API std::type_info const &GetTypeid() const;
1067
1070 VT_API std::type_info const &GetElementTypeid() const;
1071
1073 VT_API TfType GetType() const;
1074
1076 VT_API std::string GetTypeName() const;
1077
1083 if (ARCH_UNLIKELY(_IsProxy())) {
1084 return _info->GetProxiedAsVtValue(
1085 _storage).GetKnownValueTypeIndex();
1086 }
1087 return _info.GetLiteral() ? _info->knownTypeIndex : -1;
1088 }
1089
1093 template <class T>
1094 T const &UncheckedGet() const & { return _Get<T>(); }
1095
1098 template <class T>
1099 T UncheckedGet() && { return UncheckedRemove<T>(); }
1100
1109 template <class T>
1110 T const &Get() const & {
1111 typedef Vt_DefaultValueFactory<T> Factory;
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
1125 template <class T>
1126 T Get() && {
1127 typedef Vt_DefaultValueFactory<T> Factory;
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
1143 template <class T>
1144 T GetWithDefault(T const &def = T()) const {
1145 return IsHolding<T>() ? UncheckedGet<T>() : def;
1146 }
1147
1149 template <typename From, typename To>
1150 static void RegisterCast(VtValue (*castFn)(VtValue const &)) {
1151 _RegisterCast(typeid(From), typeid(To), castFn);
1152 }
1153
1155 // holding To.
1156 template <typename From, typename To>
1157 static void RegisterSimpleCast() {
1158 _RegisterCast(typeid(From), typeid(To), _SimpleCast<From, To>);
1159 }
1160
1163 template <typename From, typename To>
1165 RegisterSimpleCast<From, To>();
1166 RegisterSimpleCast<To, From>();
1167 }
1168
1176 template <typename T>
1177 static VtValue Cast(VtValue const &val) {
1178 VtValue ret = val;
1179 return ret.Cast<T>();
1180 }
1181
1189 VT_API static VtValue
1190 CastToTypeOf(VtValue const &val, VtValue const &other);
1191
1199 VT_API static VtValue
1200 CastToTypeid(VtValue const &val, std::type_info const &type);
1201
1205 static bool CanCastFromTypeidToTypeid(std::type_info const &from,
1206 std::type_info const &to) {
1207 return _CanCast(from, to);
1208 }
1209
1217 template <typename T>
1219 if (IsHolding<T>())
1220 return *this;
1221 return *this = _PerformCast(typeid(T), *this);
1222 }
1223
1232 return CastToTypeid(other.GetTypeid());
1233 }
1234
1242 VtValue &CastToTypeid(std::type_info const &type) {
1243 if (!TfSafeTypeCompare(GetTypeid(), type)) {
1244 *this = _PerformCast(type, *this);
1245 }
1246 return *this;
1247 }
1248
1252 template <typename T>
1253 bool CanCast() const {
1254 return _CanCast(GetTypeid(), typeid(T));
1255 }
1256
1260 bool CanCastToTypeOf(VtValue const &other) const {
1261 return _CanCast(GetTypeid(), other.GetTypeid());
1262 }
1263
1267 bool CanCastToTypeid(std::type_info const &type) const {
1268 return _CanCast(GetTypeid(), type);
1269 }
1270
1272 bool IsEmpty() const { return _info.GetLiteral() == 0; }
1273
1275 VT_API bool CanHash() const;
1276
1278 VT_API size_t GetHash() const;
1279
1280 friend inline size_t hash_value(VtValue const &val) {
1281 return val.GetHash();
1282 }
1283
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
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
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
1321 VT_API friend std::ostream &
1322 operator << (std::ostream &out, const VtValue &self);
1323
1324private:
1325 VT_API const Vt_ShapeData* _GetShapeData() const;
1326 VT_API size_t _GetNumElements() const;
1327 friend struct Vt_ValueShapeDataAccess;
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>
1362 inline std::enable_if_t<VtIsKnownValueType_Workaround<T>::value, bool>
1363 _TypeIs() const {
1364 return _info->knownTypeIndex == VtGetKnownValueTypeIndex<T>() ||
1365 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(typeid(T)));
1366 }
1367
1368 template <class T>
1369 inline std::enable_if_t<!VtIsKnownValueType_Workaround<T>::value, bool>
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>
1381 std::enable_if_t<VtIsValueProxy<Proxy>::value, Proxy &>
1382 _GetMutable() {
1383 typedef typename _TypeInfoFor<Proxy>::Type TypeInfo;
1384 return TypeInfo::GetMutableObj(_storage);
1385 }
1386
1387 template <class T>
1388 std::enable_if_t<!VtIsValueProxy<T>::value, 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>
1399 std::enable_if_t<VtIsValueProxy<Proxy>::value, Proxy const &>
1400 _Get() const {
1401 typedef typename _TypeInfoFor<Proxy>::Type TypeInfo;
1402 return TypeInfo::GetObj(_storage);
1403 }
1404
1405 template <class T>
1406 std::enable_if_t<!VtIsValueProxy<T>::value, T const &>
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.
1427ARCH_PRAGMA_PUSH
1428// XXX: http://bug/DEV-16695
1429ARCH_PRAGMA_MAYBE_UNINITIALIZED
1430 if (_info.GetLiteral() && !_IsLocalAndTriviallyCopyable())
1431 _info.Get()->Destroy(_storage);
1432ARCH_PRAGMA_POP
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 // boost::python wrapped object corresponding to the held type. This
1469 // facility is necessary to get the python API we want.
1470 friend TfPyObjWrapper
1471 Vt_GetPythonObjectFromHeldValue(VtValue const &self);
1472
1473 VT_API TfPyObjWrapper _GetPythonObject() const;
1474
1475 _Storage _storage;
1477};
1478
1479#ifndef doxygen
1480
1481struct Vt_ValueShapeDataAccess {
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
1494template <class T>
1495struct Vt_DefaultValueFactory {
1496 static Vt_DefaultValueHolder Invoke();
1497};
1498
1499template <class T>
1500inline Vt_DefaultValueHolder
1501Vt_DefaultValueFactory<T>::Invoke() {
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) \
1514template <> \
1515VT_API Vt_DefaultValueHolder Vt_DefaultValueFactory<VT_TYPE(elem)>::Invoke();
1516
1517BOOST_PP_SEQ_FOR_EACH(_VT_DECLARE_ZERO_VALUE_FACTORY,
1518 unused,
1519 VT_VEC_VALUE_TYPES
1520 VT_MATRIX_VALUE_TYPES
1521 VT_QUATERNION_VALUE_TYPES
1522 VT_DUALQUATERNION_VALUE_TYPES)
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
1531template <>
1532inline const VtValue&
1533VtValue::Get<VtValue>() const & {
1534 return *this;
1535}
1536
1537template <>
1538inline VtValue
1539VtValue::Get<VtValue>() && {
1540 return std::move(*this);
1541}
1542
1543template <>
1544inline const VtValue&
1545VtValue::UncheckedGet<VtValue>() const & {
1546 return *this;
1547}
1548
1549template <>
1550inline VtValue
1551VtValue::UncheckedGet<VtValue>() && {
1552 return std::move(*this);
1553}
1554
1555template <>
1556inline bool
1557VtValue::IsHolding<VtValue>() const {
1558 return true;
1559}
1560
1561// Specialize VtValue::IsHolding<void>() to always return false.
1562template <>
1563inline bool
1564VtValue::IsHolding<void>() const {
1565 return false;
1566}
1567
1568
1569
1570#endif // !doxygen
1571
1572PXR_NAMESPACE_CLOSE_SCOPE
1573
1574#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
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:168
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:1267
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition: value.h:1044
friend bool operator==(VtValue const &lhs, T const &rhs)
Tests for equality.
Definition: value.h:1286
int GetKnownValueTypeIndex() const
Return VtKnownValueTypeIndex<T> for the held type T.
Definition: value.h:1082
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:1033
static VtValue Take(T &obj)
Create a new VtValue, taking its contents from obj.
Definition: value.h:906
static void RegisterSimpleCast()
Register a simple cast from VtValue holding From to VtValue.
Definition: value.h:1157
VtValue & Cast()
Return this holding value type cast to T.
Definition: value.h:1218
VtValue & CastToTypeOf(VtValue const &other)
Return this holding value type cast to same type that other is holding.
Definition: value.h:1231
static void RegisterSimpleBidirectionalCast()
Register a two-way cast from VtValue holding From to VtValue holding To.
Definition: value.h:1164
VtValue(VtValue const &other)
Copy construct with other.
Definition: value.h:867
static void RegisterCast(VtValue(*castFn)(VtValue const &))
Register a cast from VtValue holding From to VtValue holding To.
Definition: value.h:1150
size_t GetArraySize() const
Return the number of elements in the held value if IsArrayValued(), return 0 otherwise.
Definition: value.h:1063
VtValue & operator=(char *cstr)
Assigning a char * gives a VtValue holding a std::string.
Definition: value.h:970
bool CanCastToTypeOf(VtValue const &other) const
Return if this can be cast to type.
Definition: value.h:1260
VtValue & operator=(char const *cstr)
Assigning a char const * gives a VtValue holding a std::string.
Definition: value.h:962
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:1144
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:1027
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:1272
VtValue & operator=(VtValue &&other) noexcept
Move assignment from another VtValue.
Definition: value.h:923
VtValue & CastToTypeid(std::type_info const &type)
Return this holding value type cast to type.
Definition: value.h:1242
VT_API TfType GetType() const
Returns the TfType of the type held by this value.
~VtValue()
Destructor.
Definition: value.h:913
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:882
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:975
friend void swap(VtValue &lhs, VtValue &rhs)
Overloaded swap() for generic code/stl/etc.
Definition: value.h:987
static VtValue Cast(VtValue const &val)
Return a VtValue holding val cast to hold T.
Definition: value.h:1177
bool CanCast() const
Return if this can be cast to T.
Definition: value.h:1253
T const & Get() const &
Returns a const reference to the held object if the held object is of type T.
Definition: value.h:1110
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:864
friend bool operator!=(VtValue const &lhs, T const &rhs)
Tests for inequality.
Definition: value.h:1297
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:1205
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
Definition: value.h:1054
VtValue(VtValue &&other) noexcept
Move construct with other.
Definition: value.h:872
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:1094
VtValue & operator=(VtValue const &other)
Copy assignment from another VtValue.
Definition: value.h:916
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:41
A file containing basic constants and definitions.