This document is for a version of USD that is under development. See this page for the current release.
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