7#ifndef PXR_BASE_VT_VISIT_VALUE_H
8#define PXR_BASE_VT_VISIT_VALUE_H
12#include "pxr/base/tf/meta.h"
13#include "pxr/base/tf/pxrTslRobinMap/robin_map.h"
15#include "pxr/base/vt/value.h"
20#ifndef VT_VISIT_VALUE_EXT_TYPES
21# define VT_VISIT_VALUE_EXT_TYPES PXR_NS_GLOBAL::TfMetaList<>
24PXR_NAMESPACE_OPEN_SCOPE
26namespace Vt_ValueVisitDetail {
32template <
class T,
class Visitor,
class ...Args>
34Visit(
VtValue const &val, Visitor &&visitor,
int, Args &&...args) ->
35 decltype(std::forward<Visitor>(visitor)(
36 val.UncheckedGet<T>(), std::forward<Args>(args)...))
38 return std::forward<Visitor>(visitor)(
39 val.UncheckedGet<T>(), std::forward<Args>(args)...);
42template <
class T,
class Visitor,
class ...Args>
44Visit(
VtValue const &val, Visitor &&visitor,
long, Args &&...args) {
45 return std::forward<Visitor>(visitor)(val, std::forward<Args>(args)...);
53struct Vt_ExtTypeIndexTable {
54 static int Lookup(std::type_info
const &ti) {
55 static const Vt_ExtTypeIndexTable instance;
56 auto it = instance._map.find(&ti);
57 return (it != instance._map.end()) ? it->second : -1;
61 size_t operator()(std::type_info
const *ti)
const {
62 return ti->hash_code();
66 bool operator()(std::type_info
const *a,
67 std::type_info
const *b)
const {
71 Vt_ExtTypeIndexTable() {
73 ((_map.emplace(&
typeid(Ts), idx++)), ...);
80template <
class T,
class Ret,
class Visitor,
class ...Args>
82Vt_VisitValueExtDispatchOne(
83 VtValue const &val, Visitor &&visitor, Args &&...args)
85 return Vt_ValueVisitDetail::Visit<T>(
86 val, std::forward<Visitor>(visitor), 0,
87 std::forward<Args>(args)...);
90constexpr size_t Vt_VisitValueHashThreshold = 8;
96template <
class ...Ts,
class Visitor,
class ...Args>
98Vt_VisitValueExtDispatch(
100 VtValue const &val, Visitor &&visitor, Args &&...args)
102 using Ret =
decltype(
103 Vt_ValueVisitDetail::Visit<VtValue>(
104 val, std::forward<Visitor>(visitor), 0,
105 std::forward<Args>(args)...));
107 if constexpr (
sizeof...(Ts) == 0) {
108 return Vt_ValueVisitDetail::Visit<VtValue>(
109 val, std::forward<Visitor>(visitor), 0,
110 std::forward<Args>(args)...);
112 else if constexpr (
sizeof...(Ts) <= Vt_VisitValueHashThreshold) {
113 std::optional<Ret> result;
115 (result.emplace(Vt_ValueVisitDetail::Visit<Ts>(
116 val, std::forward<Visitor>(visitor), 0,
117 std::forward<Args>(args)...)),
true)) || ...);
119 return Vt_ValueVisitDetail::Visit<VtValue>(
120 val, std::forward<Visitor>(visitor), 0,
121 std::forward<Args>(args)...);
123 return std::move(*result);
126 int idx = Vt_ExtTypeIndexTable<Ts...>::Lookup(val.
GetTypeid());
128 using FnPtr = Ret (*)(
VtValue const &, Visitor &&, Args &&...);
129 static constexpr FnPtr table[] = {
130 &Vt_VisitValueExtDispatchOne<Ts, Ret, Visitor, Args...>...
133 val, std::forward<Visitor>(visitor),
134 std::forward<Args>(args)...);
136 return Vt_ValueVisitDetail::Visit<VtValue>(
137 val, std::forward<Visitor>(visitor), 0,
138 std::forward<Args>(args)...);
143template <
class T,
class Ret,
144 template <
class,
class...>
class Visitor,
class ...TypeArgs,
147Vt_VisitValueTypeExtDispatchOne(FnArgs &&...args)
149 return Visitor<T, TypeArgs...>::Visit(std::forward<FnArgs>(args)...);
153template <
template <
class T,
class ...>
class Visitor,
typename ...TypeArgs,
154 class ...Ts,
typename ...FnArgs>
156Vt_VisitValueTypeExtDispatch(
158 VtValue const &val, FnArgs &&...args)
160 using Ret =
decltype(
161 Visitor<VtValue, TypeArgs...>::Visit(std::forward<FnArgs>(args)...));
163 if constexpr (
sizeof...(Ts) == 0) {
164 return Visitor<VtValue, TypeArgs...>::Visit(
165 std::forward<FnArgs>(args)...);
167 else if constexpr (
sizeof...(Ts) <= Vt_VisitValueHashThreshold) {
168 std::optional<Ret> result;
170 (result.emplace(Visitor<Ts, TypeArgs...>::Visit(
171 std::forward<FnArgs>(args)...)),
true)) || ...);
173 return Visitor<VtValue, TypeArgs...>::Visit(
174 std::forward<FnArgs>(args)...);
176 return std::move(*result);
179 int idx = Vt_ExtTypeIndexTable<Ts...>::Lookup(val.
GetTypeid());
181 using FnPtr = Ret (*)(FnArgs &&...);
182 static constexpr FnPtr table[] = {
183 &Vt_VisitValueTypeExtDispatchOne<
184 Ts, Ret, Visitor, TypeArgs...>...
186 return table[idx](std::forward<FnArgs>(args)...);
188 return Visitor<VtValue, TypeArgs...>::Visit(
189 std::forward<FnArgs>(args)...);
194template <
class T,
class Ret,
195 template <
class,
template <
class...>
class,
class...>
class Visitor,
196 template <
class...>
class Tmpl,
class ...TypeArgs,
199Vt_VisitValueTypeTmplExtDispatchOne(FnArgs &&...args)
201 return Visitor<T, Tmpl, TypeArgs...>::Visit(std::forward<FnArgs>(args)...);
205template <
template <
class T,
template <
class...>
class,
class ...>
class Visitor,
206 template <
class...>
class Tmpl,
typename ...TypeArgs,
207 class ...Ts,
typename ...FnArgs>
209Vt_VisitValueTypeTmplExtDispatch(
211 VtValue const &val, FnArgs &&...args)
213 using Ret =
decltype(
214 Visitor<VtValue, Tmpl, TypeArgs...>::Visit(
215 std::forward<FnArgs>(args)...));
217 if constexpr (
sizeof...(Ts) == 0) {
218 return Visitor<VtValue, Tmpl, TypeArgs...>::Visit(
219 std::forward<FnArgs>(args)...);
221 else if constexpr (
sizeof...(Ts) <= Vt_VisitValueHashThreshold) {
222 std::optional<Ret> result;
224 (result.emplace(Visitor<Ts, Tmpl, TypeArgs...>::Visit(
225 std::forward<FnArgs>(args)...)),
true)) || ...);
227 return Visitor<VtValue, Tmpl, TypeArgs...>::Visit(
228 std::forward<FnArgs>(args)...);
230 return std::move(*result);
233 int idx = Vt_ExtTypeIndexTable<Ts...>::Lookup(val.
GetTypeid());
235 using FnPtr = Ret (*)(FnArgs &&...);
236 static constexpr FnPtr table[] = {
237 &Vt_VisitValueTypeTmplExtDispatchOne<
238 Ts, Ret, Visitor, Tmpl, TypeArgs...>...
240 return table[idx](std::forward<FnArgs>(args)...);
242 return Visitor<VtValue, Tmpl, TypeArgs...>::Visit(
243 std::forward<FnArgs>(args)...);
259template <
class ExtTypes>
266 template <
class Visitor,
class ...Args>
268 VtValue const &value, Visitor &&visitor, Args&&...args)
270 switch (value.GetKnownValueTypeIndex()) {
271#define VT_CASE_FOR_TYPE_INDEX(unused, elem) \
272 case VtGetKnownValueTypeIndex<VT_TYPE(elem)>(): \
273 return Vt_ValueVisitDetail::Visit<VT_TYPE(elem)>( \
274 value, std::forward<Visitor>(visitor), 0, \
275 std::forward<Args>(args)...); \
277VT_FOR_EACH_VALUE_TYPE(VT_CASE_FOR_TYPE_INDEX)
278#undef VT_CASE_FOR_TYPE_INDEX
280 return Vt_VisitValueExtDispatch(
282 value, std::forward<Visitor>(visitor),
283 std::forward<Args>(args)...);
291 template <
class T,
class ...>
class Visitor,
292 typename ...TypeArgs,
297 switch (value.GetKnownValueTypeIndex()) {
298#define VT_CASE_FOR_TYPE_INDEX(unused, elem) \
299 case VtGetKnownValueTypeIndex<VT_TYPE(elem)>(): \
300 return Visitor<VT_TYPE(elem), TypeArgs...>::Visit( \
301 std::forward<FnArgs>(args)...); \
303VT_FOR_EACH_VALUE_TYPE(VT_CASE_FOR_TYPE_INDEX)
304#undef VT_CASE_FOR_TYPE_INDEX
306 return Vt_VisitValueTypeExtDispatch<Visitor, TypeArgs...>(
307 ExtTypes{}, value, std::forward<FnArgs>(args)...);
314 template <
class T,
template <
class...>
class,
class ...>
class Visitor,
315 template <
class...>
class Tmpl,
316 typename ...TypeArgs,
321 switch (value.GetKnownValueTypeIndex()) {
322#define VT_CASE_FOR_TYPE_INDEX(unused, elem) \
323 case VtGetKnownValueTypeIndex<VT_TYPE(elem)>(): \
324 return Visitor<VT_TYPE(elem), Tmpl, TypeArgs...>::Visit( \
325 std::forward<FnArgs>(args)...); \
327VT_FOR_EACH_VALUE_TYPE(VT_CASE_FOR_TYPE_INDEX)
328#undef VT_CASE_FOR_TYPE_INDEX
330 return Vt_VisitValueTypeTmplExtDispatch<Visitor, Tmpl, TypeArgs...>(
331 ExtTypes{}, value, std::forward<FnArgs>(args)...);
336PXR_NAMESPACE_CLOSE_SCOPE
439template <
class Visitor,
class ...Args>
440auto VtVisitValue(
VtValue const &value, Visitor &&visitor, Args &&...args);
506 template <
class T,
class ...>
class Visitor,
507 typename ...TypeArgs,
510auto VtVisitValueType(
VtValue const &value, FnArgs &&...args);
541 template <
class T,
template <
class...>
class,
class ...>
class Visitor,
542 template <
class...>
class Tmpl,
543 typename ...TypeArgs,
546auto VtVisitValueType(
VtValue const &value, FnArgs &&...args);
550#define VtVisitValue \
551 VtVisitValueWithExtTypes<VT_VISIT_VALUE_EXT_TYPES>::VisitValue
553#define VtVisitValueType \
554 VtVisitValueWithExtTypes<VT_VISIT_VALUE_EXT_TYPES>::VisitType
Provides a container which may hold any type, and provides introspection and iteration over array typ...
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
VT_API std::type_info const & GetTypeid() const
Return the typeid of the type held by this value.
Implementation of a hash map using open-addressing and the robin hood hashing algorithm with backward...
Safely compare C++ RTTI type structures.
bool TfSafeTypeCompare(const std::type_info &t1, const std::type_info &t2)
Safely compare std::type_info structures.
Provides VtVisitValue() and VtVisitValueType() dispatch, parameterized on a compile-time list of exte...
static auto VisitType(VtValue const &value, FnArgs &&...args)
Invoke Visitor<T, TypeArgs...>::Visit(args...) where T is the held type.
static auto VisitValue(VtValue const &value, Visitor &&visitor, Args &&...args)
Invoke visitor with value's held object if value holds a known or extended type.
static auto VisitType(VtValue const &value, FnArgs &&...args)
This is an overloaded member function, provided for convenience. It differs from the above function o...