Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions tree/ntuple/inc/ROOT/RField/RFieldRecord.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,6 @@ public:

/// The generic field for `std::pair<T1, T2>` types
class RPairField : public RRecordField {
private:
static std::string GetTypeList(const std::array<std::unique_ptr<RFieldBase>, 2> &itemFields);

protected:
RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> itemFields,
const std::array<std::size_t, 2> &offsets);
Expand Down Expand Up @@ -188,9 +185,6 @@ public:

/// The generic field for `std::tuple<Ts...>` types
class RTupleField : public RRecordField {
private:
static std::string GetTypeList(const std::vector<std::unique_ptr<RFieldBase>> &itemFields);

protected:
RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
const std::vector<std::size_t> &offsets);
Expand Down
1 change: 0 additions & 1 deletion tree/ntuple/inc/ROOT/RField/RFieldSTLMisc.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,6 @@ private:
size_t fVariantOffset = 0;
std::vector<ROOT::Internal::RColumnIndex::ValueType> fNWritten;

static std::string GetTypeList(const std::vector<std::unique_ptr<RFieldBase>> &itemFields);
/// Extracts the index from an `std::variant` and transforms it into the 1-based index used for the switch column
/// The implementation supports two memory layouts that are in use: a trailing unsigned byte, zero-indexed,
/// having the exception caused empty state encoded by the max tag value,
Expand Down
7 changes: 7 additions & 0 deletions tree/ntuple/src/RField.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,9 @@ ROOT::RNullableField::RNullableField(std::string_view fieldName, const std::stri
: ROOT::RFieldBase(fieldName, typePrefix + "<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection,
false /* isSimple */)
{
if (!itemField->GetTypeAlias().empty())
fTypeAlias = typePrefix + "<" + itemField->GetTypeAlias() + ">";

Attach(std::move(itemField));
}

Expand Down Expand Up @@ -1183,6 +1186,10 @@ ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::unique_ptr<RFi
fTraits |= kTraitTriviallyConstructible;
if (itemField->GetTraits() & kTraitTriviallyDestructible)
fTraits |= kTraitTriviallyDestructible;

if (!itemField->GetTypeAlias().empty())
fTypeAlias = "std::atomic<" + itemField->GetTypeAlias() + ">";

Attach(std::move(itemField));
}

Expand Down
115 changes: 74 additions & 41 deletions tree/ntuple/src/RFieldMeta.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,25 @@ TEnum *EnsureValidEnum(std::string_view enumName)
return e;
}

std::string BuildSetTypeName(ROOT::RSetField::ESetType setType, const ROOT::RFieldBase &innerField)
std::string GetTypeList(std::span<std::unique_ptr<ROOT::RFieldBase>> itemFields, bool useTypeAliases)
Copy link
Member

@pcanal pcanal Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a short summary of the behavior (Intend of the use of the result, reach of the list).

{
std::string result;
for (size_t i = 0; i < itemFields.size(); ++i) {
if (useTypeAliases && !itemFields[i]->GetTypeAlias().empty()) {
result += itemFields[i]->GetTypeAlias();
} else {
result += itemFields[i]->GetTypeName();
}
result.push_back(',');
}
if (result.empty()) {
throw ROOT::RException(R__FAIL("invalid empty type list provided as template argument"));
}
result.pop_back(); // remove trailing comma
return result;
}

std::string BuildSetTypeName(ROOT::RSetField::ESetType setType, const ROOT::RFieldBase &innerField, bool useTypeAlias)
{
std::string typePrefix;
switch (setType) {
Expand All @@ -81,10 +99,13 @@ std::string BuildSetTypeName(ROOT::RSetField::ESetType setType, const ROOT::RFie
case ROOT::RSetField::ESetType::kUnorderedMultiSet: typePrefix = "std::unordered_multiset<"; break;
default: R__ASSERT(false);
}
return typePrefix + innerField.GetTypeName() + ">";
return typePrefix +
((useTypeAlias && !innerField.GetTypeAlias().empty()) ? innerField.GetTypeAlias()
: innerField.GetTypeName()) +
">";
}

std::string BuildMapTypeName(ROOT::RMapField::EMapType mapType, const ROOT::RFieldBase *innerField)
std::string BuildMapTypeName(ROOT::RMapField::EMapType mapType, const ROOT::RFieldBase *innerField, bool useTypeAliases)
{
if (const auto pairField = dynamic_cast<const ROOT::RPairField *>(innerField)) {
std::string typePrefix;
Expand All @@ -95,8 +116,18 @@ std::string BuildMapTypeName(ROOT::RMapField::EMapType mapType, const ROOT::RFie
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() + ">";
const auto &items = pairField->GetConstSubfields();
std::string type = typePrefix;
for (int i : {0, 1}) {
if (useTypeAliases && !items[i]->GetTypeAlias().empty()) {
type += items[i]->GetTypeAlias();
} else {
type += items[i]->GetTypeName();
}
if (i == 0)
type.push_back(',');
}
return type + ">";
}

throw ROOT::RException(R__FAIL("RMapField inner field type must be of RPairField"));
Expand Down Expand Up @@ -667,23 +698,26 @@ void ROOT::REnumField::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const

//------------------------------------------------------------------------------

std::string ROOT::RPairField::RPairField::GetTypeList(const std::array<std::unique_ptr<RFieldBase>, 2> &itemFields)
{
return itemFields[0]->GetTypeName() + "," + itemFields[1]->GetTypeName();
}

ROOT::RPairField::RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> itemFields,
const std::array<std::size_t, 2> &offsets)
: ROOT::RRecordField(fieldName, "std::pair<" + GetTypeList(itemFields) + ">")
: ROOT::RRecordField(fieldName, "std::pair<" + GetTypeList(itemFields, false /* useTypeAliases */) + ">")
{
const std::string typeAlias = "std::pair<" + GetTypeList(itemFields, true /* useTypeAliases */) + ">";
if (typeAlias != GetTypeName())
fTypeAlias = typeAlias;

AttachItemFields(std::move(itemFields));
fOffsets.push_back(offsets[0]);
fOffsets.push_back(offsets[1]);
}

ROOT::RPairField::RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> itemFields)
: ROOT::RRecordField(fieldName, "std::pair<" + GetTypeList(itemFields) + ">")
: ROOT::RRecordField(fieldName, "std::pair<" + GetTypeList(itemFields, false /* useTypeAliases */) + ">")
{
const std::string typeAlias = "std::pair<" + GetTypeList(itemFields, true /* useTypeAliases */) + ">";
if (typeAlias != GetTypeName())
fTypeAlias = typeAlias;

AttachItemFields(std::move(itemFields));

// ISO C++ does not guarantee any specific layout for `std::pair`; query TClass for the member offsets
Expand Down Expand Up @@ -929,8 +963,13 @@ void ROOT::RProxiedCollectionField::AcceptVisitor(ROOT::Detail::RFieldVisitor &v
//------------------------------------------------------------------------------

ROOT::RMapField::RMapField(std::string_view fieldName, EMapType mapType, std::unique_ptr<RFieldBase> itemField)
: RProxiedCollectionField(fieldName, EnsureValidClass(BuildMapTypeName(mapType, itemField.get()))), fMapType(mapType)
: RProxiedCollectionField(fieldName,
EnsureValidClass(BuildMapTypeName(mapType, itemField.get(), false /* useTypeAliases */))),
fMapType(mapType)
{
if (!itemField->GetTypeAlias().empty())
fTypeAlias = BuildMapTypeName(mapType, itemField.get(), true /* useTypeAliases */);

auto *itemClass = fProxy->GetValueClass();
fItemSize = itemClass->GetClassSize();

Expand Down Expand Up @@ -960,10 +999,15 @@ void ROOT::RMapField::ReconcileOnDiskField(const RNTupleDescriptor &desc)
//------------------------------------------------------------------------------

ROOT::RSetField::RSetField(std::string_view fieldName, ESetType setType, std::unique_ptr<RFieldBase> itemField)
: ROOT::RProxiedCollectionField(fieldName, EnsureValidClass(BuildSetTypeName(setType, *itemField))),
: ROOT::RProxiedCollectionField(fieldName,
EnsureValidClass(BuildSetTypeName(setType, *itemField, false /* useTypeAlias */))),
fSetType(setType)
{
if (!itemField->GetTypeAlias().empty())
fTypeAlias = BuildSetTypeName(setType, *itemField, true /* useTypeAlias */);

fItemSize = itemField->GetValueSize();

Attach(std::move(itemField));
}

Expand Down Expand Up @@ -1268,29 +1312,25 @@ void ROOT::RField<TObject>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor)

//------------------------------------------------------------------------------

std::string ROOT::RTupleField::RTupleField::GetTypeList(const std::vector<std::unique_ptr<RFieldBase>> &itemFields)
{
std::string result;
if (itemFields.empty())
throw RException(R__FAIL("the type list for std::tuple must have at least one element"));
for (size_t i = 0; i < itemFields.size(); ++i) {
result += itemFields[i]->GetTypeName() + ",";
}
result.pop_back(); // remove trailing comma
return result;
}

ROOT::RTupleField::RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
const std::vector<std::size_t> &offsets)
: ROOT::RRecordField(fieldName, "std::tuple<" + GetTypeList(itemFields) + ">")
: ROOT::RRecordField(fieldName, "std::tuple<" + GetTypeList(itemFields, false /* useTypeAliases */) + ">")
{
const std::string typeAlias = "std::tuple<" + GetTypeList(itemFields, true /* useTypeAliases */) + ">";
if (typeAlias != GetTypeName())
fTypeAlias = typeAlias;

AttachItemFields(std::move(itemFields));
fOffsets = offsets;
}

ROOT::RTupleField::RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
: ROOT::RRecordField(fieldName, "std::tuple<" + GetTypeList(itemFields) + ">")
: ROOT::RRecordField(fieldName, "std::tuple<" + GetTypeList(itemFields, false /* useTypeAliases */) + ">")
{
const std::string typeAlias = "std::tuple<" + GetTypeList(itemFields, true /* useTypeAliases */) + ">";
if (typeAlias != GetTypeName())
fTypeAlias = typeAlias;

AttachItemFields(std::move(itemFields));

auto *c = TClass::GetClass(GetTypeName().c_str());
Expand Down Expand Up @@ -1362,17 +1402,6 @@ struct RVariantTag {

} // anonymous namespace

std::string ROOT::RVariantField::GetTypeList(const std::vector<std::unique_ptr<RFieldBase>> &itemFields)
{
std::string result;
for (size_t i = 0; i < itemFields.size(); ++i) {
result += itemFields[i]->GetTypeName() + ",";
}
R__ASSERT(!result.empty()); // there is always at least one variant
result.pop_back(); // remove trailing comma
return result;
}

ROOT::RVariantField::RVariantField(std::string_view name, const RVariantField &source)
: ROOT::RFieldBase(name, source.GetTypeName(), ROOT::ENTupleStructure::kVariant, false /* isSimple */),
fMaxItemSize(source.fMaxItemSize),
Expand All @@ -1387,12 +1416,16 @@ ROOT::RVariantField::RVariantField(std::string_view name, const RVariantField &s
}

ROOT::RVariantField::RVariantField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
: ROOT::RFieldBase(fieldName, "std::variant<" + GetTypeList(itemFields) + ">", ROOT::ENTupleStructure::kVariant,
false /* isSimple */)
: ROOT::RFieldBase(fieldName, "std::variant<" + GetTypeList(itemFields, false /* useTypeAliases */) + ">",
ROOT::ENTupleStructure::kVariant, false /* isSimple */)
{
// The variant needs to initialize its own tag member
fTraits |= kTraitTriviallyDestructible & ~kTraitTriviallyConstructible;

const std::string typeAlias = "std::variant<" + GetTypeList(itemFields, true /* useTypeAliases */) + ">";
if (typeAlias != GetTypeName())
fTypeAlias = typeAlias;

auto nFields = itemFields.size();
if (nFields == 0 || nFields > kMaxVariants) {
throw RException(R__FAIL("invalid number of variant fields (outside [1.." + std::to_string(kMaxVariants) + ")"));
Expand Down
13 changes: 13 additions & 0 deletions tree/ntuple/src/RFieldSequenceContainer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ ROOT::RArrayField::RArrayField(std::string_view fieldName, std::unique_ptr<RFiel
fArrayLength(arrayLength)
{
fTraits |= itemField->GetTraits() & ~kTraitMappable;
if (!itemField->GetTypeAlias().empty()) {
fTypeAlias = "std::array<" + itemField->GetTypeAlias() + "," +
Internal::GetNormalizedInteger(static_cast<unsigned long long>(arrayLength)) + ">";
}
Attach(std::move(itemField));
}

Expand Down Expand Up @@ -245,6 +249,8 @@ ROOT::RRVecField::RRVecField(std::string_view fieldName, std::unique_ptr<RFieldB
{
if (!(itemField->GetTraits() & kTraitTriviallyDestructible))
fItemDeleter = GetDeleterOf(*itemField);
if (!itemField->GetTypeAlias().empty())
fTypeAlias = "ROOT::VecOps::RVec<" + itemField->GetTypeAlias() + ">";
Attach(std::move(itemField));
fValueSize = EvalRVecValueSize(fSubfields[0]->GetAlignment(), fSubfields[0]->GetValueSize(), GetAlignment());

Expand Down Expand Up @@ -549,6 +555,9 @@ ROOT::RVectorField::RVectorField(std::string_view fieldName, std::unique_ptr<RFi
if (emulatedFromType && !emulatedFromType->empty())
fTraits |= kTraitEmulatedField;

if (!itemField->GetTypeAlias().empty())
fTypeAlias = "std::vector<" + itemField->GetTypeAlias() + ">";

if (!(itemField->GetTraits() & kTraitTriviallyDestructible))
fItemDeleter = GetDeleterOf(*itemField);
Attach(std::move(itemField));
Expand Down Expand Up @@ -859,6 +868,8 @@ ROOT::RArrayAsRVecField::RArrayAsRVecField(std::string_view fieldName, std::uniq
fItemSize(itemField->GetValueSize()),
fArrayLength(arrayLength)
{
if (!itemField->GetTypeAlias().empty())
fTypeAlias = "ROOT::VecOps::RVec<" + itemField->GetTypeAlias() + ">";
Attach(std::move(itemField));
fValueSize = EvalRVecValueSize(fSubfields[0]->GetAlignment(), fSubfields[0]->GetValueSize(), GetAlignment());
if (!(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
Expand Down Expand Up @@ -961,6 +972,8 @@ ROOT::RArrayAsVectorField::RArrayAsVectorField(std::string_view fieldName, std::
fItemSize(itemField->GetValueSize()),
fArrayLength(arrayLength)
{
if (!itemField->GetTypeAlias().empty())
fTypeAlias = "std::vector<" + itemField->GetTypeAlias() + ">";
Attach(std::move(itemField));
if (!(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
fItemDeleter = GetDeleterOf(*fSubfields[0]);
Expand Down
Loading
Loading