From 739114044fda4a50fc5054e50803fe6f60efe29c Mon Sep 17 00:00:00 2001 From: Gerhard Raven Date: Mon, 30 Aug 2021 16:43:18 +0200 Subject: [PATCH] Make Gaudi::Functional constructors more paranoid about # of inputs/outputs Currenly, the constructors of the Gaudi::Functional baseclasses use `std::array` as arguments where N is the number of inputs or outputs specified. However, this implies that one can specify a list of less than N KeyValues, as `std::array` will happily default-initialize any missing items. This will then result in an error in genConf, as this implies a property with a default-initialized string (i.e. an empty string) as key. This can be fixed by replacing the `std::array` with a tuple with N `KeyValues, eg. for N=2 an `st::tuple`. --- GaudiAlg/include/GaudiAlg/FunctionalDetails.h | 40 +++++++++++++------ .../include/GaudiAlg/MergingTransformer.h | 4 +- .../include/GaudiAlg/SplittingTransformer.h | 8 ++-- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/GaudiAlg/include/GaudiAlg/FunctionalDetails.h b/GaudiAlg/include/GaudiAlg/FunctionalDetails.h index c8ee0728b..ef11ac79e 100644 --- a/GaudiAlg/include/GaudiAlg/FunctionalDetails.h +++ b/GaudiAlg/include/GaudiAlg/FunctionalDetails.h @@ -44,6 +44,10 @@ namespace ranges::views { # define GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END #endif +// temporary hack to help in transition to updated constructor +// allows to write code which is forward and backwards compatible +#define GAUDI_FUNCTIONAL_CONSTRUCTOR_USES_TUPLE + namespace Gaudi::Functional::details { // CRJ : Stuff for zipping @@ -142,6 +146,16 @@ namespace Gaudi::Functional::details { } invoke_optionally{}; ///////////////////////////////////////// + template + auto get_values_helper( std::index_sequence ) { + return std::make_tuple( ( (void)I, Value{} )... ); + } + + template + using RepeatValues_ = decltype( get_values_helper( std::make_index_sequence() ) ); + + ///////////////////////////////////////// + template && std::is_base_of_v>> auto put( const DataObjectHandle& out_handle, Out2&& out ) { @@ -485,24 +499,24 @@ namespace Gaudi::Functional::details { using KeyValues = std::pair>; // generic constructor: N -> M - DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const std::array& inputs, - const std::array& outputs ) + DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, RepeatValues_ const& inputs, + RepeatValues_ const& outputs ) : DataHandleMixin( std::move( name ), pSvcLocator, inputs, std::index_sequence_for{}, outputs, std::index_sequence_for{} ) {} // special cases: forward to the generic case... // 1 -> 1 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& input, const KeyValue& output ) - : DataHandleMixin( std::move( name ), locator, std::array{input}, - std::array{output} ) {} + : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ), + std::forward_as_tuple( output ) ) {} // 1 -> N DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& input, - const std::array& outputs ) - : DataHandleMixin( std::move( name ), locator, std::array{input}, outputs ) {} + RepeatValues_ const& outputs ) + : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ), outputs ) {} // N -> 1 - DataHandleMixin( std::string name, ISvcLocator* locator, const std::array& inputs, + DataHandleMixin( std::string name, ISvcLocator* locator, RepeatValues_ const& inputs, const KeyValue& output ) - : DataHandleMixin( std::move( name ), locator, inputs, std::array{output} ) {} + : DataHandleMixin( std::move( name ), locator, inputs, std::forward_as_tuple( output ) ) {} template decltype( auto ) inputLocation() const { @@ -538,7 +552,7 @@ namespace Gaudi::Functional::details { public: using KeyValue = std::pair; using KeyValues = std::pair>; - DataHandleMixin( std::string name, ISvcLocator* pSvcLocator ) + DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, std::tuple<> = {}, std::tuple<> = {} ) : BaseClass_t( std::move( name ), pSvcLocator ) { // make sure this algorithm is seen as reentrant by Gaudi this->setProperty( "Cardinality", 0 ).ignore(); @@ -568,13 +582,13 @@ namespace Gaudi::Functional::details { constexpr static std::size_t N_in = sizeof...( In ); // generic constructor: N -> 0 - DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const std::array& inputs ) + DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, RepeatValues_ const& inputs ) : DataHandleMixin( std::move( name ), pSvcLocator, inputs, std::index_sequence_for{} ) {} // special cases: forward to the generic case... // 1 -> 0 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& input ) - : DataHandleMixin( std::move( name ), locator, std::array{input} ) {} + : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ) ) {} template decltype( auto ) inputLocation() const { @@ -617,12 +631,12 @@ namespace Gaudi::Functional::details { using KeyValues = std::pair>; // generic constructor: 0 -> N - DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const std::array& outputs ) + DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, RepeatValues_ const& outputs ) : DataHandleMixin( std::move( name ), pSvcLocator, outputs, std::index_sequence_for{} ) {} // 0 -> 1 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& output ) - : DataHandleMixin( std::move( name ), locator, std::array{output} ) {} + : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( output ) ) {} template decltype( auto ) outputLocation() const { diff --git a/GaudiAlg/include/GaudiAlg/MergingTransformer.h b/GaudiAlg/include/GaudiAlg/MergingTransformer.h index c60b1538e..386d9747d 100644 --- a/GaudiAlg/include/GaudiAlg/MergingTransformer.h +++ b/GaudiAlg/include/GaudiAlg/MergingTransformer.h @@ -217,7 +217,7 @@ namespace Gaudi::Functional { public: using KeyValue = typename base_class::KeyValue; using KeyValues = typename base_class::KeyValues; - using OutKeys = std::array; + using OutKeys = details::RepeatValues_; MergingMultiTransformer( std::string const& name, ISvcLocator* locator, KeyValues const& inputs, OutKeys const& outputs ); @@ -293,7 +293,7 @@ namespace Gaudi::Functional { public: using KeyValue = typename base_class::KeyValue; using KeyValues = typename base_class::KeyValues; - using OutKeys = std::array; + using OutKeys = details::RepeatValues_; MergingMultiTransformerFilter( std::string const& name, ISvcLocator* locator, KeyValues const& inputs, OutKeys const& outputs ); diff --git a/GaudiAlg/include/GaudiAlg/SplittingTransformer.h b/GaudiAlg/include/GaudiAlg/SplittingTransformer.h index f48304e51..92c783474 100644 --- a/GaudiAlg/include/GaudiAlg/SplittingTransformer.h +++ b/GaudiAlg/include/GaudiAlg/SplittingTransformer.h @@ -43,7 +43,7 @@ namespace Gaudi::Functional { using KeyValue = typename base_class::KeyValue; using KeyValues = typename base_class::KeyValues; - SplittingTransformer( std::string name, ISvcLocator* locator, const std::array& inputs, + SplittingTransformer( std::string name, ISvcLocator* locator, const RepeatValues_& inputs, const KeyValues& outputs ) : base_class( std::move( name ), locator, inputs ) , m_outputLocations( @@ -61,7 +61,7 @@ namespace Gaudi::Functional { Gaudi::Details::Property::ImmediatelyInvokeHandler{true} ) {} SplittingTransformer( std::string name, ISvcLocator* locator, const KeyValue& input, const KeyValues& output ) - : SplittingTransformer( std::move( name ), locator, std::array{input}, output ) { + : SplittingTransformer( std::move( name ), locator, std::forward_as_tuple( input ), output ) { static_assert( N == 1, "single input argument requires single input signature" ); } @@ -110,7 +110,7 @@ namespace Gaudi::Functional { using KeyValue = typename base_class::KeyValue; using KeyValues = typename base_class::KeyValues; - SplittingTransformer( std::string name, ISvcLocator* locator, const std::array& inputs, + SplittingTransformer( std::string name, ISvcLocator* locator, const RepeatValues_& inputs, const KeyValues& outputs ) : base_class( std::move( name ), locator, inputs ) , m_outputLocations( @@ -128,7 +128,7 @@ namespace Gaudi::Functional { Gaudi::Details::Property::ImmediatelyInvokeHandler{true} ) {} SplittingTransformer( std::string name, ISvcLocator* locator, const KeyValue& input, const KeyValues& output ) - : SplittingTransformer( std::move( name ), locator, std::array{input}, output ) { + : SplittingTransformer( std::move( name ), locator, std::forward_as_tuple( input ), output ) { static_assert( N == 1, "single input argument requires single input signature" ); } -- GitLab