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