Loading...
Searching...
No Matches
traits.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_VT_TRAITS_H
8#define PXR_BASE_VT_TRAITS_H
9
11
12#include "pxr/pxr.h"
13#include "pxr/base/vt/api.h"
14#include "pxr/base/tf/preprocessorUtilsLite.h"
15
16#include <type_traits>
17
18PXR_NAMESPACE_OPEN_SCOPE
19
21template <typename T>
22struct VtIsArray : public std::false_type {};
23
25template <typename T>
26struct VtIsArrayEdit : public std::false_type {};
27
28// We attempt to use local storage if a given type will fit and if it has a
29// cheap copy operation. By default we only treat types with trivial
30// assignments as "cheap to copy". Typically types that would fit in local
31// space but do not have a trivial assignment are not cheap to copy. E.g. std::
32// containers. Clients can specialize this template for their own types that
33// aren't trivially assignable but are cheap to copy to enable local storage.
34template <class T>
35struct VtValueTypeHasCheapCopy : std::is_trivially_copy_assignable<T> {};
36
37#define VT_TYPE_IS_CHEAP_TO_COPY(T) \
38 template <> struct VtValueTypeHasCheapCopy<TF_PP_EAT_PARENS(T)> \
39 : std::true_type {}
40
41// VtValue supports two kinds of "value proxy":
42//
43// 1. Typed proxies, where given a proxy type P, we can determine the underlying
44// proxied type at compile-time.
45//
46// 2. Erased proxies, where we cannot know the underlying proxied type at
47// compile-time.
48//
49// Typed proxies are mostly useful from a performance standpoint, where you can
50// produce a VtValue that holds an object that is not stored in its own storage
51// area. That is, you can make a VtValue that points at an object you own
52// rather than copying/swapping/moving it to the VtValue.
53//
54// To implement a Typed proxy, either have it derive VtTypedValueProxyBase or
55// specialize the VtIsTypedValueProxy class template (possibly by way of the
56// VT_TYPE_IS_TYPED_VALUE_PROXY macro). Then provide an implementation of
57// VtGetProxiedObject that accepts `TypedProxy const &` and returns a const
58// lvalue reference to the underlying proxied type. That reference must be
59// valid so long as the YourProxyType argument reference is valid. Like:
60//
61// ProxiedType const &VtGetProxiedObject(TypedProxy const &);
62//
63// Erased proxies are mostly useful to enable producing VtValues holding
64// "deferred" values; values whose types are not yet loaded in the process. For
65// example, this can be used to produce VtValues holding objects whose types are
66// provided in plugins that are not yet loaded. When a real object instance is
67// required, VtValue will call `VtGetErasedProxiedVtValue(YourErasedProxy const
68// &)` which must return a pointer to a VtValue holding the underlying proxied
69// type. This can be manufactured "on-the-fly" (with affordances for
70// thread-safety).
71//
72// To implement an Erased proxy, either have it derive VtErasedValueProxyBase or
73// specialize the VtIsErasedValueProxy class template (possibly by way of the
74// VT_TYPE_IS_ERASED_VALUE_PROXY macro). Then provide implementations of:
75//
76// bool VtErasedProxyHoldsType(ErasedProxy const &, std::type_info const &);
77// TfType VtGetErasedProxiedTfType(ErasedProxy const &);
78// VtValue const *VtGetErasedProxiedVtValue(ErasedProxy const &);
79//
80// The pointer returned by VtGetErasedProxiedVtValue must be valid as long as
81// the ErasedProxy argument reference is valid.
82//
83// A note on Equality Comparisons. If a proxy type provides equality
84// comparison, then two VtValues that hold the same proxy types will invoke that
85// equality comparison when compared. Otherwise, the underlying proxied objects
86// will be compared. This is beneficial when equality can be checked without
87// having to actually instantiate the proxied object (for proxies that load &
88// construct the proxied object lazily).
89
90// Clients may derive VtTypedValueProxyBase, specialize VtIsTypedValueProxy,
91// or use the VT_TYPE_IS_TYPED_VALUE_PROXY macro to indicate their type is a
92// VtValue proxy type.
93struct VtTypedValueProxyBase {};
94template <class T>
95struct VtIsTypedValueProxy : std::is_base_of<VtTypedValueProxyBase, T> {};
96#define VT_TYPE_IS_TYPED_VALUE_PROXY(T) \
97 template <> struct VtIsTypedValueProxy<TF_PP_EAT_PARENS(T)> \
98 : std::true_type {}
99
100// Base implementation for VtGetProxiedObject (for non-proxy types).
101template <class T,
102 typename std::enable_if<
103 !VtIsTypedValueProxy<T>::value, int>::type = 0>
104T const &
105VtGetProxiedObject(T const &nonProxy) {
106 return nonProxy;
107}
108
109// Metafunction to determine the proxied type for a typed proxy.
110template <class T>
111struct VtGetProxiedType
112{
113 using type = typename std::decay<
114 decltype(VtGetProxiedObject(std::declval<T>()))>::type;
115};
116
117// Clients may derive VtErasedValueProxyBase, specialize VtIsErasedValueProxy,
118// or use the VT_TYPE_IS_ERASED_VALUE_PROXY macro to indicate their type is a
119// VtValue proxy type.
120struct VtErasedValueProxyBase {};
121template <class T>
122struct VtIsErasedValueProxy : std::is_base_of<VtErasedValueProxyBase, T> {};
123#define VT_TYPE_IS_ERASED_VALUE_PROXY(T) \
124 template <> struct VtIsErasedValueProxy<TF_PP_EAT_PARENS(T)> \
125 : std::true_type {}
126
127// Metafunction to determine whether or not a given type T is a value proxy
128// (either typed or type-erased).
129template <class T>
130struct VtIsValueProxy :
131 std::integral_constant<
132 bool, VtIsTypedValueProxy<T>::value || VtIsErasedValueProxy<T>::value> {};
133
134PXR_NAMESPACE_CLOSE_SCOPE
135
136#endif // PXR_BASE_VT_TRAITS_H
A trait to detect instantiations of VtArrayEdit, specialized in arrayEdit.h.
Definition: traits.h:26
A trait to detect instantiations of VtArray, specialized in array.h.
Definition: traits.h:22