Skip to content
Merged
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
18 changes: 18 additions & 0 deletions Core/include/Acts/EventData/SourceLink.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,24 @@ class SourceLink final {
return m_upstream.as<T>();
}

/// Concrete source link pointer getter
/// @tparam T The source link type to retrieve
/// @return Pointer to the stored source link, or nullptr if the type
/// doesn't match or the SourceLink is empty
template <typename T>
T* getPtr() {
return m_upstream.asPtr<T>();
}

/// Concrete source link pointer getter, const version
/// @tparam T The source link type to retrieve
/// @return Const pointer to the stored source link, or nullptr if the type
/// doesn't match or the SourceLink is empty
template <typename T>
const T* getPtr() const {
return m_upstream.asPtr<T>();
}

private:
any_type m_upstream{};
};
Expand Down
28 changes: 28 additions & 0 deletions Core/include/Acts/Utilities/Any.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,34 @@ class AnyBase : public AnyBaseAll {
return *std::bit_cast<const T*>(dataPtr());
}

/// Get pointer to stored value of specified type
/// @tparam T Type to retrieve (must be exact type, no const/ref)
/// @return Pointer to the stored value, or nullptr if the type doesn't match
/// or the Any is empty
template <typename T>
T* asPtr() {
static_assert(std::is_same_v<T, std::decay_t<T>>,
"Please pass the raw type, no const or ref");
if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
return nullptr;
}
return std::bit_cast<T*>(dataPtr());
}

/// Get const pointer to stored value of specified type
/// @tparam T Type to retrieve (must be exact type, no const/ref)
/// @return Const pointer to the stored value, or nullptr if the type doesn't
/// match or the Any is empty
template <typename T>
const T* asPtr() const {
static_assert(std::is_same_v<T, std::decay_t<T>>,
"Please pass the raw type, no const or ref");
if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
return nullptr;
}
return std::bit_cast<const T*>(dataPtr());
}
Comment thread
paulgessinger marked this conversation as resolved.

~AnyBase() { destroy(); }

/// Copy constructor
Expand Down
39 changes: 39 additions & 0 deletions Tests/UnitTests/Core/EventData/SourceLinkTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,45 @@ BOOST_AUTO_TEST_CASE(Construct) {
}
}

BOOST_AUTO_TEST_CASE(GetPtr) {
{
// correct type returns non-null pointer
MySourceLink msl;
msl.m_geometryId = GeometryIdentifier().withSensitive(7);
SourceLink sl{msl};

auto* p = sl.getPtr<MySourceLink>();
BOOST_REQUIRE_NE(p, static_cast<MySourceLink*>(nullptr));
BOOST_CHECK_EQUAL(p->geometryId(), msl.geometryId());

// wrong type returns nullptr
BOOST_CHECK_EQUAL(sl.getPtr<int>(), static_cast<int*>(nullptr));
BOOST_CHECK_EQUAL(sl.getPtr<double>(), static_cast<double*>(nullptr));
}

{
// const overload
int value = 42;
const SourceLink sl{value};

const int* p = sl.getPtr<int>();
BOOST_REQUIRE_NE(p, static_cast<const int*>(nullptr));
BOOST_CHECK_EQUAL(*p, 42);

BOOST_CHECK_EQUAL(sl.getPtr<float>(), static_cast<const float*>(nullptr));
}

{
// mutation through pointer
int value = 10;
SourceLink sl{value};
int* p = sl.getPtr<int>();
BOOST_REQUIRE_NE(p, static_cast<int*>(nullptr));
*p = 99;
BOOST_CHECK_EQUAL(sl.get<int>(), 99);
}
}

BOOST_AUTO_TEST_CASE(Reassign) {
int value = 5;
SourceLink sl{value};
Expand Down
73 changes: 73 additions & 0 deletions Tests/UnitTests/Core/Utilities/AnyTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,79 @@ BOOST_AUTO_TEST_CASE(AnyConstructPrimitive) {
CHECK_ANY_ALLOCATIONS();
}

BOOST_AUTO_TEST_CASE(AnyAsPtr) {
{
// small type: correct type returns non-null pointer
Any a{42};
int* p = a.asPtr<int>();
BOOST_REQUIRE_NE(p, static_cast<int*>(nullptr));
BOOST_CHECK_EQUAL(*p, 42);

// wrong type returns nullptr
BOOST_CHECK_EQUAL(a.asPtr<float>(), static_cast<float*>(nullptr));
BOOST_CHECK_EQUAL(a.asPtr<double>(), static_cast<double*>(nullptr));

// mutation through pointer
*p = 99;
BOOST_CHECK_EQUAL(a.as<int>(), 99);
}
CHECK_ANY_ALLOCATIONS();

{
// large (heap-allocated) type: correct type returns non-null pointer
std::array<unsigned long, 5> v{10, 20, 30, 40, 50};
Any a{v};
auto* p = a.asPtr<std::array<unsigned long, 5>>();
BOOST_REQUIRE_NE(p, static_cast<decltype(p)>(nullptr));
BOOST_CHECK_EQUAL_COLLECTIONS(p->begin(), p->end(), v.begin(), v.end());

// wrong type returns nullptr
BOOST_CHECK_EQUAL(a.asPtr<int>(), static_cast<int*>(nullptr));
}
CHECK_ANY_ALLOCATIONS();

{
// empty Any returns nullptr
Any a;
BOOST_CHECK_EQUAL(a.asPtr<int>(), static_cast<int*>(nullptr));
BOOST_CHECK_EQUAL(a.asPtr<float>(), static_cast<float*>(nullptr));
}
CHECK_ANY_ALLOCATIONS();

{
// const overload
const Any a{3.14f};
const float* p = a.asPtr<float>();
BOOST_REQUIRE_NE(p, static_cast<const float*>(nullptr));
BOOST_CHECK_EQUAL(*p, 3.14f);

// wrong type on const Any
BOOST_CHECK_EQUAL(a.asPtr<int>(), static_cast<const int*>(nullptr));
}
CHECK_ANY_ALLOCATIONS();

{
// const overload with empty Any
const Any a;
BOOST_CHECK_EQUAL(a.asPtr<int>(), static_cast<const int*>(nullptr));
}
CHECK_ANY_ALLOCATIONS();

{
// const overload with heap-allocated type
std::array<int, 64> v{};
v.fill(7);
const Any a{v};
const auto* p = a.asPtr<std::array<int, 64>>();
BOOST_REQUIRE_NE(p, static_cast<decltype(p)>(nullptr));
for (const auto& elem : *p) {
BOOST_CHECK_EQUAL(elem, 7);
}
BOOST_CHECK_EQUAL(a.asPtr<float>(), static_cast<const float*>(nullptr));
}
CHECK_ANY_ALLOCATIONS();
}

BOOST_AUTO_TEST_CASE(AnyAssignConstructEmpty) {
Any a;
Any b;
Expand Down
Loading