All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
SplittingTransformer.h
Go to the documentation of this file.
1 #ifndef SPLITTING_TRANSFORMER_H
2 #define SPLITTING_TRANSFORMER_H
3 
4 #include <vector>
5 #include <string>
6 #include <functional>
7 
10 
11 namespace Gaudi { namespace Functional {
12 
13  template <typename Signature, typename Traits_=Traits::useDefaults> class SplittingTransformer;
14 
15  template <typename Container> using vector_of_ = std::vector<Container>;
16  template <typename Container> using vector_of_optional_ = std::vector<boost::optional<Container>>;
17 
19  template <typename Out, typename... In, typename Traits_>
20  class SplittingTransformer<vector_of_<Out>(const In&...),Traits_>
22  {
24  public:
25  constexpr static std::size_t N = sizeof...(In);
28 
31  const KeyValues& output);
32 
34  const KeyValue& input,
35  const KeyValues& output)
36  : SplittingTransformer( name, locator, std::array<KeyValue,1>{ input }, output )
37  {
38  static_assert(N==1,"single input argument requires single input signature");
39  }
40 
41  // accessor to output Locations
42  const std::string& outputLocation(unsigned int n) const { return m_outputLocations[n]; }
43  unsigned int outputLocationSize() const { return m_outputLocations.size(); }
44 
45  // derived classes can NOT implement execute
46  StatusCode execute() override final
47  { return invoke(std::index_sequence_for<In...>{}); }
48 
49  // TODO/FIXME: how does the callee know in which order to produce the outputs?
50  // (note: 'missing' items can be specified by making Out an boost::optional<Out>,
51  // and only those entries which contain an Out are stored)
52  virtual vector_of_<Out> operator()(const In&... ) const = 0;
53 
54  private:
55  template <std::size_t... I> StatusCode invoke(std::index_sequence<I...>)
56  {
57  try {
58  //TODO:FIXME: how does operator() know the number and order of expected outputs?
59  using details::as_const;
60  auto out = as_const(*this)( as_const(*std::get<I>(this->m_inputs).get())... );
61  if (out.size()!=m_outputs.size()) {
62  throw GaudiException( "Error during transform: expected " + std::to_string(m_outputs.size())
63  + " containers, got " + std::to_string(out.size()) + " instead",
64  this->name(),
66  }
67  for (unsigned i=0;i!=out.size();++i) details::put( m_outputs[i], std::move(out[i]) );
68  } catch ( GaudiException& e ) {
69  (e.code() ? this->warning() : this->error() ) << e.message() << endmsg;
70  return e.code();
71  }
72  return StatusCode::SUCCESS;
73  }
75  std::vector<std::string> m_outputLocations; //TODO/FIXME for now: use a call-back to update the actual handles!
77  };
78 
79 
80  template <typename Out, typename... In, typename Traits_>
82  ::SplittingTransformer( const std::string& name, ISvcLocator* pSvcLocator,
83  const std::array<KeyValue,N>& inputs, const KeyValues& outputs )
84  : base_class ( name , pSvcLocator, inputs )
85  , m_outputLocations( outputs.second )
86  {
87  auto p = this->declareProperty( outputs.first, m_outputLocations );
88  p->declareUpdateHandler( [=](Gaudi::Details::PropertyBase&) {
89  this->m_outputs = details::make_vector_of_handles<decltype(this->m_outputs)>(this, m_outputLocations, Gaudi::DataHandle::Writer);
90  if (details::is_optional<Out>::value) { // handle constructor does not (yet) allow to set optional flag... so do it explicitly here...
91  std::for_each( this->m_outputs.begin(), this->m_outputs.end(), [](auto& h) { h.setOptional(true); } );
92  }
93  } );
94  p->useUpdateHandler(); // invoke now, to be sure the input handles are synced with the property...
95  }
96 
97 
98 }}
99 
100 #endif
virtual const std::string & message() const
error message to be printed
constexpr std::add_const< T >::type & as_const(T &t) noexcept
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.
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:90
details::OutputHandle_t< Traits_, details::remove_optional_t< T >> OutputHandle
class MergingTransformer< Out(const vector_of_const_< In > Traits_
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
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)
detected_or_t_< detail2::defaultHandle_, detail2::OutputHandle_, Tr, T > OutputHandle_t
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.
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:244
Out1 * put(DataObjectHandle< Out1 > &out_handle, Out2 &&out)