7#ifndef PXR_BASE_VT_VALUEREF_H
8#define PXR_BASE_VT_VALUEREF_H
14#include "pxr/base/tf/pyObjWrapper.h"
16#include "pxr/base/tf/pyLock.h"
21#include "pxr/base/tf/anyUniquePtr.h"
22#include "pxr/base/tf/preprocessorUtilsLite.h"
26#include "pxr/base/tf/type.h"
28#include "pxr/base/vt/api.h"
29#include "pxr/base/vt/hash.h"
30#include "pxr/base/vt/streamOut.h"
33#include "pxr/base/vt/valueCommon.h"
39PXR_NAMESPACE_OPEN_SCOPE
47VtStreamOut(std::vector<VtValueRef>
const &val, std::ostream &);
80 struct alignas(8) _TypeInfo {
82 using _CanHashFunc = bool (*)(_RefdObjPtr);
83 using _HashFunc = size_t (*)(_RefdObjPtr);
84 using _EqualFunc = bool (*)(_RefdObjPtr, _RefdObjPtr);
86 using _GetVtValueFunc =
VtValue (*)(_RefdObjPtr);
87 using _StreamOutFunc = std::ostream & (*)(_RefdObjPtr, std::ostream &);
88 using _IsArrayValuedFunc = bool (*)(_RefdObjPtr);
89 using _GetNumElementsFunc = size_t (*)(_RefdObjPtr);
92 constexpr _TypeInfo(
const std::type_info &ti,
93 const std::type_info &elementTi,
100 _CanHashFunc canHash,
103 _GetPyObjFunc getPyObj,
104 _GetVtValueFunc getVtValue,
105 _StreamOutFunc streamOut,
106 _IsArrayValuedFunc isArrayValued,
107 _GetNumElementsFunc getNumElements)
109 , elementTypeInfo(elementTi)
110 , knownTypeIndex(knownTypeIndex)
112 , isHashable(isHashable)
113 , canComposeOver(canComposeOver)
114 , canTransform(canTransform)
115 , isMutable(isMutable)
120 , _getPyObj(getPyObj)
121 , _getVtValue(getVtValue)
122 , _streamOut(streamOut)
123 , _isArrayValued(isArrayValued)
124 , _getNumElements(getNumElements)
128 bool CanHash(_RefdObjPtr storage)
const {
129 return _canHash(storage);
131 size_t Hash(_RefdObjPtr storage)
const {
132 return _hash(storage);
134 bool Equal(_RefdObjPtr lhs, _RefdObjPtr rhs)
const {
135 return _equal(lhs, rhs);
138 return _getPyObj(storage);
141 inline VtValue GetVtValue(_RefdObjPtr storage)
const;
142 std::ostream &StreamOut(_RefdObjPtr storage,
143 std::ostream &out)
const {
144 return _streamOut(storage, out);
147 return _isArrayValued(storage);
149 size_t GetNumElements(_RefdObjPtr storage)
const {
150 return _getNumElements(storage);
153 const std::type_info &typeInfo;
154 const std::type_info &elementTypeInfo;
155 const int knownTypeIndex;
157 const bool isHashable;
158 const bool canComposeOver;
159 const bool canTransform;
160 const bool isMutable;
163 _CanHashFunc _canHash;
166 _GetPyObjFunc _getPyObj;
167 _GetVtValueFunc _getVtValue;
168 _StreamOutFunc _streamOut;
169 _IsArrayValuedFunc _isArrayValued;
170 _GetNumElementsFunc _getNumElements;
178 struct _NonArrayHelper
181 static size_t GetNumElements(U &&) {
return 0; }
182 constexpr static std::type_info
const &GetElementTypeid() {
187 template <
class Array>
188 struct _IsArrayHelper
190 static size_t GetNumElements(Array
const &obj) {
193 constexpr static std::type_info
const &GetElementTypeid() {
194 return typeid(
typename Array::ElementType);
199 template <
class ArrayEdit>
200 struct _IsArrayEditHelper : _NonArrayHelper<ArrayEdit>
202 constexpr static std::type_info
const &GetElementTypeid() {
203 return typeid(
typename ArrayEdit::ElementType);
211 using _ArrayHelper = TfConditionalType<
213 TfConditionalType<VtIsArrayEdit<T>::value,
214 _IsArrayEditHelper<T>, _NonArrayHelper<T>>
218 template <
class T,
bool IsMutable>
219 struct _TypeInfoImpl :
public _TypeInfo
222 using This = _TypeInfoImpl;
224 static constexpr bool IsPointer = std::is_pointer_v<Type>;
225 static constexpr bool IsFunctionPointer =
226 IsPointer && std::is_function_v<std::remove_pointer_t<Type>>;
228 using ConstType = std::conditional_t<
230 const std::remove_pointer_t<Type> *,
233 using GetObjResultType = std::conditional_t<
234 IsPointer, ConstType, ConstType &>;
236 using GetMutableObjResultType = std::conditional_t<
237 IsPointer, Type, Type &>;
244 constexpr _TypeInfoImpl()
245 : _TypeInfo(
typeid(T),
246 _ArrayHelper<T>::GetElementTypeid(),
247 Vt_KnownValueTypeDetail::GetIndex<T>(),
261 &This::_IsArrayValued,
262 &This::_GetNumElements)
268 static GetObjResultType
269 GetObj(_RefdObjPtr
const &storage) {
270 if constexpr (IsFunctionPointer) {
271 return reinterpret_cast<GetObjResultType
>(storage.fnPtr);
273 else if constexpr (IsPointer) {
274 return reinterpret_cast<GetObjResultType
>(storage.objPtr);
277 return *
static_cast<ConstType *
>(storage.objPtr);
281 static GetMutableObjResultType
282 GetMutableObj(_RefdObjPtr &storage) {
285 if constexpr (IsFunctionPointer) {
286 return reinterpret_cast<GetMutableObjResultType
>(storage.fnPtr);
288 else if constexpr (IsPointer) {
289 return reinterpret_cast<
290 GetMutableObjResultType
>(storage.objPtr);
293 return *
static_cast<Type *
>(
const_cast<void *
>(storage.objPtr));
297 static void SetObj(T
const &obj, _RefdObjPtr &storage) {
298 if constexpr (IsFunctionPointer) {
299 storage.fnPtr =
reinterpret_cast<void (*)()
>(obj);
301 else if constexpr (IsPointer) {
302 storage.objPtr =
static_cast<void const *
>(obj);
305 storage.objPtr =
static_cast<void const *
>(std::addressof(obj));
310 static bool _CanHash(_RefdObjPtr) {
311 return VtIsHashable<T>();
314 static size_t _Hash(_RefdObjPtr ptr) {
315 return VtHashValue(GetObj(ptr));
318 static bool _Equal(_RefdObjPtr lhs, _RefdObjPtr rhs) {
319 return GetObj(lhs) == GetObj(rhs);
323#ifdef PXR_PYTHON_SUPPORT_ENABLED
325 return pxr_boost::python::api::object(GetObj(storage));
332 static VtValue _GetVtValue(_RefdObjPtr storage);
334 static std::ostream &_StreamOut(
335 _RefdObjPtr storage, std::ostream &out) {
336 return VtStreamOut(GetObj(storage), out);
339 static bool _IsArrayValued(_RefdObjPtr storage) {
343 static std::type_info
const &
344 _GetElementTypeid(_RefdObjPtr ptr) {
345 return _ArrayHelper<T>::GetElementTypeid();
348 static size_t _GetNumElements(_RefdObjPtr ptr) {
349 return _ArrayHelper<T>::GetNumElements(GetObj(ptr));
359 using _TypeInfoFor = _TypeInfoImpl<
361 std::is_reference_v<T> && std::is_const_v<T>>;
375 !std::is_same_v<std::decay_t<T>,
VtValueRef> &&
376 !std::is_same_v<std::decay_t<T>,
VtValue>> * = 0) {
377 using TypeInfo = _TypeInfoFor<T>;
378 using TypeInfoType =
typename TypeInfo::Type;
379 static_assert(!VtIsValueProxy<TypeInfoType>::value,
380 "VtValueRef does not support proxies");
381 static const TypeInfo ti;
382 ti.SetObj(obj, _ptr);
383 _info = std::addressof(ti);
396 std::swap(lhs._ptr, rhs._ptr);
397 std::swap(lhs._info, rhs._info);
404 return _info && _TypeIs<T>();
410 return _info && _info->isMutable;
425 return _info ? _info->typeInfo :
typeid(void);
432 return _info ? _info->elementTypeInfo :
typeid(void);
444 return _info ? _info->knownTypeIndex : -1;
451 typename _TypeInfoFor<T>::GetObjResultType
463 typename _TypeInfoFor<T>::GetObjResultType
465 using Factory = Vt_DefaultValueFactory<T>;
469 if (ARCH_UNLIKELY(!IsHolding<T>())) {
470 return *(
static_cast<T
const *
>(
471 _FailGet(Factory::Invoke,
typeid(T))));
483 return IsHolding<T>() ? UncheckedGet<T>() : def;
493 if (IsHolding<T>()) {
494 return UncheckedRemove<T>();
497 _FailRemove(
typeid(T));
509 return std::move(_GetMutable<T>());
526 friend inline size_t hash_value(
VtValueRef const &val) {
536 return !_info || _info->canComposeOver;
545 return _info && _info->canTransform;
551 if (empty || rhsEmpty) {
553 return empty == rhsEmpty;
555 if (_info == rhs._info) {
557 return _info->Equal(_ptr, rhs._ptr);
561 bool operator != (
const VtValueRef &rhs)
const {
return !(*
this == rhs); }
564 VT_API
friend std::ostream &
568 VT_API
size_t _GetNumElements()
const;
573 if constexpr (VtIsKnownValueType_Workaround<T>::value) {
574 return _info->knownTypeIndex == VtGetKnownValueTypeIndex<T>();
577 std::type_info
const &t =
typeid(T);
583 typename _TypeInfoFor<T>::GetMutableObjResultType
585 using TypeInfo = _TypeInfoFor<T>;
586 return TypeInfo::GetMutableObj(_ptr);
590 typename _TypeInfoFor<T>::GetObjResultType
592 using TypeInfo = _TypeInfoFor<T>;
593 return TypeInfo::GetObj(_ptr);
599 _FailGet(Vt_DefaultValueHolder (*factory)(),
600 std::type_info
const &queryType)
const;
602 VT_API
void _FailRemove(std::type_info
const &);
609 Vt_GetPythonObjectFromHeldValue(
VtValueRef const &self);
614 _TypeInfo
const *_info;
626VtValueRef::Get<VtValueRef>()
const {
632VtValueRef::UncheckedGet<VtValueRef>()
const {
638VtValueRef::IsHolding<VtValueRef>()
const {
645VtValueRef::IsHolding<void>()
const {
673 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
674 "Can only assign to VtMutableValueRef with a type T "
676 if (IsHolding<T>()) {
677 _GetMutable<T>() = std::forward<T>(obj);
680 _FailAssign(
typeid(T));
687 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
688 "Can only assign to VtMutableValueRef with a type T "
690 _GetMutable<T>() = std::forward<T>(obj);
701 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
702 "Can only VtValueRef::Swap with a type T "
704 if (IsHolding<T>()) {
708 _FailSwap(
typeid(T));
719 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
720 "Can only VtValueRef::Swap with a type T "
723 swap(_GetMutable<T>(), rhs);
729 template <
class T,
class Fn>
732 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
733 "Can only VtValueRef::Mutate a type T that stores as T");
734 if (!IsHolding<T>()) {
737 UncheckedMutate<T>(std::forward<Fn>(mutateFn));
744 template <
class T,
class Fn>
747 static_assert(std::is_same_v<T, typename Vt_ValueGetStored<T>::Type>,
748 "Can only VtValueRef::Mutate a type T that stores as T");
752 T &stored = _GetMutable<T>();
753 T tmp = std::move(stored);
754 std::forward<Fn>(mutateFn)(tmp);
755 stored = std::move(tmp);
759 VT_API
void _FailAssign(std::type_info
const &);
760 VT_API
void _FailSwap(std::type_info
const &);
764PXR_NAMESPACE_CLOSE_SCOPE
774#include "pxr/base/vt/value.h"
776PXR_NAMESPACE_OPEN_SCOPE
780VtValueRef::_TypeInfo::GetVtValue(_RefdObjPtr storage)
const {
781 return _getVtValue(storage);
784template <
class T,
bool B>
786VtValueRef::_TypeInfoImpl<T, B>::_GetVtValue(_RefdObjPtr storage) {
787 return VtValue { GetObj(storage) };
790PXR_NAMESPACE_CLOSE_SCOPE
792#ifdef PXR_PYTHON_SUPPORT_ENABLED
794#include "pxr/external/boost/python/converter/arg_from_python.hpp"
797namespace PXR_BOOST_NAMESPACE::python::converter {
807struct arg_rvalue_from_python<PXR_NS::
VtValueRef>
808 :
public arg_rvalue_from_python<PXR_NS::VtValue>
810 using base_type = arg_rvalue_from_python<PXR_NS::VtValue>;
811 using base_type::convertible;
812 using result_type = PXR_NS::VtValueRef &;
814 VT_API arg_rvalue_from_python(PyObject* obj);
816 VT_API result_type operator()();
818 std::optional<PXR_NS::VtValueRef> optValueRef;
Defines all the types "TYPED" for which Vt creates a VtTYPEDArray typedef.
Convenience class for accessing the Python Global Interpreter Lock.
Boost Python object wrapper.
TfType represents a dynamic runtime type.
A non-owning type-erased view of a mutable lvalue, interoperating with VtValue.
void UncheckedMutate(Fn &&mutateFn)
Invoke mutateFn, passing it a non-const reference to the viewed object which must be of type T.
VtMutableValueRef()=default
Default ctor gives empty VtMutableValueRef.
bool Mutate(Fn &&mutateFn)
If this value holds an object of type T, invoke mutateFn, passing it a non-const reference to the vie...
VtMutableValueRef & operator=(T &&obj)
Assign to the viewed value.
void UncheckedSwap(T &rhs)
Swap the viewed value with rhs.
void Swap(T &rhs)
Swap the viewed value with rhs.
Provides a container which may hold any type, and provides introspection and iteration over array typ...
A non-owning type-erased view of a value, interoperating with VtValue.
VT_API std::string GetTypeName() const
Return the type name of the viewed typeid.
T UncheckedRemove()
Return a move-constructed (if the viewed object is an rvalue) or copy-constructed T instance from the...
std::type_info const & GetElementTypeid() const
If this value views a VtArray or VtArrayEdit instance, return the typeid of its element type.
bool operator==(const VtValueRef &rhs) const
Test two values for equality.
int GetKnownValueTypeIndex() const
Return VtKnownValueTypeIndex<T> for the viewed type T.
bool IsRValue() const
Return true if this refers to an rvalue, and thus can be Remove()d by a move construction operation i...
VtValueRef(T &&obj, std::enable_if_t< !std::is_same_v< std::decay_t< T >, VtValueRef > &&!std::is_same_v< std::decay_t< T >, VtValue > > *=0)
Implicitly convert or construct a VtValueRef referring to obj.
T Remove()
Return a move-constructed (if the viewed object is an rvalue) or copy-constructed T instance from the...
VtValueRef()
Default ctor gives empty VtValueRef.
size_t GetArraySize() const
Return the number of elements in the viewed value if IsArrayValued(), return 0 otherwise.
VtValueRef & operator=(VtValueRef const &ref)=default
Rebind to view the same object as another VtValueRef.
T GetWithDefault(T const &def=T()) const
Return a copy of the viewed object if the viewed object is of type T.
friend void swap(VtValueRef &lhs, VtValueRef &rhs)
Overloaded swap() for generic code/stl/etc. Swaps the viewed objects.
VT_API bool IsArrayValued() const
Return true if this views a VtArray instance, false otherwise.
bool IsEmpty() const
Returns true iff this value is empty.
VT_API TfType GetType() const
Returns the TfType of the type viewed by this value.
bool CanComposeOver() const
Return true if this value holds a type that has been declared at compile time to support composing ov...
VT_API size_t GetHash() const
Return a hash code for the viewed object by calling VtHashValue() on it.
std::type_info const & GetTypeid() const
Return the typeid of the type viewed by this value.
bool CanTransform() const
Return true if this value holds a type that has been declared to support value transforms at compile ...
_TypeInfoFor< T >::GetObjResultType UncheckedGet() const
Return a const reference to the viewed object if the viewed object is of type T.
VT_API bool IsArrayEditValued() const
Return true if this views a VtArrayEdit instance, false otherwise.
bool IsHolding() const
Return true if this value is viewing an object of type T, false otherwise.
VT_API bool CanHash() const
Return true if the viewed object provides a hash implementation.
VT_API friend std::ostream & operator<<(std::ostream &out, const VtValueRef &self)
Calls through to operator << on the viewed object.
_TypeInfoFor< T >::GetObjResultType Get() const
Return a const reference to the viewed object if the viewed object is of type T.
Demangle C++ typenames generated by the typeid() facility.
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.
A trait to detect instantiations of VtArray, specialized in array.h.
A trait indicating whether VtValue compose-over functionality can be registered for a type.
A file containing basic constants and definitions.