diff --git a/k4FWCore/components/CollectionMerger.cpp b/k4FWCore/components/CollectionMerger.cpp index af4da585..89845de2 100644 --- a/k4FWCore/components/CollectionMerger.cpp +++ b/k4FWCore/components/CollectionMerger.cpp @@ -38,12 +38,11 @@ #include "k4FWCore/Transformer.h" #include -#include #include #include -struct CollectionMerger final : k4FWCore::Transformer( - const std::vector*>&)> { +struct CollectionMerger final + : k4FWCore::Transformer&)> { CollectionMerger(const std::string& name, ISvcLocator* svcLoc) : Transformer(name, svcLoc, {KeyValues("InputCollections", {"MCParticles"})}, {KeyValues("OutputCollection", {"NewMCParticles"})}) { @@ -91,43 +90,38 @@ struct CollectionMerger final : k4FWCore::Transformer; } - std::shared_ptr operator()( - const std::vector*>& input) const override { - std::shared_ptr ret; + podio::CollectionBase* operator()(const std::vector& input) const override { + podio::CollectionBase* ret = nullptr; debug() << "Merging " << input.size() << " collections" << endmsg; std::string_view type = ""; for (const auto& coll : input) { - debug() << "Merging collection of type " << (*coll)->getTypeName() << " with " << (*coll)->size() << " elements" + debug() << "Merging collection of type " << coll->getTypeName() << " with " << coll->size() << " elements" << endmsg; if (type.empty()) { - type = (*coll)->getTypeName(); - } else if (type != (*coll)->getTypeName()) { + type = coll->getTypeName(); + } else if (type != coll->getTypeName()) { throw std::runtime_error("Different collection types are not supported"); - return ret; } - (this->*m_map.at((*coll)->getTypeName()))(*coll, ret); + (this->*m_map.at(coll->getTypeName()))(coll, ret); } return ret; } private: - using MergeType = void (CollectionMerger::*)(const std::shared_ptr&, - std::shared_ptr&) const; + using MergeType = void (CollectionMerger::*)(const podio::CollectionBase*, podio::CollectionBase*&) const; std::map m_map; Gaudi::Property m_copy{this, "Copy", false, "Copy the elements of the collections instead of creating a subset collection"}; - template - void mergeCollections(const std::shared_ptr& source, - std::shared_ptr& ret) const { + template void mergeCollections(const podio::CollectionBase* source, podio::CollectionBase*& ret) const { if (!ret) { - ret = std::make_shared(); + ret = new T(); if (!m_copy) { ret->setSubsetCollection(); } } - const auto ptr = std::static_pointer_cast(ret); - const auto sourceColl = std::static_pointer_cast(source); + const auto ptr = static_cast(ret); + const auto sourceColl = static_cast(source); if (m_copy) { for (const auto& elem : *sourceColl) { ptr->push_back(elem.clone()); diff --git a/k4FWCore/components/IIOSvc.h b/k4FWCore/components/IIOSvc.h index 288164ef..61821294 100644 --- a/k4FWCore/components/IIOSvc.h +++ b/k4FWCore/components/IIOSvc.h @@ -39,9 +39,8 @@ class IIOSvc : virtual public IInterface { * @brief Read the next event from the input file * @return A tuple containing the collections read, the collection names and the frame that owns the collections */ - virtual std::tuple>, std::vector, podio::Frame> - next() = 0; - virtual std::shared_ptr> getCollectionNames() const = 0; + virtual std::tuple, std::vector, podio::Frame> next() = 0; + virtual std::shared_ptr> getCollectionNames() const = 0; virtual podio::Writer& getWriter() = 0; virtual void deleteWriter() = 0; diff --git a/k4FWCore/components/IOSvc.cpp b/k4FWCore/components/IOSvc.cpp index ec7f7acf..da1e725f 100644 --- a/k4FWCore/components/IOSvc.cpp +++ b/k4FWCore/components/IOSvc.cpp @@ -109,15 +109,14 @@ StatusCode IOSvc::initialize() { StatusCode IOSvc::finalize() { return Service::finalize(); } -std::tuple>, std::vector, podio::Frame> IOSvc::next() { +std::tuple, std::vector, podio::Frame> IOSvc::next() { podio::Frame frame; { - std::scoped_lock lock(m_changeBufferLock); + std::lock_guard lock(m_changeBufferLock); if (m_nextEntry < m_entries) { frame = podio::Frame(m_reader->readEvent(m_nextEntry)); } else { - return std::make_tuple(std::vector>(), std::vector(), - std::move(frame)); + return std::make_tuple(std::vector(), std::vector(), std::move(frame)); } m_nextEntry++; if (m_collectionNames.empty()) { @@ -134,11 +133,11 @@ std::tuple>, std::vector> collections; + std::vector collections; for (const auto& name : m_collectionNames) { auto ptr = const_cast(frame.get(name)); - collections.push_back(std::shared_ptr(ptr)); + collections.push_back(ptr); } return std::make_tuple(collections, m_collectionNames, std::move(frame)); @@ -178,7 +177,10 @@ void IOSvc::handle(const Incident& incident) { code = m_dataSvc->retrieveObject("/Event/" + coll, collPtr); if (code.isSuccess()) { debug() << "Removing the collection: " << coll << " from the store" << endmsg; - code = m_dataSvc->unregisterObject(collPtr); + code = m_dataSvc->unregisterObject(collPtr); + auto storePtr = dynamic_cast>*>(collPtr); + storePtr->getData().release(); + delete storePtr; } else { error() << "Expected collection " << coll << " in the store but it was not found" << endmsg; } diff --git a/k4FWCore/components/IOSvc.h b/k4FWCore/components/IOSvc.h index 2d1957d3..d392352c 100644 --- a/k4FWCore/components/IOSvc.h +++ b/k4FWCore/components/IOSvc.h @@ -43,8 +43,7 @@ class IOSvc : public extends { StatusCode initialize() override; StatusCode finalize() override; - std::tuple>, std::vector, podio::Frame> next() - override; + std::tuple, std::vector, podio::Frame> next() override; std::shared_ptr> getCollectionNames() const override { return std::make_shared>(m_collectionNames); diff --git a/k4FWCore/components/Reader.cpp b/k4FWCore/components/Reader.cpp index 6e5511a6..f78628ca 100644 --- a/k4FWCore/components/Reader.cpp +++ b/k4FWCore/components/Reader.cpp @@ -16,12 +16,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include #include "Gaudi/Functional/details.h" #include "Gaudi/Functional/utilities.h" #include "GaudiKernel/AnyDataWrapper.h" #include "GaudiKernel/FunctionalFilterDecision.h" #include "GaudiKernel/IDataProviderSvc.h" +#include "GaudiKernel/SmartIF.h" #include "GaudiKernel/StatusCode.h" #include "podio/CollectionBase.h" @@ -32,18 +32,16 @@ #include -template using vector_of_ = std::vector; - class CollectionPusher : public Gaudi::Functional::details::BaseClass_t { using Traits_ = Gaudi::Functional::Traits::useDefaults; - using Out = std::shared_ptr; + using Out = std::unique_ptr; using base_class = Gaudi::Functional::details::BaseClass_t; static_assert(std::is_base_of_v, "BaseClass must inherit from Algorithm"); template using OutputHandle_t = Gaudi::Functional::details::OutputHandle_t>; - std::vector>> m_outputs; - Gaudi::Property> m_inputCollections{ + std::vector> m_outputs; + Gaudi::Property> m_inputCollections{ this, "InputCollections", {"First collection"}, "List of input collections"}; // Gaudi::Property m_input{this, "Input", "Event", "Input file"}; @@ -73,7 +71,7 @@ class CollectionPusher : public Gaudi::Functional::details::BaseClass_t>>(out); + auto outColls = std::get>(out); auto outputLocations = std::get>(out); // if (out.size() != m_outputs.size()) { @@ -82,7 +80,7 @@ class CollectionPusher : public Gaudi::Functional::details::BaseClass_tname(), StatusCode::FAILURE); // } for (size_t i = 0; i != outColls.size(); ++i) { - m_outputs[i].put(std::move(outColls[i])); + m_outputs[i].put(std::unique_ptr(outColls[i])); } return Gaudi::Functional::FilterDecision::PASSED; } catch (GaudiException& e) { @@ -91,7 +89,7 @@ class CollectionPusher : public Gaudi::Functional::details::BaseClass_t, std::vector> operator()() const = 0; + virtual std::tuple, std::vector> operator()() const = 0; private: ServiceHandle m_dataSvc{this, "EventDataSvc", "EventDataSvc"}; @@ -108,7 +106,7 @@ class Reader final : public CollectionPusher { // Gaudi doesn't run the destructor of the Services so we have to // manually ask for the reader to be deleted so it will call finish() // See https://gitlab.cern.ch/gaudi/Gaudi/-/issues/169 - ~Reader() { iosvc->deleteReader(); } + ~Reader() override { iosvc->deleteReader(); } ServiceHandle iosvc{this, "IOSvc", "IOSvc"}; @@ -131,8 +129,7 @@ class Reader final : public CollectionPusher { // The IOSvc takes care of reading and passing the data // By convention the Frame is pushed to the store // so that it's deleted at the right time - std::tuple>, std::vector> operator()() - const override { + std::tuple, std::vector> operator()() const override { auto val = iosvc->next(); auto eds = eventSvc().as(); diff --git a/k4FWCore/components/Writer.cpp b/k4FWCore/components/Writer.cpp index 25c9874c..1e276c96 100644 --- a/k4FWCore/components/Writer.cpp +++ b/k4FWCore/components/Writer.cpp @@ -23,7 +23,6 @@ #include "GaudiKernel/IDataProviderSvc.h" #include "GaudiKernel/SmartDataPtr.h" #include "GaudiKernel/StatusCode.h" - #include "podio/Frame.h" #include "IIOSvc.h" @@ -185,18 +184,22 @@ class Writer final : public Gaudi::Functional::ConsumerretrieveObject("/Event" + k4FWCore::frameLocation, p); - AnyDataWrapper* ptr; + DataObject* p; + StatusCode code = m_dataSvc->retrieveObject("/Event" + k4FWCore::frameLocation, p); + std::unique_ptr> ptr; // This is the case when we are reading from a file + // Putting it into a unique_ptr will make sure it's deleted if (code.isSuccess()) { - m_dataSvc->unregisterObject(p).ignore(); - ptr = dynamic_cast*>(p); + auto sc = m_dataSvc->unregisterObject(p); + if (!sc.isSuccess()) { + error() << "Failed to unregister object" << endmsg; + return; + } + ptr = std::unique_ptr>(dynamic_cast*>(p)); } // This is the case when no reading is being done - // Will be deleted by the store else { - ptr = new AnyDataWrapper(podio::Frame()); + ptr = std::make_unique>(podio::Frame()); } const auto& frameCollections = ptr->getData().getAvailableCollections(); @@ -229,6 +232,10 @@ class Writer final : public Gaudi::Functional::Consumer>*>(storeCollection); + storePtr->getData().release(); + delete storePtr; } for (auto& coll : m_collectionsToAdd) { @@ -242,8 +249,11 @@ class Writer final : public Gaudi::Functional::Consumer>*>(storeCollection); - if (!collection) { + const auto collection = dynamic_cast>*>(storeCollection); + if (collection) { + ptr->getData().put(std::move(collection->getData()), coll); + delete collection; + } else { // Check the case when the data has been produced using the old DataHandle const auto old_collection = dynamic_cast(storeCollection); if (!old_collection) { @@ -254,10 +264,6 @@ class Writer final : public Gaudi::Functional::Consumer(old_collection->collectionBase())); ptr->getData().put(std::move(uptr), coll); } - - } else { - std::unique_ptr uptr(collection->getData().get()); - ptr->getData().put(std::move(uptr), coll); } } diff --git a/k4FWCore/include/k4FWCore/Consumer.h b/k4FWCore/include/k4FWCore/Consumer.h index 8077645e..9b08a4ae 100644 --- a/k4FWCore/include/k4FWCore/Consumer.h +++ b/k4FWCore/include/k4FWCore/Consumer.h @@ -19,9 +19,9 @@ #ifndef FWCORE_CONSUMER_H #define FWCORE_CONSUMER_H -#include #include "Gaudi/Functional/details.h" #include "Gaudi/Functional/utilities.h" +#include "GaudiKernel/FunctionalFilterDecision.h" // #include "GaudiKernel/CommonMessaging.h" @@ -46,11 +46,10 @@ namespace k4FWCore { static_assert(((std::is_base_of_v || isVectorLike_v)&&...), "Consumer input types must be EDM4hep collections or vectors of collection pointers"); - template - using InputHandle_t = Gaudi::Functional::details::InputHandle_t>; + template using InputHandle_t = Gaudi::Functional::details::InputHandle_t; - std::tuple::type>>...> m_inputs; - std::array>, sizeof...(In)> m_inputLocations{}; + std::tuple::type>>...> m_inputs; + std::array>, sizeof...(In)> m_inputLocations{}; using base_class = Gaudi::Functional::details::DataHandleMixin, std::tuple<>, Traits_>; @@ -66,9 +65,9 @@ namespace k4FWCore { m_inputLocations{Gaudi::Property>{ this, std::get(inputs).first, to_DataObjID(std::get(inputs).second), [this](Gaudi::Details::PropertyBase&) { - std::vector::type>> handles; + std::vector> handles; for (auto& value : this->m_inputLocations[I].value()) { - auto handle = InputHandle_t::type>(value, this); + auto handle = InputHandle_t(value, this); handles.push_back(std::move(handle)); } std::get(m_inputs) = std::move(handles); diff --git a/k4FWCore/include/k4FWCore/DataHandle.h b/k4FWCore/include/k4FWCore/DataHandle.h index 8d5e8689..92b48c4f 100644 --- a/k4FWCore/include/k4FWCore/DataHandle.h +++ b/k4FWCore/include/k4FWCore/DataHandle.h @@ -27,8 +27,6 @@ #include "edm4hep/Constants.h" -#include "TTree.h" - #include #include @@ -133,9 +131,9 @@ template const T* DataHandle::get() { return reinterpret_cast(tmp->collectionBase()); } else { // When a functional has pushed a std::shared_ptr into the store - auto ptr = static_cast>*>(dataObjectp)->getData(); + auto ptr = static_cast>*>(dataObjectp); if (ptr) { - return reinterpret_cast(ptr.get()); + return static_cast(ptr->getData().get()); } std::string errorMsg("The type provided for " + DataObjectHandle>::pythonRepr() + " is different from the one of the object in the store."); diff --git a/k4FWCore/include/k4FWCore/DataWrapper.h b/k4FWCore/include/k4FWCore/DataWrapper.h index 5bfc22f9..59511bc3 100644 --- a/k4FWCore/include/k4FWCore/DataWrapper.h +++ b/k4FWCore/include/k4FWCore/DataWrapper.h @@ -41,7 +41,7 @@ template class GAUDI_API DataWrapper : public DataWrapperBase { template friend class DataHandle; public: - DataWrapper() : m_data(nullptr){}; + DataWrapper() : m_data(nullptr) {} DataWrapper(T&& coll) { m_data = new T(std::move(coll)); is_owner = true; @@ -49,7 +49,7 @@ template class GAUDI_API DataWrapper : public DataWrapperBase { DataWrapper(std::unique_ptr uptr) : m_data(uptr.get()) { uptr.release(); is_owner = false; - }; + } virtual ~DataWrapper(); const T* getData() const { return m_data; } diff --git a/k4FWCore/include/k4FWCore/FunctionalUtils.h b/k4FWCore/include/k4FWCore/FunctionalUtils.h index 003aad28..0347f83b 100644 --- a/k4FWCore/include/k4FWCore/FunctionalUtils.h +++ b/k4FWCore/include/k4FWCore/FunctionalUtils.h @@ -19,17 +19,18 @@ #ifndef FWCORE_FUNCTIONALUTILS_H #define FWCORE_FUNCTIONALUTILS_H -#include -#include #include "Gaudi/Functional/details.h" +#include "GaudiKernel/AnyDataWrapper.h" #include "GaudiKernel/DataObjID.h" -#include "k4FWCore/DataWrapper.h" -#include "podio/CollectionBase.h" - #include "GaudiKernel/DataObjectHandle.h" #include "GaudiKernel/EventContext.h" +#include "GaudiKernel/IDataProviderSvc.h" #include "GaudiKernel/ThreadLocalContext.h" +#include "podio/CollectionBase.h" + +#include "k4FWCore/DataWrapper.h" + // #include "GaudiKernel/CommonMessaging.h" #include @@ -42,38 +43,36 @@ namespace k4FWCore { namespace details { - // This function will be used to modify std::shared_ptr to the actual collection type - template - requires std::same_as>> - auto maybeTransformToEDM4hep(P& arg) { - return arg; - } + // It doesn't need to be a template but this allows parameter pack expansion + template struct EventStoreType { + using type = std::unique_ptr; + }; + using EventStoreType_t = typename EventStoreType::type; + // This is used when there is an arbitrary number of collections as input/output template - requires(!std::is_same_v>) + requires(!std::is_same_v) const auto& maybeTransformToEDM4hep(const P& arg) { return arg; } + // This is used by the FilterPredicate template - requires std::is_base_of_v - const auto& maybeTransformToEDM4hep(P* arg) { - return *arg; + requires std::same_as + const auto& maybeTransformToEDM4hep(P&& arg) { + return static_cast(*arg); } + // This is used in all the remaining cases template - requires std::same_as> - const auto& maybeTransformToEDM4hep(P arg) { - return static_cast(*arg); + requires(std::is_base_of_v && !std::same_as) + const auto& maybeTransformToEDM4hep(P* arg) { + return *arg; } template > using addPtrIfColl = std::conditional_t, T>; - template const auto& transformtoEDM4hep(const std::shared_ptr& arg) { - return static_cast(*arg); - } - // Check if the type is a vector like type, where vector is the special // type to have an arbitrary number of collections as input or output: // std::vector where Coll is the collection type for output @@ -82,7 +81,7 @@ namespace k4FWCore { template requires std::is_base_of_v> || - std::is_same_v, std::remove_cvref_t> + std::is_same_v> struct isVectorLike> : std::true_type {}; template @@ -91,28 +90,16 @@ namespace k4FWCore { template inline constexpr bool isVectorLike_v = isVectorLike::value; - // transformType function to transform the types from the ones that the user wants - // like edm4hep::MCParticleCollection, to the ones that are actually stored in the - // event store, like std::shared_ptr - // For std::map, th - template struct transformType { - using type = T; - }; - - template - requires std::is_base_of_v || isVectorLike_v - struct transformType { - using type = std::shared_ptr; - }; - - template auto convertToSharedPtr(T&& arg) { - return std::shared_ptr(std::make_shared(std::move(arg))); - } - - template - requires std::is_same_v> - auto convertToSharedPtr(T&& arg) { - return std::move(arg); + template auto convertToUniquePtr(T&& arg) { + // This is the case for CollectionMerger.cpp, where a raw pointer is + // returned from the algorithm + if constexpr (std::same_as) { + return std::unique_ptr(std::forward(arg)); + } else { + // Most common case, when an algorithm returns a collection and + // we want to store a unique_ptr + return std::make_unique(std::forward(arg)); + } } template struct filter_evtcontext_tt { @@ -146,18 +133,18 @@ namespace k4FWCore { std::remove_pointer_t>::value_type>; auto inputMap = std::vector(); for (auto& handle : std::get(handles)) { - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v) { inputMap.push_back(&get(handle, thisClass, Gaudi::Hive::currentContext())); } else { - auto in = get(handle, thisClass, Gaudi::Hive::currentContext()); - inputMap.push_back(static_cast(in.get())); + podio::CollectionBase* in = handle.get()->get(); + inputMap.push_back(static_cast(in)); } } std::get(inputTuple) = std::move(inputMap); } else { try { - auto in = get(std::get(handles)[0], thisClass, Gaudi::Hive::currentContext()); - std::get(inputTuple) = static_cast>*>(in.get()); + podio::CollectionBase* in = std::get(handles)[0].get()->get(); + std::get(inputTuple) = static_cast>*>(in); } catch (GaudiException& e) { // When the type of the collection is different from the one requested, this can happen because // 1. a mistake was made in the input types of a functional algorithm @@ -201,12 +188,12 @@ namespace k4FWCore { throw GaudiException(thisClass->name(), msg, StatusCode::FAILURE); } for (auto& val : std::get(handles)) { - Gaudi::Functional::details::put(std::get(m_outputs)[i], convertToSharedPtr(std::move(val))); + Gaudi::Functional::details::put(std::get(m_outputs)[i], convertToUniquePtr(std::move(val))); i++; } } else { Gaudi::Functional::details::put(std::get(m_outputs)[0], - convertToSharedPtr(std::move(std::get(handles)))); + convertToUniquePtr(std::move(std::get(handles)))); } // Recursive call for the next index @@ -222,6 +209,8 @@ namespace k4FWCore { } // Functional handles + // This is currently used so that the FilterPredicate can be used together with the + // consumer/producer/transformer template class FunctionalDataObjectReadHandle : public ::details::ReadHandle { template FunctionalDataObjectReadHandle(std::tuple&& args, std::index_sequence) @@ -248,8 +237,8 @@ namespace k4FWCore { throw GaudiException("Cannot retrieve \'" + this->objKey() + "\' from transient store.", this->m_owner ? this->owner()->name() : "no owner", StatusCode::FAILURE); } - auto ptr = dynamic_cast>*>(dataObj); - return maybeTransformToEDM4hep(ptr->getData()); + auto ptr = dynamic_cast>*>(dataObj); + return maybeTransformToEDM4hep(ptr->getData().get()); } struct BaseClass_t { diff --git a/k4FWCore/include/k4FWCore/Transformer.h b/k4FWCore/include/k4FWCore/Transformer.h index 696c8f58..bc61793b 100644 --- a/k4FWCore/include/k4FWCore/Transformer.h +++ b/k4FWCore/include/k4FWCore/Transformer.h @@ -46,7 +46,7 @@ namespace k4FWCore { static_assert(((std::is_base_of_v || isVectorLike_v)&&...), "Transformer and Producer input types must be EDM4hep collections or vectors of collections"); static_assert((std::is_base_of_v || isVectorLike_v || - std::is_same_v, Out>), + std::is_same_v), "Transformer and Producer output types must be EDM4hep collections or vectors of collections"); template @@ -54,10 +54,10 @@ namespace k4FWCore { template using OutputHandle_t = Gaudi::Functional::details::OutputHandle_t>; - std::tuple::type>>...> m_inputs; - std::tuple::type>>> m_outputs; - std::array>, sizeof...(In)> m_inputLocations{}; - Gaudi::Property> m_outputLocations{}; + std::tuple::type>>...> m_inputs; + std::tuple::type>>> m_outputs; + std::array>, sizeof...(In)> m_inputLocations{}; + Gaudi::Property> m_outputLocations{}; using base_class = Gaudi::Functional::details::DataHandleMixin, std::tuple<>, Traits_>; @@ -75,9 +75,9 @@ namespace k4FWCore { m_inputLocations{Gaudi::Property>{ this, std::get(inputs).first, to_DataObjID(std::get(inputs).second), [this](Gaudi::Details::PropertyBase&) { - std::vector::type>> h; + std::vector::type>> h; for (auto& value : this->m_inputLocations[I].value()) { - auto handle = InputHandle_t::type>(value, this); + auto handle = InputHandle_t::type>(value, this); h.push_back(std::move(handle)); } std::get(m_inputs) = std::move(h); @@ -87,12 +87,12 @@ namespace k4FWCore { m_outputLocations{Gaudi::Property>{ this, std::get(outputs).first, to_DataObjID(std::get(outputs).second), [this](Gaudi::Details::PropertyBase&) { - std::vector::type>> h; + std::vector::type>> h; for (auto& inpID : this->m_outputLocations.value()) { if (inpID.key().empty()) { continue; } - auto handle = OutputHandle_t::type>(inpID, this); + auto handle = OutputHandle_t::type>(inpID, this); h.push_back(std::move(handle)); } std::get<0>(m_outputs) = std::move(h); @@ -117,7 +117,7 @@ namespace k4FWCore { } else { Gaudi::Functional::details::put( std::get<0>(this->m_outputs)[0], - convertToSharedPtr(std::move(filter_evtcontext_tt::apply(*this, ctx, this->m_inputs)))); + convertToUniquePtr(std::move(filter_evtcontext_tt::apply(*this, ctx, this->m_inputs)))); } return Gaudi::Functional::FilterDecision::PASSED; } catch (GaudiException& e) { @@ -192,10 +192,10 @@ namespace k4FWCore { template using OutputHandle_t = Gaudi::Functional::details::OutputHandle_t>; - std::tuple::type>>...> m_inputs; - std::tuple::type>>...> m_outputs; - std::array>, sizeof...(In)> m_inputLocations{}; - std::array>, sizeof...(Out)> m_outputLocations{}; + std::tuple::type>>...> m_inputs; + std::tuple::type>>...> m_outputs; + std::array>, sizeof...(In)> m_inputLocations{}; + std::array>, sizeof...(Out)> m_outputLocations{}; using base_class = Gaudi::Functional::details::DataHandleMixin, std::tuple<>, Traits_>; @@ -208,9 +208,9 @@ namespace k4FWCore { m_inputLocations{Gaudi::Property>{ this, std::get(inputs).first, to_DataObjID(std::get(inputs).second), [this](Gaudi::Details::PropertyBase&) { - std::vector::type>> h; + std::vector::type>> h; for (auto& value : this->m_inputLocations[I].value()) { - auto handle = InputHandle_t::type>(value, this); + auto handle = InputHandle_t::type>(value, this); h.push_back(std::move(handle)); } std::get(m_inputs) = std::move(h); @@ -219,7 +219,7 @@ namespace k4FWCore { m_outputLocations{Gaudi::Property>{ this, std::get(outputs).first, to_DataObjID(std::get(outputs).second), [this](Gaudi::Details::PropertyBase&) { - std::vector::type>> h; + std::vector::type>> h; // Is this needed? // std::sort(this->m_outputLocations[J].value().begin(), this->m_outputLocations[J].value().end(), // [](const DataObjID& a, const DataObjID& b) { return a.key() < b.key(); }); @@ -227,7 +227,7 @@ namespace k4FWCore { if (inpID.key().empty()) { continue; } - auto handle = OutputHandle_t::type>(inpID, this); + auto handle = OutputHandle_t::type>(inpID, this); h.push_back(std::move(handle)); } std::get(m_outputs) = std::move(h);