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
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 intrusive_ptr_add_ref(_Counted const *d) {
183 d->_refCount.fetch_add(1, std::memory_order_relaxed);
184 }
185 friend inline void intrusive_ptr_release(_Counted const *d) {
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 // intrusive_ptr to an object holder: _Counted<T>.
767 template <class T>
768 struct _RemoteTypeInfo : _TypeInfoImpl<
769 T, // type
770 boost::intrusive_ptr<_Counted<T> >, // container
771 _RemoteTypeInfo<T> // CRTP
772 >
773 {
774 constexpr _RemoteTypeInfo()
775 : _TypeInfoImpl<
776 T, boost::intrusive_ptr<_Counted<T>>, _RemoteTypeInfo<T>>()
777 {}
778
779 typedef boost::intrusive_ptr<_Counted<T> > Ptr;
780 // Get returns object stored in the pointed-to _Counted<T>.
781 static T &_GetMutableObj(Ptr &ptr) {
782 if (!ptr->IsUnique())
783 ptr.reset(new _Counted<T>(ptr->Get()));
784 return ptr->GetMutable();
785 }
786 static T const &_GetObj(Ptr const &ptr) { return ptr->Get(); }
787 // PlaceCopy() allocates a new _Counted<T> with a copy of the object.
788 static void _PlaceCopy(Ptr *dst, T const &src) {
789 new (dst) Ptr(new _Counted<T>(src));
790 }
791 };
792
793 // Metafunction that returns the specific _TypeInfo subclass for T.
794 template <class T>
795 struct _TypeInfoFor {
796 // return _UsesLocalStore(T) ? _LocalTypeInfo<T> : _RemoteTypeInfo<T>;
797 typedef std::conditional_t<_UsesLocalStore<T>::value,
798 _LocalTypeInfo<T>,
799 _RemoteTypeInfo<T>> Type;
800 };
801
802 // Make sure char[N] is treated as a string.
803 template <size_t N>
804 struct _TypeInfoFor<char[N]> : _TypeInfoFor<std::string> {};
805
806 // Runtime function to return a _TypeInfo base pointer to a specific
807 // _TypeInfo subclass for type T.
808 template <class T>
809 static TfPointerAndBits<const _TypeInfo> GetTypeInfo() {
810 typedef typename _TypeInfoFor<T>::Type TI;
811 static const TI ti;
812 static constexpr unsigned int flags =
813 (TI::IsLocal ? _LocalFlag : 0) |
814 (TI::HasTrivialCopy ? _TrivialCopyFlag : 0) |
815 (TI::IsProxy ? _ProxyFlag : 0);
816 return TfPointerAndBits<const _TypeInfo>(&ti, flags);
817 }
818
819 // A helper that moves a held value to temporary storage, but keeps it alive
820 // until the _HoldAside object is destroyed. This is used when assigning
821 // over a VtValue that might own the object being assigned. For instance,
822 // if I have a VtValue holding a map<string, VtValue>, and I reassign this
823 // VtValue with one of the elements from the map, we must ensure that the
824 // map isn't destroyed until after the assignment has taken place.
825 friend struct _HoldAside;
826 struct _HoldAside {
827 explicit _HoldAside(VtValue *val)
828 : info((val->IsEmpty() || val->_IsLocalAndTriviallyCopyable())
829 ? static_cast<_TypeInfo const *>(NULL) : val->_info.Get()) {
830 if (info)
831 info->Move(val->_storage, storage);
832 }
833 ~_HoldAside() {
834 if (info)
835 info->Destroy(storage);
836 }
837 _Storage storage;
838 _TypeInfo const *info;
839 };
840
841 template <class T>
842 std::enable_if_t<
843 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
844 _Init(T const &obj) {
845 _info = GetTypeInfo<T>();
846 typedef typename _TypeInfoFor<T>::Type TypeInfo;
847 TypeInfo::CopyInitObj(obj, _storage);
848 }
849
850 template <class T>
851 std::enable_if_t<
852 !std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
853 _Init(T const &obj) {
854 _Init(typename Vt_ValueGetStored<T>::Type(obj));
855 }
856
857public:
858
861
863 VtValue(VtValue const &other) {
864 _Copy(other, *this);
865 }
866
868 VtValue(VtValue &&other) noexcept {
869 _Move(other, *this);
870 }
871
877 template <class T>
878 explicit VtValue(T const &obj) {
879 _Init(obj);
880 }
881
901 template <class T>
902 static VtValue Take(T &obj) {
903 VtValue ret;
904 ret.Swap(obj);
905 return ret;
906 }
907
909 ~VtValue() { _Clear(); }
910
912 VtValue &operator=(VtValue const &other) {
913 if (ARCH_LIKELY(this != &other))
914 _Copy(other, *this);
915 return *this;
916 }
917
919 VtValue &operator=(VtValue &&other) noexcept {
920 if (ARCH_LIKELY(this != &other))
921 _Move(other, *this);
922 return *this;
923 }
924
925#ifndef doxygen
926 template <class T>
927 inline
928 std::enable_if_t<
929 _TypeInfoFor<T>::Type::IsLocal &&
930 _TypeInfoFor<T>::Type::HasTrivialCopy,
931 VtValue &>
932 operator=(T obj) {
933 _Clear();
934 _Init(obj);
935 return *this;
936 }
937#endif
938
940#ifdef doxygen
941 template <class T>
942 VtValue&
943 operator=(T const &obj);
944#else
945 template <class T>
946 std::enable_if_t<
947 !_TypeInfoFor<T>::Type::IsLocal ||
948 !_TypeInfoFor<T>::Type::HasTrivialCopy,
949 VtValue &>
950 operator=(T const &obj) {
951 _HoldAside tmp(this);
952 _Init(obj);
953 return *this;
954 }
955#endif
956
958 VtValue &operator=(char const *cstr) {
959 std::string tmp(cstr);
960 _Clear();
961 _Init(tmp);
962 return *this;
963 }
964
966 VtValue &operator=(char *cstr) {
967 return *this = const_cast<char const *>(cstr);
968 }
969
971 VtValue &Swap(VtValue &rhs) noexcept {
972 // Do nothing if both empty. Otherwise general swap.
973 if (!IsEmpty() || !rhs.IsEmpty()) {
974 VtValue tmp;
975 _Move(*this, tmp);
976 _Move(rhs, *this);
977 _Move(tmp, rhs);
978 }
979 return *this;
980 }
981
983 friend void swap(VtValue &lhs, VtValue &rhs) { lhs.Swap(rhs); }
984
986 // make an unqualified call to swap(<held-value>, rhs). If this value is
987 // not holding a T, replace the held value with a value-initialized T
988 // instance first, then swap.
989#ifdef doxygen
990 template <class T>
991 void
992 Swap(T &rhs);
993#else
994 template <class T>
995 std::enable_if_t<
996 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
997 Swap(T &rhs) {
998 if (!IsHolding<T>())
999 *this = T();
1000 UncheckedSwap(rhs);
1001 }
1002#endif
1003
1008#ifdef doxygen
1009 template <class T>
1010 void
1012#else
1013 template <class T>
1014 std::enable_if_t<
1015 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
1016 UncheckedSwap(T &rhs) {
1017 using std::swap;
1018 swap(_GetMutable<T>(), rhs);
1019 }
1020#endif
1021
1023 void UncheckedSwap(VtValue &rhs) { Swap(rhs); }
1024
1028 template <class T>
1030 T result;
1031 Swap(result);
1032 _Clear();
1033 return result;
1034 }
1035
1039 template <class T>
1041 T result;
1042 UncheckedSwap(result);
1043 _Clear();
1044 return result;
1045 }
1046
1050 template <class T, class Fn>
1051 std::enable_if_t<
1052 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value, bool>
1053 Mutate(Fn &&mutateFn) {
1054 if (!IsHolding<T>()) {
1055 return false;
1056 }
1057 UncheckedMutate<T>(std::forward<Fn>(mutateFn));
1058 return true;
1059 }
1060
1064 template <class T, class Fn>
1065 std::enable_if_t<
1066 std::is_same<T, typename Vt_ValueGetStored<T>::Type>::value>
1067 UncheckedMutate(Fn &&mutateFn) {
1068 // We move to a temporary, mutate the temporary, then move back. This
1069 // prevents callers from escaping a mutable reference to the held object
1070 // via a side-effect of mutateFn.
1071 T &stored =_GetMutable<T>();
1072 T tmp = std::move(stored);
1073 std::forward<Fn>(mutateFn)(tmp);
1074 stored = std::move(tmp);
1075 }
1076
1079 template <class T>
1080 bool IsHolding() const {
1081 return _info.GetLiteral() && _TypeIs<T>();
1082 }
1083
1085 VT_API bool IsArrayValued() const;
1086
1089 size_t GetArraySize() const { return _GetNumElements(); }
1090
1092 VT_API std::type_info const &GetTypeid() const;
1093
1096 VT_API std::type_info const &GetElementTypeid() const;
1097
1099 VT_API TfType GetType() const;
1100
1102 VT_API std::string GetTypeName() const;
1103
1109 if (ARCH_UNLIKELY(_IsProxy())) {
1110 return _info->GetProxiedAsVtValue(
1111 _storage).GetKnownValueTypeIndex();
1112 }
1113 return _info.GetLiteral() ? _info->knownTypeIndex : -1;
1114 }
1115
1119 template <class T>
1120 T const &UncheckedGet() const & { return _Get<T>(); }
1121
1124 template <class T>
1125 T UncheckedGet() && { return UncheckedRemove<T>(); }
1126
1135 template <class T>
1136 T const &Get() const & {
1137 typedef Vt_DefaultValueFactory<T> Factory;
1138
1139 // In the unlikely case that the types don't match, we obtain a default
1140 // value to return and issue an error via _FailGet.
1141 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1142 return *(static_cast<T const *>(
1143 _FailGet(Factory::Invoke, typeid(T))));
1144 }
1145
1146 return _Get<T>();
1147 }
1148
1151 template <class T>
1152 T Get() && {
1153 typedef Vt_DefaultValueFactory<T> Factory;
1154
1155 // In the unlikely case that the types don't match, we obtain a default
1156 // value to return and issue an error via _FailGet.
1157 if (ARCH_UNLIKELY(!IsHolding<T>())) {
1158 return *(static_cast<T const *>(
1159 _FailGet(Factory::Invoke, typeid(T))));
1160 }
1161
1162 return UncheckedRemove<T>();
1163 }
1164
1169 template <class T>
1170 T GetWithDefault(T const &def = T()) const {
1171 return IsHolding<T>() ? UncheckedGet<T>() : def;
1172 }
1173
1175 template <typename From, typename To>
1176 static void RegisterCast(VtValue (*castFn)(VtValue const &)) {
1177 _RegisterCast(typeid(From), typeid(To), castFn);
1178 }
1179
1181 // holding To.
1182 template <typename From, typename To>
1183 static void RegisterSimpleCast() {
1184 _RegisterCast(typeid(From), typeid(To), _SimpleCast<From, To>);
1185 }
1186
1189 template <typename From, typename To>
1191 RegisterSimpleCast<From, To>();
1192 RegisterSimpleCast<To, From>();
1193 }
1194
1202 template <typename T>
1203 static VtValue Cast(VtValue const &val) {
1204 VtValue ret = val;
1205 return ret.Cast<T>();
1206 }
1207
1215 VT_API static VtValue
1216 CastToTypeOf(VtValue const &val, VtValue const &other);
1217
1225 VT_API static VtValue
1226 CastToTypeid(VtValue const &val, std::type_info const &type);
1227
1231 static bool CanCastFromTypeidToTypeid(std::type_info const &from,
1232 std::type_info const &to) {
1233 return _CanCast(from, to);
1234 }
1235
1243 template <typename T>
1245 if (IsHolding<T>())
1246 return *this;
1247 return *this = _PerformCast(typeid(T), *this);
1248 }
1249
1258 return CastToTypeid(other.GetTypeid());
1259 }
1260
1268 VtValue &CastToTypeid(std::type_info const &type) {
1269 if (!TfSafeTypeCompare(GetTypeid(), type)) {
1270 *this = _PerformCast(type, *this);
1271 }
1272 return *this;
1273 }
1274
1278 template <typename T>
1279 bool CanCast() const {
1280 return _CanCast(GetTypeid(), typeid(T));
1281 }
1282
1286 bool CanCastToTypeOf(VtValue const &other) const {
1287 return _CanCast(GetTypeid(), other.GetTypeid());
1288 }
1289
1293 bool CanCastToTypeid(std::type_info const &type) const {
1294 return _CanCast(GetTypeid(), type);
1295 }
1296
1298 bool IsEmpty() const { return _info.GetLiteral() == 0; }
1299
1301 VT_API bool CanHash() const;
1302
1304 VT_API size_t GetHash() const;
1305
1306 friend inline size_t hash_value(VtValue const &val) {
1307 return val.GetHash();
1308 }
1309
1311 template <typename T>
1312 friend bool operator == (VtValue const &lhs, T const &rhs) {
1313 typedef typename Vt_ValueGetStored<T>::Type Stored;
1314 return lhs.IsHolding<Stored>() && lhs.UncheckedGet<Stored>() == rhs;
1315 }
1316 template <typename T>
1317 friend bool operator == (T const &lhs, VtValue const &rhs) {
1318 return rhs == lhs;
1319 }
1320
1322 template <typename T>
1323 friend bool operator != (VtValue const &lhs, T const &rhs) {
1324 return !(lhs == rhs);
1325 }
1326 template <typename T>
1327 friend bool operator != (T const &lhs, VtValue const &rhs) {
1328 return !(lhs == rhs);
1329 }
1330
1332 bool operator == (const VtValue &rhs) const {
1333 bool empty = IsEmpty(), rhsEmpty = rhs.IsEmpty();
1334 if (empty || rhsEmpty) {
1335 // Either one or both empty -- only equal if both empty.
1336 return empty == rhsEmpty;
1337 }
1338 if (_info.GetLiteral() == rhs._info.GetLiteral()) {
1339 // Holding identical types -- compare directly.
1340 return _info.Get()->Equal(_storage, rhs._storage);
1341 }
1342 return _EqualityImpl(rhs);
1343 }
1344 bool operator != (const VtValue &rhs) const { return !(*this == rhs); }
1345
1347 VT_API friend std::ostream &
1348 operator << (std::ostream &out, const VtValue &self);
1349
1350private:
1351 VT_API const Vt_ShapeData* _GetShapeData() const;
1352 VT_API size_t _GetNumElements() const;
1353 friend struct Vt_ValueShapeDataAccess;
1354
1355 static inline void _Copy(VtValue const &src, VtValue &dst) {
1356 if (src.IsEmpty()) {
1357 dst._Clear();
1358 return;
1359 }
1360
1361 _HoldAside tmp(&dst);
1362 dst._info = src._info;
1363 if (src._IsLocalAndTriviallyCopyable()) {
1364 dst._storage = src._storage;
1365 } else {
1366 dst._info->CopyInit(src._storage, dst._storage);
1367 }
1368 }
1369
1370 static inline void _Move(VtValue &src, VtValue &dst) noexcept {
1371 if (src.IsEmpty()) {
1372 dst._Clear();
1373 return;
1374 }
1375
1376 _HoldAside tmp(&dst);
1377 dst._info = src._info;
1378 if (src._IsLocalAndTriviallyCopyable()) {
1379 dst._storage = src._storage;
1380 } else {
1381 dst._info->Move(src._storage, dst._storage);
1382 }
1383
1384 src._info.Set(nullptr, 0);
1385 }
1386
1387 template <class T>
1388 inline std::enable_if_t<VtIsKnownValueType_Workaround<T>::value, bool>
1389 _TypeIs() const {
1390 return _info->knownTypeIndex == VtGetKnownValueTypeIndex<T>() ||
1391 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(typeid(T)));
1392 }
1393
1394 template <class T>
1395 inline std::enable_if_t<!VtIsKnownValueType_Workaround<T>::value, bool>
1396 _TypeIs() const {
1397 std::type_info const &t = typeid(T);
1398 return TfSafeTypeCompare(_info->typeInfo, t) ||
1399 ARCH_UNLIKELY(_IsProxy() && _TypeIsImpl(t));
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(r, unused, elem) \
1540template <> \
1541VT_API Vt_DefaultValueHolder Vt_DefaultValueFactory<VT_TYPE(elem)>::Invoke();
1542
1543BOOST_PP_SEQ_FOR_EACH(_VT_DECLARE_ZERO_VALUE_FACTORY,
1544 unused,
1545 VT_VEC_VALUE_TYPES
1546 VT_MATRIX_VALUE_TYPES
1547 VT_QUATERNION_VALUE_TYPES
1548 VT_DUALQUATERNION_VALUE_TYPES)
1549
1550#undef _VT_DECLARE_ZERO_VALUE_FACTORY
1551
1552//
1553// The Get()/IsHolding routines needs to be special-cased to handle getting a
1554// VtValue *as* a VtValue.
1555//
1556
1557template <>
1558inline const VtValue&
1559VtValue::Get<VtValue>() const & {
1560 return *this;
1561}
1562
1563template <>
1564inline VtValue
1565VtValue::Get<VtValue>() && {
1566 return std::move(*this);
1567}
1568
1569template <>
1570inline const VtValue&
1571VtValue::UncheckedGet<VtValue>() const & {
1572 return *this;
1573}
1574
1575template <>
1576inline VtValue
1577VtValue::UncheckedGet<VtValue>() && {
1578 return std::move(*this);
1579}
1580
1581template <>
1582inline bool
1583VtValue::IsHolding<VtValue>() const {
1584 return true;
1585}
1586
1587// Specialize VtValue::IsHolding<void>() to always return false.
1588template <>
1589inline bool
1590VtValue::IsHolding<void>() const {
1591 return false;
1592}
1593
1594
1595
1596#endif // !doxygen
1597
1598PXR_NAMESPACE_CLOSE_SCOPE
1599
1600#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: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:1293
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition: value.h:1040
friend bool operator==(VtValue const &lhs, T const &rhs)
Tests for equality.
Definition: value.h:1312
int GetKnownValueTypeIndex() const
Return VtKnownValueTypeIndex<T> for the held type T.
Definition: value.h:1108
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:1029
static VtValue Take(T &obj)
Create a new VtValue, taking its contents from obj.
Definition: value.h:902
static void RegisterSimpleCast()
Register a simple cast from VtValue holding From to VtValue.
Definition: value.h:1183
VtValue & Cast()
Return this holding value type cast to T.
Definition: value.h:1244
VtValue & CastToTypeOf(VtValue const &other)
Return this holding value type cast to same type that other is holding.
Definition: value.h:1257
static void RegisterSimpleBidirectionalCast()
Register a two-way cast from VtValue holding From to VtValue holding To.
Definition: value.h:1190
VtValue(VtValue const &other)
Copy construct with other.
Definition: value.h:863
static void RegisterCast(VtValue(*castFn)(VtValue const &))
Register a cast from VtValue holding From to VtValue holding To.
Definition: value.h:1176
size_t GetArraySize() const
Return the number of elements in the held value if IsArrayValued(), return 0 otherwise.
Definition: value.h:1089
VtValue & operator=(char *cstr)
Assigning a char * gives a VtValue holding a std::string.
Definition: value.h:966
bool CanCastToTypeOf(VtValue const &other) const
Return if this can be cast to type.
Definition: value.h:1286
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:1067
VtValue & operator=(char const *cstr)
Assigning a char const * gives a VtValue holding a std::string.
Definition: value.h:958
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:1170
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:1023
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:1053
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:1298
VtValue & operator=(VtValue &&other) noexcept
Move assignment from another VtValue.
Definition: value.h:919
VtValue & CastToTypeid(std::type_info const &type)
Return this holding value type cast to type.
Definition: value.h:1268
VT_API TfType GetType() const
Returns the TfType of the type held by this value.
~VtValue()
Destructor.
Definition: value.h:909
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:878
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:971
friend void swap(VtValue &lhs, VtValue &rhs)
Overloaded swap() for generic code/stl/etc.
Definition: value.h:983
static VtValue Cast(VtValue const &val)
Return a VtValue holding val cast to hold T.
Definition: value.h:1203
bool CanCast() const
Return if this can be cast to T.
Definition: value.h:1279
T const & Get() const &
Returns a const reference to the held object if the held object is of type T.
Definition: value.h:1136
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:860
friend bool operator!=(VtValue const &lhs, T const &rhs)
Tests for inequality.
Definition: value.h:1323
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:1231
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
Definition: value.h:1080
VtValue(VtValue &&other) noexcept
Move construct with other.
Definition: value.h:868
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:1120
VtValue & operator=(VtValue const &other)
Copy assignment from another VtValue.
Definition: value.h:912
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.