From 21d3e4b4cef767460bd9c674e5397a794d35b801 Mon Sep 17 00:00:00 2001 From: Mateusz Jakub Fila <37295697+m-fila@users.noreply.github.com> Date: Mon, 17 Feb 2025 17:34:19 +0100 Subject: [PATCH] fix setting link with interface without specific link direction (#736) * fix setting link with interface without specific link direction * use always_false template to avoid compilation error in `else static_assert(false)` --- include/podio/detail/Link.h | 11 ++++++++++- include/podio/utilities/TypeHelpers.h | 5 +++++ tests/unittests/links.cpp | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/include/podio/detail/Link.h b/include/podio/detail/Link.h index b7f38da73..c9ddd1b38 100644 --- a/include/podio/detail/Link.h +++ b/include/podio/detail/Link.h @@ -5,6 +5,7 @@ #include "podio/detail/LinkObj.h" #include "podio/utilities/MaybeSharedPtr.h" #include "podio/utilities/TypeHelpers.h" +#include #ifdef PODIO_JSON_OUTPUT #include "nlohmann/json.hpp" @@ -262,8 +263,16 @@ class LinkT { void set(T value) { if constexpr (std::is_same_v) { setFrom(std::move(value)); - } else { + } else if constexpr (std::is_same_v) { + setTo(std::move(value)); + } else if constexpr (detail::isInterfaceInitializableFrom && + !detail::isInterfaceInitializableFrom) { + setFrom(std::move(value)); + } else if constexpr (detail::isInterfaceInitializableFrom && + !detail::isInterfaceInitializableFrom) { setTo(std::move(value)); + } else { + static_assert(detail::always_false, "Argument type is ambiguous, can't determine link direction"); } } diff --git a/include/podio/utilities/TypeHelpers.h b/include/podio/utilities/TypeHelpers.h index d774644d7..b2a568f13 100644 --- a/include/podio/utilities/TypeHelpers.h +++ b/include/podio/utilities/TypeHelpers.h @@ -40,6 +40,11 @@ namespace det { namespace detail { + // A helper variable template that is always false, used for static_asserts + // and other compile-time checks that should always fail. + template + inline constexpr bool always_false = false; + /// Helper struct to determine whether a given type T is in a tuple of types /// that act as a type list in this case template diff --git a/tests/unittests/links.cpp b/tests/unittests/links.cpp index 0bb939731..eba6bd5da 100644 --- a/tests/unittests/links.cpp +++ b/tests/unittests/links.cpp @@ -460,6 +460,21 @@ TEST_CASE("Links with interfaces", "[links][interface-types]") { link.set(hit); REQUIRE(link.get() == hit); REQUIRE(link.get() == cluster); + + // Check determining `set` direction for a link going in a reverse direction + using ReverseInterfaceLinkCollection = + podio::LinkCollection; + auto rColl = ReverseInterfaceLinkCollection{}; + auto rLink = rColl.create(); + + rLink.set(cluster); + rLink.set(iface); + REQUIRE(rLink.get() == iface); + REQUIRE(rLink.get() == cluster); + + rLink.set(hit); + REQUIRE(rLink.get() == hit); + REQUIRE(rLink.get() == cluster); } #ifdef PODIO_JSON_OUTPUT