diff --git a/include/podio/utilities/TypeHelpers.h b/include/podio/utilities/TypeHelpers.h index 2d6371a1a..7c794230c 100644 --- a/include/podio/utilities/TypeHelpers.h +++ b/include/podio/utilities/TypeHelpers.h @@ -233,6 +233,24 @@ namespace detail { */ template using GetDefaultHandleType = typename det::detected_or::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 + using GetMutableHandleType = typename det::detected_or::type; + + /** + * Helper type alias to transform a tuple of handle types to a tuple of + * mutable handle types. + */ + template + using TupleOfMutableTypes = typename ToTupleOfTemplateHelper::type; + } // namespace detail // forward declaration to be able to use it below diff --git a/python/templates/Interface.h.jinja2 b/python/templates/Interface.h.jinja2 index 98527a5e7..cdb87f350 100644 --- a/python/templates/Interface.h.jinja2 +++ b/python/templates/Interface.h.jinja2 @@ -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" @@ -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; + + /// template variable for determining whether type T is a valid interface type + template + constexpr static bool isInterfacedType = podio::detail::isInTuple; + + /// template variable for determining whether type T can be used to initialize + /// this interface + template + constexpr static bool isInitializableFrom = isInterfacedType || podio::detail::isInTuple; + struct Concept { virtual ~Concept() = default; virtual std::unique_ptr clone() const = 0; @@ -65,13 +81,13 @@ class {{ class.bare_type }} { ValueT m_value{}; }; - std::unique_ptr m_self{nullptr}; + std::unique_ptr m_self{nullptr}; public: template {{ class.bare_type }}(ValueT value) : m_self(std::make_unique>>(value)) { - static_assert(podio::detail::isPodioType, "{{ class.bare_type }} can only be initialized with a podio type"); + static_assert(isInitializableFrom, "{{ 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) : @@ -104,6 +120,7 @@ public: /// Check if the object currently holds a value of the requested type template bool isA() const { + static_assert(isInterfacedType, "{{ class.bare_type }} can only ever be one of the following types: {{ Types | join (", ") }}"); return typeid(T) == m_self->typeInfo(); }