Loading...
Searching...
No Matches
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
37PXR_NAMESPACE_OPEN_SCOPE
38
40template <typename T>
41struct 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.
49template <class T>
50struct 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.
108struct VtTypedValueProxyBase {};
109template <class T>
110struct 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).
116template <class T,
117 typename std::enable_if<
118 !VtIsTypedValueProxy<T>::value, int>::type = 0>
119T const &
120VtGetProxiedObject(T const &nonProxy) {
121 return nonProxy;
122}
123
124// Metafunction to determine the proxied type for a typed proxy.
125template <class T>
126struct 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.
135struct VtErasedValueProxyBase {};
136template <class T>
137struct 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).
144template <class T>
145struct VtIsValueProxy :
146 std::integral_constant<
147 bool, VtIsTypedValueProxy<T>::value || VtIsErasedValueProxy<T>::value> {};
148
149PXR_NAMESPACE_CLOSE_SCOPE
150
151#endif // PXR_BASE_VT_TRAITS_H
Array concept. By default, types are not arrays.
Definition: traits.h:41