Skip to content

Commit

Permalink
Make interfaces only accept interfaced types
Browse files Browse the repository at this point in the history
  • Loading branch information
tmadlener committed Dec 1, 2023
1 parent 4d47ee2 commit 443a654
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
18 changes: 18 additions & 0 deletions include/podio/utilities/TypeHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,24 @@ namespace detail {
*/
template <typename T>
using GetDefaultHandleType = typename det::detected_or<T, hasObject_t, T>::type;

/**
* Variable template for obtaining the mutable handle type from any podio
* generated handle type.
*
* If T is alrady a mutable handle, this will return T, if T is a default
* handle it will return T::mutable_type.
*/
template <typename T>
using GetMutableHandleType = typename det::detected_or<T, hasMutable_t, T>::type;

/**
* Helper type alias to transform a tuple of handle types to a tuple of
* mutable handle types.
*/
template <typename Tuple>
using TupleOfMutableTypes = typename ToTupleOfTemplateHelper<GetMutableHandleType, Tuple>::type;

} // namespace detail

// forward declaration to be able to use it below
Expand Down
25 changes: 21 additions & 4 deletions python/templates/Interface.h.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
#ifndef {{ package_name.upper() }}_{{ class.bare_type }}_H
#define {{ package_name.upper() }}_{{ class.bare_type }}_H

{# We only need one concrete type below for the makeEmpty static initialization. #}
{{ include_types[0] }}
{% for include in include_types %}
{{ include }}
{% endfor %}

#include "podio/ObjectID.h"
#include "podio/utilities/TypeHelpers.h"
Expand All @@ -21,6 +22,21 @@
{{ common_macros.class_description(class.bare_type, Description, Author) }}
class {{ class.bare_type }} {

/// type alias containing all the types this interface should work for.
using InterfacedTypes = std::tuple<{{ Types | join(", ")}}>;
/// type alias containing all the mutable types that can be used to initalize
/// this interface
using InterfacedMutableTypes = podio::detail::TupleOfMutableTypes<InterfacedTypes>;

/// template variable for determining whether type T is a valid interface type
template<typename T>
constexpr static bool isInterfacedType = podio::detail::isInTuple<T, InterfacedTypes>;

/// template variable for determining whether type T can be used to initialize
/// this interface
template<typename T>
constexpr static bool isInitializableFrom = isInterfacedType<T> || podio::detail::isInTuple<T, InterfacedMutableTypes>;

struct Concept {
virtual ~Concept() = default;
virtual std::unique_ptr<Concept> clone() const = 0;
Expand Down Expand Up @@ -65,13 +81,13 @@ class {{ class.bare_type }} {
ValueT m_value{};
};

std::unique_ptr<Concept> m_self{nullptr};
std::unique_ptr<Concept> m_self{nullptr};

public:
template<typename ValueT>
{{ class.bare_type }}(ValueT value) :
m_self(std::make_unique<Model<podio::detail::GetDefaultHandleType<ValueT>>>(value)) {
static_assert(podio::detail::isPodioType<ValueT>, "{{ class.bare_type }} can only be initialized with a podio type");
static_assert(isInitializableFrom<ValueT>, "{{ class.bare_type }} can only be initialized with one of the following types (and their Mutable counter parts): {{ Types | join(", ") }}");
}

{{ class.bare_type }}(const {{ class.bare_type }}& other) :
Expand Down Expand Up @@ -104,6 +120,7 @@ public:
/// Check if the object currently holds a value of the requested type
template<typename T>
bool isA() const {
static_assert(isInterfacedType<T>, "{{ class.bare_type }} can only ever be one of the following types: {{ Types | join (", ") }}");
return typeid(T) == m_self->typeInfo();
}

Expand Down

0 comments on commit 443a654

Please sign in to comment.