diff --git a/tree/ntuple/v7/inc/ROOT/RField.hxx b/tree/ntuple/v7/inc/ROOT/RField.hxx index 22e8b3e09df69..ad5e2e243bafa 100644 --- a/tree/ntuple/v7/inc/ROOT/RField.hxx +++ b/tree/ntuple/v7/inc/ROOT/RField.hxx @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -291,7 +292,7 @@ public: template class RField final : public RClassField { public: - static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); } + static std::string TypeName() { return ROOT::Internal::GetRenormalizedDemangledTypeName(typeid(T)); } RField(std::string_view name) : RClassField(name, TypeName()) { static_assert(std::is_class_v, "no I/O support for this basic C++ type"); diff --git a/tree/ntuple/v7/inc/ROOT/RField/RFieldProxiedCollection.hxx b/tree/ntuple/v7/inc/ROOT/RField/RFieldProxiedCollection.hxx index 980df0da69485..a83673d8a93bf 100644 --- a/tree/ntuple/v7/inc/ROOT/RField/RFieldProxiedCollection.hxx +++ b/tree/ntuple/v7/inc/ROOT/RField/RFieldProxiedCollection.hxx @@ -268,7 +268,7 @@ struct IsCollectionProxy : HasCollectionProxyMemberType { template class RField::value>::type> final : public RProxiedCollectionField { public: - static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); } + static std::string TypeName() { return ROOT::Internal::GetRenormalizedDemangledTypeName(typeid(T)); } RField(std::string_view name) : RProxiedCollectionField(name, TypeName()) { static_assert(std::is_class::value, "collection proxy unsupported for fundamental types"); diff --git a/tree/ntuple/v7/inc/ROOT/RFieldUtils.hxx b/tree/ntuple/v7/inc/ROOT/RFieldUtils.hxx index 668862727c497..2d668aebc72a8 100644 --- a/tree/ntuple/v7/inc/ROOT/RFieldUtils.hxx +++ b/tree/ntuple/v7/inc/ROOT/RFieldUtils.hxx @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -26,6 +27,10 @@ std::string GetCanonicalTypePrefix(const std::string &typeName); /// Given a type name normalized by ROOT meta, renormalize it for RNTuple. E.g., insert std::prefix. std::string GetRenormalizedTypeName(const std::string &metaNormalizedName); +/// Given a type info ask ROOT meta to demangle it, then renormalize the resulting type name for RNTuple. Useful to +/// ensure that e.g. fundamental types are normalized to the type used by RNTuple (e.g. int -> std::int32_t). +std::string GetRenormalizedDemangledTypeName(const std::type_info &ti); + /// Applies all RNTuple type normalization rules except typedef resolution. std::string GetNormalizedUnresolvedTypeName(const std::string &origName); diff --git a/tree/ntuple/v7/src/RFieldUtils.cxx b/tree/ntuple/v7/src/RFieldUtils.cxx index f8754ff32ad46..b640aba7a7d43 100644 --- a/tree/ntuple/v7/src/RFieldUtils.cxx +++ b/tree/ntuple/v7/src/RFieldUtils.cxx @@ -463,3 +463,8 @@ std::vector ROOT::Internal::TokenizeTypeList(std::string_view templ result.push_back(std::string(typeBegin, typeCursor - typeBegin)); return result; } + +std::string ROOT::Internal::GetRenormalizedDemangledTypeName(const std::type_info &ti) +{ + return ROOT::Internal::GetRenormalizedTypeName(ROOT::Internal::GetDemangledTypeName(ti)); +} diff --git a/tree/ntuple/v7/test/CustomStructLinkDef.h b/tree/ntuple/v7/test/CustomStructLinkDef.h index 9b267d4a0850d..b10c1333182b9 100644 --- a/tree/ntuple/v7/test/CustomStructLinkDef.h +++ b/tree/ntuple/v7/test/CustomStructLinkDef.h @@ -28,6 +28,7 @@ #pragma link C++ class DataVector < int, double> + ; #pragma link C++ class DataVector < int, float> + ; #pragma link C++ class DataVector < bool, std::vector < unsigned int>> + ; +#pragma link C++ class DataVector < StructUsingCollectionProxy < int>, double> + ; #pragma link C++ class DataVector < int, double> ::Inner + ; #pragma link C++ class DataVector < int, double> ::Inner + ; #pragma link C++ class DataVector < int, float> ::Inner + ; diff --git a/tree/ntuple/v7/test/ntuple_type_name.cxx b/tree/ntuple/v7/test/ntuple_type_name.cxx index 3d4e01b564232..bcc4d56412c03 100644 --- a/tree/ntuple/v7/test/ntuple_type_name.cxx +++ b/tree/ntuple/v7/test/ntuple_type_name.cxx @@ -70,6 +70,7 @@ TEST(RNTuple, TClassDefaultTemplateParameter) model->AddField(RFieldBase::Create("f4", "struct DataVector>").Unwrap()); model->AddField(RFieldBase::Create("f5", "DataVector").Unwrap()); model->AddField(RFieldBase::Create("f6", "DataVector").Unwrap()); + model->MakeField>>("f7"); auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath()); } @@ -99,6 +100,11 @@ TEST(RNTuple, TClassDefaultTemplateParameter) auto v1 = reader->GetView>("f1"); auto v3 = reader->GetView>("f3"); EXPECT_THROW(reader->GetView>("f2"), ROOT::RException); + + // Ensure the typed API does not throw an exception + auto f1 = reader->GetModel().GetDefaultEntry().GetPtr>("f1"); + auto f4 = reader->GetModel().GetDefaultEntry().GetPtr>>("f4"); + auto f7 = reader->GetModel().GetDefaultEntry().GetPtr>>("f7"); } TEST(RNTuple, TemplateArgIntegerNormalization)