diff --git a/pxr/base/vt/testenv/testVtCpp.cpp b/pxr/base/vt/testenv/testVtCpp.cpp index d4fce98f6d..47d008b4f4 100644 --- a/pxr/base/vt/testenv/testVtCpp.cpp +++ b/pxr/base/vt/testenv/testVtCpp.cpp @@ -1766,6 +1766,46 @@ testVisitValue() } +template +static void +AssertIsHoldingKnownType(const VtValue &val) +{ + switch (val.GetKnownValueTypeIndex()) { + case VtGetKnownValueTypeIndex(): + break; + default: + TF_FATAL_ERROR("Expected %s (index=%d); got index %d", + ArchGetDemangled().c_str(), + VtGetKnownValueTypeIndex(), + val.GetKnownValueTypeIndex()); + } +} + +struct TypeNotKnownToVt {}; + +static void +testKnownValueTypeIndex() +{ + VtValue iv(123); + VtValue dv(1.23); + VtValue fv(2.34f); + VtValue hv(GfHalf(3.45)); + VtValue sv(std::string("hello")); + VtValue av(VtArray(123)); + + AssertIsHoldingKnownType(iv); + AssertIsHoldingKnownType(dv); + AssertIsHoldingKnownType(fv); + AssertIsHoldingKnownType(hv); + AssertIsHoldingKnownType(sv); + AssertIsHoldingKnownType>(av); + + TF_AXIOM(VtIsKnownValueType()); + TF_AXIOM(VtIsKnownValueType>()); + TF_AXIOM(!VtIsKnownValueType()); + TF_AXIOM(!VtIsKnownValueType()); +} + int main(int argc, char *argv[]) { testArray(); @@ -1784,6 +1824,7 @@ int main(int argc, char *argv[]) testCombinedVtValueProxies(); testVisitValue(); + testKnownValueTypeIndex(); printf("Test SUCCEEDED\n"); diff --git a/pxr/base/vt/types.h b/pxr/base/vt/types.h index a5a9923b06..9df7ecd0f4 100644 --- a/pxr/base/vt/types.h +++ b/pxr/base/vt/types.h @@ -190,32 +190,64 @@ VT_ARRAY_VALUE_TYPES VT_SCALAR_CLASS_VALUE_TYPES VT_NONARRAY_VALUE_TYPES #define VT_VALUE_TYPES \ VT_BUILTIN_VALUE_TYPES VT_CLASS_VALUE_TYPES -// Provide compile-time value type indexes for types that are "known" to Vt -- -// specifically, those types that appear in VT_VALUE_TYPES. Note that VtArray -// and VtValue can work with other types that are not these "known" types. +namespace Vt_KnownValueTypeDetail +{ + +// Implement compile-time value type indexes. // // Base case -- unknown types get index -1. template constexpr int -VtGetKnownValueTypeIndex() { +GetIndex() { return -1; } // Set indexes for known types. #define VT_SET_VALUE_TYPE_INDEX(r, unused, i, elem) \ template <> constexpr int \ - VtGetKnownValueTypeIndex< VT_TYPE(elem) >() { \ + GetIndex< VT_TYPE(elem) >() { \ return i; \ } BOOST_PP_SEQ_FOR_EACH_I(VT_SET_VALUE_TYPE_INDEX, ~, VT_VALUE_TYPES) #undef VT_SET_VALUE_TYPE_INDEX +} // Vt_KnownValueTypeDetail + // Total number of 'known' value types. constexpr int VtGetNumKnownValueTypes() { return BOOST_PP_SEQ_SIZE(VT_VALUE_TYPES); } +/// Provide compile-time value type indexes for types that are "known" to Vt -- +/// specifically, those types that appear in VT_VALUE_TYPES. Note that VtArray +/// and VtValue can work with other types that are not these "known" types. +/// +/// VtGetKnownValueTypeIndex can only be used with known types. Querying a +/// type that is not known to Vt results in a compilation error. The set of +/// known types and their indexes are not guaranteed to be stable across +/// releases of the library. +/// +/// Most clients should prefer VtVisitValue over direct use of the type index +/// as VtVisitValue provides convenient and efficient access to the held +/// value. +template +constexpr int +VtGetKnownValueTypeIndex() +{ + constexpr int index = Vt_KnownValueTypeDetail::GetIndex(); + static_assert(index != -1, "T is not one of the known VT_VALUE_TYPES."); + return index; +} + +/// Returns true if `T` is a type that appears in VT_VALUE_TYPES. +template +constexpr bool +VtIsKnownValueType() +{ + return Vt_KnownValueTypeDetail::GetIndex() != -1; +} + // None of the VT_VALUE_TYPES are value proxies. We want to specialize these // templates here, since otherwise the VtIsTypedValueProxy will require a // complete type to check if it derives VtTypedValueProxyBase. diff --git a/pxr/base/vt/value.h b/pxr/base/vt/value.h index 7e3529b8ed..1584a93fe3 100644 --- a/pxr/base/vt/value.h +++ b/pxr/base/vt/value.h @@ -584,7 +584,7 @@ class VtValue constexpr _TypeInfoImpl() : _TypeInfo(typeid(T), _ArrayHelper::GetElementTypeid(), - VtGetKnownValueTypeIndex(), + Vt_KnownValueTypeDetail::GetIndex(), VtIsArray::value, VtIsHashable(), IsProxy,