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