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
2 changes: 0 additions & 2 deletions tree/ntuple/inc/ROOT/RFieldBase.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,6 @@ protected:

/// Allow parents to mark their childs as artificial fields (used in class and record fields)
static void CallSetArtificialOn(RFieldBase &other) { other.SetArtificial(); }
/// Allow class fields to adjust the type alias of their members
static void SetTypeAliasOf(RFieldBase &other, const std::string &alias) { other.fTypeAlias = alias; }

/// Operations on values of complex types, e.g. ones that involve multiple columns or for which no direct
/// column type exists.
Expand Down
14 changes: 1 addition & 13 deletions tree/ntuple/src/RFieldMeta.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -226,28 +226,16 @@ ROOT::RClassField::RClassField(std::string_view fieldName, TClass *classp)
// context-dependent types (e.g. typedefs defined in the class itself - which will not be fully qualified in
// the string returned by dataMember->GetFullTypeName())
std::string typeName{dataMember->GetTrueTypeName()};
// RFieldBase::Create() set subField->fTypeAlias based on the assumption that the user specified typeName, which
// already went through one round of type resolution.
std::string origTypeName{dataMember->GetFullTypeName()};

// For C-style arrays, complete the type name with the size for each dimension, e.g. `int[4][2]`
if (dataMember->Property() & kIsArray) {
for (int dim = 0, n = dataMember->GetArrayDim(); dim < n; ++dim) {
const auto addedStr = "[" + std::to_string(dataMember->GetMaxIndex(dim)) + "]";
typeName += addedStr;
origTypeName += addedStr;
typeName += "[" + std::to_string(dataMember->GetMaxIndex(dim)) + "]";
}
}

auto subField = RFieldBase::Create(dataMember->GetName(), typeName).Unwrap();

const auto normTypeName = ROOT::Internal::GetNormalizedUnresolvedTypeName(origTypeName);
if (normTypeName == subField->GetTypeName()) {
SetTypeAliasOf(*subField, "");
} else {
SetTypeAliasOf(*subField, normTypeName);
}

fTraits &= subField->GetTraits();
Attach(std::move(subField), RSubfieldInfo{kDataMember, static_cast<std::size_t>(dataMember->GetOffset())});
}
Expand Down
13 changes: 12 additions & 1 deletion tree/ntuple/test/CustomStruct.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,17 @@ struct CustomAtomicNotLockFree {
};

struct CustomStruct {
template <typename T>
struct VectorWrapper {
std::vector<T> fVec;
};

template <typename T>
using MyVec = std::vector<T>;

template <typename T>
using MyVectorWrapper = VectorWrapper<T>;

float a = 0.0;
std::vector<float> v1;
std::vector<std::vector<float>> v2;
Expand All @@ -72,7 +80,10 @@ struct DerivedA2 : public CustomStruct {
};

struct DerivedWithTypedef : public CustomStruct {
MyVec<int> m;
MyVec<Double32_t> m1;
MyVec<Long64_t> m2;
MyVec<Int_t> m3;
MyVectorWrapper<Long64_t> m4;
};

struct DerivedB : public DerivedA {
Expand Down
1 change: 1 addition & 0 deletions tree/ntuple/test/CustomStructLinkDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#pragma link C++ class CustomAtomicNotLockFree+;

#pragma link C++ class CustomStruct+;
#pragma link C++ class CustomStruct::VectorWrapper<Long64_t>+;
#pragma link C++ class DerivedA+;
#pragma link C++ class DerivedA2+;
#pragma link C++ class DerivedWithTypedef + ;
Expand Down
36 changes: 20 additions & 16 deletions tree/ntuple/test/ntuple_type_name.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,11 @@ TEST(RNTuple, TypeNameTemplatesNestedAlias)
ASSERT_EQ(2, hashSubfields.size());
EXPECT_EQ("fHash", hashSubfields[0]->GetFieldName());
EXPECT_EQ("std::string", hashSubfields[0]->GetTypeName());
EXPECT_EQ("EdmHash<1>::value_type", hashSubfields[0]->GetTypeAlias());
EXPECT_EQ("", hashSubfields[0]->GetTypeAlias());

EXPECT_EQ("fHash2", hashSubfields[1]->GetFieldName());
EXPECT_EQ("std::string", hashSubfields[1]->GetTypeName());
// FIXME: This should really be EdmHash<1>::value_typeT<EdmHash<1>::value_type>, but this is the value we get from
// TDataMember::GetFullTypeName right now...
EXPECT_EQ("value_typeT<EdmHash<1>::value_type>", hashSubfields[1]->GetTypeAlias());
EXPECT_EQ("", hashSubfields[1]->GetTypeAlias());
}

TEST(RNTuple, ContextDependentTypeNames)
Expand All @@ -330,28 +328,34 @@ TEST(RNTuple, ContextDependentTypeNames)
auto model = RNTupleModel::Create();
auto fieldBase = RFieldBase::Create("foo", "DerivedWithTypedef").Unwrap();
model->AddField(std::move(fieldBase));
auto ntuple = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
auto entry = ntuple->GetModel().CreateBareEntry();
auto ptr = std::make_unique<DerivedWithTypedef>();
entry->BindRawPtr("foo", ptr.get());
for (auto i = 0; i < 10; ++i) {
ptr->m.push_back(i);
ntuple->Fill(*entry);
ptr->m.clear();
}
auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
}

{
auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
EXPECT_EQ(reader->GetNEntries(), 10);

const auto &desc = reader->GetDescriptor();
const auto fooId = desc.FindFieldId("foo");
const auto baseId = desc.GetFieldDescriptor(fooId).GetLinkIds()[0];
{
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("m", fooId));
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("m1", fooId));
EXPECT_EQ(fdesc.GetTypeName(), "std::vector<double>");
EXPECT_EQ(fdesc.GetTypeAlias(), "std::vector<Double32_t>");
}
{
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("m2", fooId));
EXPECT_EQ(fdesc.GetTypeName(), "std::vector<std::int64_t>");
EXPECT_EQ(fdesc.GetTypeAlias(), "");
}
{
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("m3", fooId));
EXPECT_EQ(fdesc.GetTypeName(), "std::vector<std::int32_t>");
EXPECT_EQ(fdesc.GetTypeAlias(), "MyVec<std::int32_t>");
EXPECT_EQ(fdesc.GetTypeAlias(), "");
}
{
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("m4", fooId));
EXPECT_EQ(fdesc.GetTypeName(), "CustomStruct::VectorWrapper<std::int64_t>");
EXPECT_EQ(fdesc.GetTypeAlias(), "CustomStruct::VectorWrapper<Long64_t>");
}
{
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("a", baseId));
Expand Down
23 changes: 16 additions & 7 deletions tree/ntuple/test/ntuple_types.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2250,9 +2250,15 @@ TEST(RNTuple, ContextDependentTypes)
auto ptr = std::make_unique<DerivedWithTypedef>();
entry->BindRawPtr("foo", ptr.get());
for (auto i = 0; i < 10; ++i) {
ptr->m.push_back(i);
ptr->m1.push_back(i);
ptr->m2.push_back(i);
ptr->m3.push_back(i);
ptr->m4.fVec.push_back(i);
ntuple->Fill(*entry);
ptr->m.clear();
ptr->m1.clear();
ptr->m2.clear();
ptr->m3.clear();
ptr->m4.fVec.clear();
}
}

Expand All @@ -2263,13 +2269,16 @@ TEST(RNTuple, ContextDependentTypes)
const auto &model = reader->GetModel();
const auto &field = model.GetConstField("foo");
EXPECT_EQ(field.GetTypeName(), "DerivedWithTypedef");
const auto &vec = model.GetConstField("foo.m");
EXPECT_EQ(vec.GetTypeName(), "std::vector<std::int32_t>");
EXPECT_EQ(vec.GetTypeAlias(), "MyVec<std::int32_t>");

auto vecView = reader->GetView<DerivedWithTypedef::MyVec<int>>("foo.m");
auto m1View = reader->GetView<DerivedWithTypedef::MyVec<Double32_t>>("foo.m1");
auto m2View = reader->GetView<DerivedWithTypedef::MyVec<Long64_t>>("foo.m2");
auto m3View = reader->GetView<DerivedWithTypedef::MyVec<Int_t>>("foo.m3");
auto m4View = reader->GetView<DerivedWithTypedef::MyVectorWrapper<Long64_t>>("foo.m4");
for (const auto &i : reader->GetEntryRange()) {
EXPECT_EQ(vecView(i), std::vector{static_cast<int>(i)});
EXPECT_DOUBLE_EQ(m1View(i)[0], std::vector<double>{static_cast<double>(i)}[0]);
EXPECT_EQ(m2View(i), std::vector<Long64_t>{static_cast<Long64_t>(i)});
EXPECT_EQ(m3View(i), std::vector<int>{static_cast<int>(i)});
EXPECT_EQ(m4View(i).fVec, std::vector<Long64_t>{static_cast<Long64_t>(i)});
}
}
}
Loading