The Gaudi Framework  v29r0 (ff2e7097)
SplittingTransformer.h
Go to the documentation of this file.
1 #ifndef SPLITTING_TRANSFORMER_H
2 #define SPLITTING_TRANSFORMER_H
3 
4 #include <functional>
5 #include <string>
6 #include <vector>
7 
10 
11 namespace Gaudi
12 {
13  namespace Functional
14  {
15 
16  template <typename Signature, typename Traits_ = Traits::useDefaults>
18 
19  template <typename Container>
21  template <typename Container>
23 
25  template <typename Out, typename... In, typename Traits_>
26  class SplittingTransformer<vector_of_<Out>( const In&... ), Traits_>
28  {
30 
31  public:
32  constexpr static std::size_t N = sizeof...( In );
35 
37  const KeyValues& output );
38 
39  SplittingTransformer( const std::string& name, ISvcLocator* locator, const KeyValue& input,
40  const KeyValues& output )
41  : SplittingTransformer( name, locator, std::array<KeyValue, 1>{input}, output )
42  {
43  static_assert( N == 1, "single input argument requires single input signature" );
44  }
45 
46  // accessor to output Locations
47  const std::string& outputLocation( unsigned int n ) const { return m_outputLocations[n]; }
48  unsigned int outputLocationSize() const { return m_outputLocations.size(); }
49 
50  // derived classes can NOT implement execute
51  StatusCode execute() override final { return invoke( std::index_sequence_for<In...>{} ); }
52 
53  // TODO/FIXME: how does the callee know in which order to produce the outputs?
54  // (note: 'missing' items can be specified by making Out an boost::optional<Out>,
55  // and only those entries which contain an Out are stored)
56  virtual vector_of_<Out> operator()( const In&... ) const = 0;
57 
58  private:
59  template <std::size_t... I>
60  StatusCode invoke( std::index_sequence<I...> )
61  {
62  try {
63  // TODO:FIXME: how does operator() know the number and order of expected outputs?
64  using details::as_const;
65  auto out = as_const( *this )( as_const( *std::get<I>( this->m_inputs ).get() )... );
66  if ( out.size() != m_outputs.size() ) {
67  throw GaudiException( "Error during transform: expected " + std::to_string( m_outputs.size() ) +
68  " containers, got " + std::to_string( out.size() ) + " instead",
69  this->name(), StatusCode::FAILURE );
70  }
71  for ( unsigned i = 0; i != out.size(); ++i ) details::put( m_outputs[i], std::move( out[i] ) );
72  } catch ( GaudiException& e ) {
73  ( e.code() ? this->warning() : this->error() ) << e.message() << endmsg;
74  return e.code();
75  }
76  return StatusCode::SUCCESS;
77  }
78  template <typename T>
80  std::vector<std::string> m_outputLocations; // TODO/FIXME for now: use a call-back to update the actual handles!
82  };
83 
84  template <typename Out, typename... In, typename Traits_>
86  const std::string& name, ISvcLocator* pSvcLocator, const std::array<KeyValue, N>& inputs,
87  const KeyValues& outputs )
88  : base_class( name, pSvcLocator, inputs ), m_outputLocations( outputs.second )
89  {
90  auto p = this->declareProperty( outputs.first, m_outputLocations );
91  p->declareUpdateHandler( [=]( Gaudi::Details::PropertyBase& ) {
92  this->m_outputs = details::make_vector_of_handles<decltype( this->m_outputs )>( this, m_outputLocations,
94  if ( details::is_optional<Out>::value ) { // handle constructor does not (yet) allow to set optional flag... so
95  // do it explicitly here...
96  std::for_each( this->m_outputs.begin(), this->m_outputs.end(), []( auto& h ) { h.setOptional( true ); } );
97  }
98  } );
99  p->useUpdateHandler(); // invoke now, to be sure the input handles are synced with the property...
100  }
101  }
102 }
103 
104 #endif
virtual const std::string & message() const
error message to be printed
constexpr std::add_const< T >::type & as_const(T &t) noexcept
detected_or_t_< detail2::defaultHandle_, detail2::OutputHandle_, Tr, T > OutputHandle_t
Define general base for Gaudi exception.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
Handles make_vector_of_handles(IDataHandleHolder *owner, const std::vector< std::string > &init, Gaudi::DataHandle::Mode mode)
T to_string(T...args)
STL namespace.
details::OutputHandle_t< Traits_, details::remove_optional_t< T >> OutputHandle
class MergingTransformer< Out(const vector_of_const_< In > void
virtual const StatusCode & code() const
StatusCode for Exception.
constexpr double second
STL class.
int N
Definition: IOTest.py:101
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:28
Gaudi::Details::PropertyBase * declareProperty(const std::string &name, TYPE &value, const std::string &doc="none")
Declare a property (templated)
SplittingTransformer(const std::string &name, ISvcLocator *locator, const KeyValue &input, const KeyValues &output)
details::template vector_of_const_< Container > vector_of_
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Definition: Property.h:32
T move(T...args)
std::vector< InputHandle_t< In > > m_inputs
struct GAUDI_API array
Parametrisation class for redirection array - like implementation.
STL class.
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
STL class.
struct[[deprecated("use MergingTransformer instead")]] Traits_
auto invoke(F &&f, ArgTypes &&...args) noexcept(noexcept(detail2::INVOKE(std::forward< F >(f), std::forward< ArgTypes >(args)...))) -> decltype(detail2::INVOKE(std::forward< F >(f), std::forward< ArgTypes >(args)...))
Definition: invoke.h:83
T for_each(T...args)
Helper functions to set/get the application return code.
Definition: __init__.py:1
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
Out1 * put(DataObjectHandle< Out1 > &out_handle, Out2 &&out)