diff --git a/tree/ntuple/inc/ROOT/RField/RFieldProxiedCollection.hxx b/tree/ntuple/inc/ROOT/RField/RFieldProxiedCollection.hxx index 25ccd270cf638..34e3217242844 100644 --- a/tree/ntuple/inc/ROOT/RField/RFieldProxiedCollection.hxx +++ b/tree/ntuple/inc/ROOT/RField/RFieldProxiedCollection.hxx @@ -150,13 +150,10 @@ protected: ROOT::Internal::RColumnIndex fNWritten; /// Constructor used when the value type of the collection is not known in advance, i.e. in the case of custom - /// collections. + /// collections. Note that this constructor requires manual initialization of the item field + /// (Attach() and setting fItemSize) RProxiedCollectionField(std::string_view fieldName, TClass *classp); - /// Constructor used when the value type of the collection is known in advance, e.g. in RSetField. - RProxiedCollectionField(std::string_view fieldName, std::string_view typeName, - std::unique_ptr itemField); -protected: std::unique_ptr CloneImpl(std::string_view newName) const final; const RColumnRepresentations &GetColumnRepresentations() const final; void GenerateColumns() final; @@ -284,7 +281,13 @@ public: /// The generic field for a `std::map` and `std::unordered_map` class RMapField : public RProxiedCollectionField { public: - RMapField(std::string_view fieldName, std::string_view typeName, std::unique_ptr itemField); + enum class EMapType { + kMap, + kUnorderedMap, + kMultiMap, + kUnorderedMultiMap + }; + RMapField(std::string_view fieldName, EMapType mapType, std::unique_ptr itemField); RMapField(RMapField &&other) = default; RMapField &operator=(RMapField &&other) = default; ~RMapField() override = default; @@ -299,7 +302,7 @@ public: } explicit RField(std::string_view name) - : RMapField(name, TypeName(), std::make_unique>>("_0")) + : RMapField(name, EMapType::kMap, std::make_unique>>("_0")) { } RField(RField &&other) = default; @@ -316,7 +319,7 @@ public: } explicit RField(std::string_view name) - : RMapField(name, TypeName(), std::make_unique>>("_0")) + : RMapField(name, EMapType::kUnorderedMap, std::make_unique>>("_0")) { } RField(RField &&other) = default; @@ -333,7 +336,7 @@ public: } explicit RField(std::string_view name) - : RMapField(name, TypeName(), std::make_unique>>("_0")) + : RMapField(name, EMapType::kMultiMap, std::make_unique>>("_0")) { } RField(RField &&other) = default; @@ -350,7 +353,7 @@ public: } explicit RField(std::string_view name) - : RMapField(name, TypeName(), std::make_unique>>("_0")) + : RMapField(name, EMapType::kUnorderedMultiMap, std::make_unique>>("_0")) { } RField(RField &&other) = default; @@ -365,7 +368,13 @@ public: /// The generic field for a `std::set` and `std::unordered_set` class RSetField : public RProxiedCollectionField { public: - RSetField(std::string_view fieldName, std::string_view typeName, std::unique_ptr itemField); + enum class ESetType { + kSet, + kUnorderedSet, + kMultiSet, + kUnorderedMultiSet + }; + RSetField(std::string_view fieldName, ESetType setType, std::unique_ptr itemField); RSetField(RSetField &&other) = default; RSetField &operator=(RSetField &&other) = default; ~RSetField() override = default; @@ -376,7 +385,7 @@ class RField> final : public RSetField { public: static std::string TypeName() { return "std::set<" + RField::TypeName() + ">"; } - explicit RField(std::string_view name) : RSetField(name, TypeName(), std::make_unique>("_0")) {} + explicit RField(std::string_view name) : RSetField(name, ESetType::kSet, std::make_unique>("_0")) {} RField(RField &&other) = default; RField &operator=(RField &&other) = default; ~RField() final = default; @@ -387,7 +396,10 @@ class RField> final : public RSetField { public: static std::string TypeName() { return "std::unordered_set<" + RField::TypeName() + ">"; } - explicit RField(std::string_view name) : RSetField(name, TypeName(), std::make_unique>("_0")) {} + explicit RField(std::string_view name) + : RSetField(name, ESetType::kUnorderedSet, std::make_unique>("_0")) + { + } RField(RField &&other) = default; RField &operator=(RField &&other) = default; ~RField() final = default; @@ -398,7 +410,9 @@ class RField> final : public RSetField { public: static std::string TypeName() { return "std::multiset<" + RField::TypeName() + ">"; } - explicit RField(std::string_view name) : RSetField(name, TypeName(), std::make_unique>("_0")) {} + explicit RField(std::string_view name) : RSetField(name, ESetType::kMultiSet, std::make_unique>("_0")) + { + } RField(RField &&other) = default; RField &operator=(RField &&other) = default; ~RField() final = default; @@ -409,7 +423,10 @@ class RField> final : public RSetField { public: static std::string TypeName() { return "std::unordered_multiset<" + RField::TypeName() + ">"; } - explicit RField(std::string_view name) : RSetField(name, TypeName(), std::make_unique>("_0")) {} + explicit RField(std::string_view name) + : RSetField(name, ESetType::kUnorderedMultiSet, std::make_unique>("_0")) + { + } RField(RField &&other) = default; RField &operator=(RField &&other) = default; ~RField() final = default; diff --git a/tree/ntuple/inc/ROOT/RField/RFieldSTLMisc.hxx b/tree/ntuple/inc/ROOT/RField/RFieldSTLMisc.hxx index 9256686ee0afb..066eeb061e4f1 100644 --- a/tree/ntuple/inc/ROOT/RField/RFieldSTLMisc.hxx +++ b/tree/ntuple/inc/ROOT/RField/RFieldSTLMisc.hxx @@ -57,7 +57,7 @@ protected: void ReconcileOnDiskField(const RNTupleDescriptor &desc) final; public: - RAtomicField(std::string_view fieldName, std::string_view typeName, std::unique_ptr itemField); + RAtomicField(std::string_view fieldName, std::unique_ptr itemField); RAtomicField(RAtomicField &&other) = default; RAtomicField &operator=(RAtomicField &&other) = default; ~RAtomicField() override = default; @@ -74,7 +74,7 @@ template class RField> final : public RAtomicField { public: static std::string TypeName() { return "std::atomic<" + RField::TypeName() + ">"; } - explicit RField(std::string_view name) : RAtomicField(name, TypeName(), std::make_unique>("_0")) {} + explicit RField(std::string_view name) : RAtomicField(name, std::make_unique>("_0")) {} RField(RField &&other) = default; RField &operator=(RField &&other) = default; ~RField() final = default; @@ -209,7 +209,7 @@ protected: /// if it is null, returns `kInvalidNTupleIndex` RNTupleLocalIndex GetItemIndex(ROOT::NTupleSize_t globalIndex); - RNullableField(std::string_view fieldName, std::string_view typeName, std::unique_ptr itemField); + RNullableField(std::string_view fieldName, const std::string &typePrefix, std::unique_ptr itemField); public: RNullableField(RNullableField &&other) = default; @@ -249,7 +249,7 @@ protected: void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final; public: - ROptionalField(std::string_view fieldName, std::string_view typeName, std::unique_ptr itemField); + ROptionalField(std::string_view fieldName, std::unique_ptr itemField); ROptionalField(ROptionalField &&other) = default; ROptionalField &operator=(ROptionalField &&other) = default; ~ROptionalField() override = default; @@ -263,7 +263,7 @@ template class RField> final : public ROptionalField { public: static std::string TypeName() { return "std::optional<" + RField::TypeName() + ">"; } - explicit RField(std::string_view name) : ROptionalField(name, TypeName(), std::make_unique>("_0")) {} + explicit RField(std::string_view name) : ROptionalField(name, std::make_unique>("_0")) {} RField(RField &&other) = default; RField &operator=(RField &&other) = default; ~RField() final = default; @@ -291,7 +291,7 @@ protected: void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final; public: - RUniquePtrField(std::string_view fieldName, std::string_view typeName, std::unique_ptr itemField); + RUniquePtrField(std::string_view fieldName, std::unique_ptr itemField); RUniquePtrField(RUniquePtrField &&other) = default; RUniquePtrField &operator=(RUniquePtrField &&other) = default; ~RUniquePtrField() override = default; @@ -305,7 +305,7 @@ template class RField> final : public RUniquePtrField { public: static std::string TypeName() { return "std::unique_ptr<" + RField::TypeName() + ">"; } - explicit RField(std::string_view name) : RUniquePtrField(name, TypeName(), std::make_unique>("_0")) {} + explicit RField(std::string_view name) : RUniquePtrField(name, std::make_unique>("_0")) {} RField(RField &&other) = default; RField &operator=(RField &&other) = default; ~RField() final = default; diff --git a/tree/ntuple/src/RField.cxx b/tree/ntuple/src/RField.cxx index 5a30d191ad798..8ea7d931e4fa3 100644 --- a/tree/ntuple/src/RField.cxx +++ b/tree/ntuple/src/RField.cxx @@ -761,9 +761,10 @@ void ROOT::RBitsetField::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) con //------------------------------------------------------------------------------ -ROOT::RNullableField::RNullableField(std::string_view fieldName, std::string_view typeName, +ROOT::RNullableField::RNullableField(std::string_view fieldName, const std::string &typePrefix, std::unique_ptr itemField) - : ROOT::RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kCollection, false /* isSimple */) + : ROOT::RFieldBase(fieldName, typePrefix + "<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection, + false /* isSimple */) { Attach(std::move(itemField)); } @@ -826,16 +827,15 @@ void ROOT::RNullableField::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) c //------------------------------------------------------------------------------ -ROOT::RUniquePtrField::RUniquePtrField(std::string_view fieldName, std::string_view typeName, - std::unique_ptr itemField) - : RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0])) +ROOT::RUniquePtrField::RUniquePtrField(std::string_view fieldName, std::unique_ptr itemField) + : RNullableField(fieldName, "std::unique_ptr", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0])) { } std::unique_ptr ROOT::RUniquePtrField::CloneImpl(std::string_view newName) const { auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName()); - return std::make_unique(newName, GetTypeName(), std::move(newItemField)); + return std::make_unique(newName, std::move(newItemField)); } std::size_t ROOT::RUniquePtrField::AppendImpl(const void *from) @@ -905,9 +905,8 @@ std::vector ROOT::RUniquePtrField::SplitValue(const RV //------------------------------------------------------------------------------ -ROOT::ROptionalField::ROptionalField(std::string_view fieldName, std::string_view typeName, - std::unique_ptr itemField) - : RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0])) +ROOT::ROptionalField::ROptionalField(std::string_view fieldName, std::unique_ptr itemField) + : RNullableField(fieldName, "std::optional", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0])) { if (fSubfields[0]->GetTraits() & kTraitTriviallyDestructible) fTraits |= kTraitTriviallyDestructible; @@ -926,7 +925,7 @@ const bool *ROOT::ROptionalField::GetEngagementPtr(const void *optionalPtr) cons std::unique_ptr ROOT::ROptionalField::CloneImpl(std::string_view newName) const { auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName()); - return std::make_unique(newName, GetTypeName(), std::move(newItemField)); + return std::make_unique(newName, std::move(newItemField)); } std::size_t ROOT::ROptionalField::AppendImpl(const void *from) @@ -1007,9 +1006,9 @@ size_t ROOT::ROptionalField::GetAlignment() const //------------------------------------------------------------------------------ -ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::string_view typeName, - std::unique_ptr itemField) - : RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kPlain, false /* isSimple */) +ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::unique_ptr itemField) + : RFieldBase(fieldName, "std::atomic<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kPlain, + false /* isSimple */) { if (itemField->GetTraits() & kTraitTriviallyConstructible) fTraits |= kTraitTriviallyConstructible; @@ -1021,7 +1020,7 @@ ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::string_view ty std::unique_ptr ROOT::RAtomicField::CloneImpl(std::string_view newName) const { auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName()); - return std::make_unique(newName, GetTypeName(), std::move(newItemField)); + return std::make_unique(newName, std::move(newItemField)); } void ROOT::RAtomicField::ReconcileOnDiskField(const RNTupleDescriptor &desc) diff --git a/tree/ntuple/src/RFieldBase.cxx b/tree/ntuple/src/RFieldBase.cxx index e87dde58ceb51..6c4a0b4c481f2 100644 --- a/tree/ntuple/src/RFieldBase.cxx +++ b/tree/ntuple/src/RFieldBase.cxx @@ -418,111 +418,66 @@ ROOT::RFieldBase::Create(const std::string &fieldName, const std::string &typeNa } else if (resolvedType.substr(0, 16) == "std::unique_ptr<") { std::string itemTypeName = resolvedType.substr(16, resolvedType.length() - 17); auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap(); - auto normalizedInnerTypeName = itemField->GetTypeName(); - result = std::make_unique(fieldName, "std::unique_ptr<" + normalizedInnerTypeName + ">", - std::move(itemField)); + result = std::make_unique(fieldName, std::move(itemField)); } else if (resolvedType.substr(0, 14) == "std::optional<") { std::string itemTypeName = resolvedType.substr(14, resolvedType.length() - 15); auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap(); - auto normalizedInnerTypeName = itemField->GetTypeName(); - result = std::make_unique(fieldName, "std::optional<" + normalizedInnerTypeName + ">", - std::move(itemField)); + result = std::make_unique(fieldName, std::move(itemField)); } else if (resolvedType.substr(0, 9) == "std::set<") { std::string itemTypeName = resolvedType.substr(9, resolvedType.length() - 10); auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap(); - auto normalizedInnerTypeName = itemField->GetTypeName(); - result = - std::make_unique(fieldName, "std::set<" + normalizedInnerTypeName + ">", std::move(itemField)); + result = std::make_unique(fieldName, RSetField::ESetType::kSet, std::move(itemField)); } else if (resolvedType.substr(0, 19) == "std::unordered_set<") { std::string itemTypeName = resolvedType.substr(19, resolvedType.length() - 20); auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap(); - auto normalizedInnerTypeName = itemField->GetTypeName(); - result = std::make_unique(fieldName, "std::unordered_set<" + normalizedInnerTypeName + ">", - std::move(itemField)); + result = std::make_unique(fieldName, RSetField::ESetType::kUnorderedSet, std::move(itemField)); } else if (resolvedType.substr(0, 14) == "std::multiset<") { std::string itemTypeName = resolvedType.substr(14, resolvedType.length() - 15); auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap(); - auto normalizedInnerTypeName = itemField->GetTypeName(); - result = std::make_unique(fieldName, "std::multiset<" + normalizedInnerTypeName + ">", - std::move(itemField)); + result = std::make_unique(fieldName, RSetField::ESetType::kMultiSet, std::move(itemField)); } else if (resolvedType.substr(0, 24) == "std::unordered_multiset<") { std::string itemTypeName = resolvedType.substr(24, resolvedType.length() - 25); auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap(); auto normalizedInnerTypeName = itemField->GetTypeName(); - result = std::make_unique(fieldName, "std::unordered_multiset<" + normalizedInnerTypeName + ">", - std::move(itemField)); + result = std::make_unique(fieldName, RSetField::ESetType::kUnorderedMultiSet, std::move(itemField)); } else if (resolvedType.substr(0, 9) == "std::map<") { auto innerTypes = TokenizeTypeList(resolvedType.substr(9, resolvedType.length() - 10)); if (innerTypes.size() != 2) { return R__FORWARD_RESULT(fnFail("the type list for std::map must have exactly two elements")); } - auto itemField = Create("_0", "std::pair<" + innerTypes[0] + "," + innerTypes[1] + ">", options, desc, maybeGetChildId(0)) .Unwrap(); - - // We use the type names of subfields of the newly created item fields to create the map's type name to - // ensure the inner type names are properly normalized. - auto keyTypeName = itemField->GetConstSubfields()[0]->GetTypeName(); - auto valueTypeName = itemField->GetConstSubfields()[1]->GetTypeName(); - - result = std::make_unique(fieldName, "std::map<" + keyTypeName + "," + valueTypeName + ">", - std::move(itemField)); + result = std::make_unique(fieldName, RMapField::EMapType::kMap, std::move(itemField)); } else if (resolvedType.substr(0, 19) == "std::unordered_map<") { auto innerTypes = TokenizeTypeList(resolvedType.substr(19, resolvedType.length() - 20)); if (innerTypes.size() != 2) return R__FORWARD_RESULT(fnFail("the type list for std::unordered_map must have exactly two elements")); - auto itemField = Create("_0", "std::pair<" + innerTypes[0] + "," + innerTypes[1] + ">", options, desc, maybeGetChildId(0)) .Unwrap(); - - // We use the type names of subfields of the newly created item fields to create the map's type name to - // ensure the inner type names are properly normalized. - auto keyTypeName = itemField->GetConstSubfields()[0]->GetTypeName(); - auto valueTypeName = itemField->GetConstSubfields()[1]->GetTypeName(); - - result = std::make_unique( - fieldName, "std::unordered_map<" + keyTypeName + "," + valueTypeName + ">", std::move(itemField)); + result = std::make_unique(fieldName, RMapField::EMapType::kUnorderedMap, std::move(itemField)); } else if (resolvedType.substr(0, 14) == "std::multimap<") { auto innerTypes = TokenizeTypeList(resolvedType.substr(14, resolvedType.length() - 15)); if (innerTypes.size() != 2) return R__FORWARD_RESULT(fnFail("the type list for std::multimap must have exactly two elements")); - auto itemField = Create("_0", "std::pair<" + innerTypes[0] + "," + innerTypes[1] + ">", options, desc, maybeGetChildId(0)) .Unwrap(); - - // We use the type names of subfields of the newly created item fields to create the map's type name to - // ensure the inner type names are properly normalized. - auto keyTypeName = itemField->GetConstSubfields()[0]->GetTypeName(); - auto valueTypeName = itemField->GetConstSubfields()[1]->GetTypeName(); - - result = std::make_unique(fieldName, "std::multimap<" + keyTypeName + "," + valueTypeName + ">", - std::move(itemField)); + result = std::make_unique(fieldName, RMapField::EMapType::kMultiMap, std::move(itemField)); } else if (resolvedType.substr(0, 24) == "std::unordered_multimap<") { auto innerTypes = TokenizeTypeList(resolvedType.substr(24, resolvedType.length() - 25)); if (innerTypes.size() != 2) return R__FORWARD_RESULT( fnFail("the type list for std::unordered_multimap must have exactly two elements")); - auto itemField = Create("_0", "std::pair<" + innerTypes[0] + "," + innerTypes[1] + ">", options, desc, maybeGetChildId(0)) .Unwrap(); - - // We use the type names of subfields of the newly created item fields to create the map's type name to - // ensure the inner type names are properly normalized. - auto keyTypeName = itemField->GetConstSubfields()[0]->GetTypeName(); - auto valueTypeName = itemField->GetConstSubfields()[1]->GetTypeName(); - - result = std::make_unique( - fieldName, "std::unordered_multimap<" + keyTypeName + "," + valueTypeName + ">", std::move(itemField)); + result = std::make_unique(fieldName, RMapField::EMapType::kUnorderedMultiMap, std::move(itemField)); } else if (resolvedType.substr(0, 12) == "std::atomic<") { std::string itemTypeName = resolvedType.substr(12, resolvedType.length() - 13); auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap(); - auto normalizedInnerTypeName = itemField->GetTypeName(); - result = std::make_unique(fieldName, "std::atomic<" + normalizedInnerTypeName + ">", - std::move(itemField)); + result = std::make_unique(fieldName, std::move(itemField)); } else if (resolvedType.substr(0, 25) == "ROOT::RNTupleCardinality<") { auto innerTypes = TokenizeTypeList(resolvedType.substr(25, resolvedType.length() - 26)); if (innerTypes.size() != 1) diff --git a/tree/ntuple/src/RFieldMeta.cxx b/tree/ntuple/src/RFieldMeta.cxx index b16b4955aafe2..d47e86e60ea25 100644 --- a/tree/ntuple/src/RFieldMeta.cxx +++ b/tree/ntuple/src/RFieldMeta.cxx @@ -71,6 +71,37 @@ TEnum *EnsureValidEnum(std::string_view enumName) return e; } +std::string BuildSetTypeName(ROOT::RSetField::ESetType setType, const ROOT::RFieldBase &innerField) +{ + std::string typePrefix; + switch (setType) { + case ROOT::RSetField::ESetType::kSet: typePrefix = "std::set<"; break; + case ROOT::RSetField::ESetType::kUnorderedSet: typePrefix = "std::unordered_set<"; break; + case ROOT::RSetField::ESetType::kMultiSet: typePrefix = "std::multiset<"; break; + case ROOT::RSetField::ESetType::kUnorderedMultiSet: typePrefix = "std::unordered_multiset<"; break; + default: R__ASSERT(false); + } + return typePrefix + innerField.GetTypeName() + ">"; +} + +std::string BuildMapTypeName(ROOT::RMapField::EMapType mapType, const ROOT::RFieldBase *innerField) +{ + if (const auto pairField = dynamic_cast(innerField)) { + std::string typePrefix; + switch (mapType) { + case ROOT::RMapField::EMapType::kMap: typePrefix = "std::map<"; break; + case ROOT::RMapField::EMapType::kUnorderedMap: typePrefix = "std::unordered_map<"; break; + case ROOT::RMapField::EMapType::kMultiMap: typePrefix = "std::multimap<"; break; + case ROOT::RMapField::EMapType::kUnorderedMultiMap: typePrefix = "std::unordered_multimap<"; break; + default: R__ASSERT(false); + } + auto subFields = pairField->GetConstSubfields(); + return typePrefix + subFields[0]->GetTypeName() + "," + subFields[1]->GetTypeName() + ">"; + } + + throw ROOT::RException(R__FAIL("RMapField inner field type must be of RPairField")); +} + } // anonymous namespace ROOT::RClassField::RClassField(std::string_view fieldName, const RClassField &source) @@ -657,14 +688,6 @@ ROOT::RProxiedCollectionField::RProxiedCollectionField(std::string_view fieldNam fIFuncsWrite = RCollectionIterableOnce::GetIteratorFuncs(fProxy.get(), false /* readFromDisk */); } -ROOT::RProxiedCollectionField::RProxiedCollectionField(std::string_view fieldName, std::string_view typeName, - std::unique_ptr itemField) - : RProxiedCollectionField(fieldName, EnsureValidClass(typeName)) -{ - fItemSize = itemField->GetValueSize(); - Attach(std::move(itemField)); -} - ROOT::RProxiedCollectionField::RProxiedCollectionField(std::string_view fieldName, std::string_view typeName) : RProxiedCollectionField(fieldName, EnsureValidClass(typeName)) { @@ -703,8 +726,11 @@ ROOT::RProxiedCollectionField::RProxiedCollectionField(std::string_view fieldNam std::unique_ptr ROOT::RProxiedCollectionField::CloneImpl(std::string_view newName) const { auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName()); - return std::unique_ptr( - new RProxiedCollectionField(newName, GetTypeName(), std::move(newItemField))); + auto clone = + std::unique_ptr(new RProxiedCollectionField(newName, fProxy->GetCollectionClass())); + clone->fItemSize = fItemSize; + clone->Attach(std::move(newItemField)); + return clone; } std::size_t ROOT::RProxiedCollectionField::AppendImpl(const void *from) @@ -812,12 +838,9 @@ void ROOT::RProxiedCollectionField::AcceptVisitor(ROOT::Detail::RFieldVisitor &v //------------------------------------------------------------------------------ -ROOT::RMapField::RMapField(std::string_view fieldName, std::string_view typeName, std::unique_ptr itemField) - : RProxiedCollectionField(fieldName, EnsureValidClass(typeName)) +ROOT::RMapField::RMapField(std::string_view fieldName, EMapType mapType, std::unique_ptr itemField) + : RProxiedCollectionField(fieldName, EnsureValidClass(BuildMapTypeName(mapType, itemField.get()))) { - if (!dynamic_cast(itemField.get())) - throw RException(R__FAIL("RMapField inner field type must be of RPairField")); - auto *itemClass = fProxy->GetValueClass(); fItemSize = itemClass->GetClassSize(); @@ -826,9 +849,11 @@ ROOT::RMapField::RMapField(std::string_view fieldName, std::string_view typeName //------------------------------------------------------------------------------ -ROOT::RSetField::RSetField(std::string_view fieldName, std::string_view typeName, std::unique_ptr itemField) - : ROOT::RProxiedCollectionField(fieldName, typeName, std::move(itemField)) +ROOT::RSetField::RSetField(std::string_view fieldName, ESetType setType, std::unique_ptr itemField) + : ROOT::RProxiedCollectionField(fieldName, EnsureValidClass(BuildSetTypeName(setType, *itemField))) { + fItemSize = itemField->GetValueSize(); + Attach(std::move(itemField)); } //------------------------------------------------------------------------------ diff --git a/tree/ntuple/test/ntuple_types.cxx b/tree/ntuple/test/ntuple_types.cxx index 23ebbda982069..2675d93be1f27 100644 --- a/tree/ntuple/test/ntuple_types.cxx +++ b/tree/ntuple/test/ntuple_types.cxx @@ -586,8 +586,9 @@ TEST(RNTuple, StdMap) EXPECT_THROW(RFieldBase::Create("myInvalidMap", "std::map").Unwrap(), ROOT::RException); auto invalidInnerField = RFieldBase::Create("someIntField", "int").Unwrap(); - EXPECT_THROW(std::make_unique("myInvalidMap", "std::map", std::move(invalidInnerField)), - ROOT::RException); + EXPECT_THROW( + std::make_unique("myInvalidMap", ROOT::RMapField::EMapType::kMap, std::move(invalidInnerField)), + ROOT::RException); FileRaii fileGuard("test_ntuple_rfield_stdmap.root"); {