diff --git a/tree/ntuple/v7/inc/ROOT/RField/RFieldRecord.hxx b/tree/ntuple/v7/inc/ROOT/RField/RFieldRecord.hxx index a3c19502cb3a0..02a9484d0f9f3 100644 --- a/tree/ntuple/v7/inc/ROOT/RField/RFieldRecord.hxx +++ b/tree/ntuple/v7/inc/ROOT/RField/RFieldRecord.hxx @@ -85,6 +85,9 @@ protected: fTraits &= itemFields[i]->GetTraits(); Attach(std::move(itemFields[i])); } + // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the + // requirements of the type with strictest alignment + fSize += GetItemPadding(fSize, fMaxAlignment); } public: @@ -145,8 +148,8 @@ public: static std::string TypeName() { return "std::pair<" + RField::TypeName() + "," + RField::TypeName() + ">"; } explicit RField(std::string_view name) : RPairField(name, BuildItemFields(), BuildItemOffsets()) { - fMaxAlignment = std::max(alignof(T1), alignof(T2)); - fSize = sizeof(ContainerT); + R__ASSERT(fMaxAlignment >= std::max(alignof(T1), alignof(T2))); + R__ASSERT(fSize >= sizeof(ContainerT)); } RField(RField &&other) = default; RField &operator=(RField &&other) = default; @@ -221,8 +224,8 @@ public: static std::string TypeName() { return "std::tuple<" + BuildItemTypes() + ">"; } explicit RField(std::string_view name) : RTupleField(name, BuildItemFields(), BuildItemOffsets()) { - fMaxAlignment = std::max({alignof(ItemTs)...}); - fSize = sizeof(ContainerT); + R__ASSERT(fMaxAlignment >= std::max({alignof(ItemTs)...})); + R__ASSERT(fSize >= sizeof(ContainerT)); } RField(RField &&other) = default; RField &operator=(RField &&other) = default; diff --git a/tree/ntuple/v7/src/RField.cxx b/tree/ntuple/v7/src/RField.cxx index d9e2f33b00aca..b4dbd0622cd5e 100644 --- a/tree/ntuple/v7/src/RField.cxx +++ b/tree/ntuple/v7/src/RField.cxx @@ -2522,6 +2522,9 @@ void ROOT::Experimental::RRecordField::RRecordField::AttachItemFields( fTraits &= item->GetTraits(); Attach(std::move(item)); } + // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the + // requirements of the type with strictest alignment + fSize += GetItemPadding(fSize, fMaxAlignment); } ROOT::Experimental::RRecordField::RRecordField(std::string_view fieldName, diff --git a/tree/ntuple/v7/test/ntuple_types.cxx b/tree/ntuple/v7/test/ntuple_types.cxx index 08a97c01828f4..79d48ba359c35 100644 --- a/tree/ntuple/v7/test/ntuple_types.cxx +++ b/tree/ntuple/v7/test/ntuple_types.cxx @@ -307,6 +307,14 @@ TEST(RNTuple, StdTuple) "tupleTupleField"); EXPECT_STREQ("std::tuple,std::vector>>", tupleTupleField.GetTypeName().c_str()); + using TupleMapSetType = std::tuple, std::set>; + auto tupleMapSetField = RField("tupleMapSetField"); + EXPECT_LE(sizeof(TupleMapSetType), tupleMapSetField.GetValueSize()); + EXPECT_LE(alignof(TupleMapSetType), tupleMapSetField.GetAlignment()); + using TupleUnorderedMapSetType = std::tuple, std::unordered_set>; + auto tupleUnorderedMapSetField = RField("tupleUnorderedMapSetField"); + EXPECT_LE(sizeof(TupleUnorderedMapSetType), tupleUnorderedMapSetField.GetValueSize()); + EXPECT_LE(alignof(TupleUnorderedMapSetType), tupleUnorderedMapSetField.GetAlignment()); FileRaii fileGuard("test_ntuple_rfield_stdtuple.root"); {