The Gaudi Framework  v32r0 (3325bb39)
FunctionalDetails.h
Go to the documentation of this file.
1 #ifndef FUNCTIONAL_DETAILS_H
2 #define FUNCTIONAL_DETAILS_H
3 
4 #include <cassert>
5 #include <sstream>
6 #include <stdexcept>
7 #include <type_traits>
8 
9 // TODO: fwd declare instead?
11 #include "GaudiKernel/Algorithm.h"
15 #include "GaudiKernel/detected.h"
16 
17 // Range V3
18 #include <range/v3/view/const.hpp>
19 #include <range/v3/view/zip.hpp>
20 
22 
23  // CRJ : Stuff for zipping
24  namespace zip {
25 
27  template <typename OS, typename Arg>
28  void printSizes( OS& out, Arg&& arg ) {
29  out << "SizeOf'" << System::typeinfoName( typeid( Arg ) ) << "'=" << std::forward<Arg>( arg ).size();
30  }
31 
33  template <typename OS, typename Arg, typename... Args>
34  void printSizes( OS& out, Arg&& arg, Args&&... args ) {
35  printSizes( out, arg );
36  out << ", ";
37  printSizes( out, args... );
38  }
39 
41  template <typename A>
42  inline bool check_sizes( const A& ) noexcept {
43  return true;
44  }
45 
47  template <typename A, typename B>
48  inline bool check_sizes( const A& a, const B& b ) noexcept {
49  return a.size() == b.size();
50  }
51 
53  template <typename A, typename B, typename... C>
54  inline bool check_sizes( const A& a, const B& b, const C&... c ) noexcept {
55  return ( check_sizes( a, b ) && check_sizes( b, c... ) );
56  }
57 
59  template <typename... Args>
60  inline decltype( auto ) verifySizes( Args&... args ) {
61  if ( UNLIKELY( !check_sizes( args... ) ) ) {
62  std::ostringstream mess;
63  mess << "Zipped containers have different sizes : ";
64  printSizes( mess, args... );
65  throw GaudiException( mess.str(), "Gaudi::Functional::details::zip::verifySizes", StatusCode::FAILURE );
66  }
67  }
68 
70  template <typename... Args>
71  inline decltype( auto ) range( Args&&... args ) {
72 #ifndef NDEBUG
73  verifySizes( args... );
74 #endif
75  return ranges::view::zip( std::forward<Args>( args )... );
76  }
77 
79  template <typename... Args>
80  inline decltype( auto ) const_range( Args&&... args ) {
81 #ifndef NDEBUG
82  verifySizes( args... );
83 #endif
84  return ranges::view::const_( ranges::view::zip( std::forward<Args>( args )... ) );
85  }
86  } // namespace zip
87 
89  namespace details2 {
90  // note: boost::optional in boost 1.66 does not have 'has_value()'...
91  // that requires boost 1.68 or later... so for now, use operator bool() instead ;-(
92  template <typename T>
93  using is_optional_ = decltype( bool{std::declval<T>()}, std::declval<T>().value() );
94  } // namespace details2
95  template <typename Arg>
96  constexpr bool is_optional_v = Gaudi::cpp17::is_detected_v<details2::is_optional_, Arg>;
97 
98  template <typename Arg>
99  using require_is_optional = std::enable_if_t<is_optional_v<Arg>>;
100 
101  template <typename Arg>
102  using require_is_not_optional = std::enable_if_t<!is_optional_v<Arg>>;
103 
104  template <typename T>
105  using remove_optional_t = std::conditional_t<is_optional_v<T>, typename T::value_type, T>;
106 
107  constexpr struct invoke_optionally_t {
108  template <typename F, typename Arg, typename = require_is_not_optional<Arg>>
109  decltype( auto ) operator()( F&& f, Arg&& arg ) const {
110  return std::invoke( std::forward<F>( f ), std::forward<Arg>( arg ) );
111  }
112  template <typename F, typename Arg, typename = require_is_optional<Arg>>
113  void operator()( F&& f, Arg&& arg ) const {
114  if ( arg ) std::invoke( std::forward<F>( f ), *std::forward<Arg>( arg ) );
115  }
116  } invoke_optionally{};
118 
119  template <typename Out1, typename Out2,
120  typename = std::enable_if_t<std::is_constructible_v<Out1, Out2> && std::is_base_of_v<DataObject, Out1>>>
121  Out1* put( const DataObjectHandle<Out1>& out_handle, Out2&& out ) {
122  return out_handle.put( std::make_unique<Out1>( std::forward<Out2>( out ) ) );
123  }
124 
125  template <typename Out1, typename Out2, typename = std::enable_if_t<std::is_constructible_v<Out1, Out2>>>
126  void put( const DataObjectHandle<AnyDataWrapper<Out1>>& out_handle, Out2&& out ) {
127  out_handle.put( std::forward<Out2>( out ) );
128  }
129 
130  // optional put
131  template <typename OutHandle, typename OptOut, typename = require_is_optional<OptOut>>
132  void put( const OutHandle& out_handle, OptOut&& out ) {
133  if ( out ) put( out_handle, *std::forward<OptOut>( out ) );
134  }
136  // adapt to differences between eg. std::vector (which has push_back) and KeyedContainer (which has insert)
137  // adapt to getting a T, and a container wanting T* by doing new T{ std::move(out) }
138  // adapt to getting a optional<T>
139 
140  constexpr struct insert_t {
141  // for Container<T*>, return T
142  template <typename Container>
143  using c_remove_ptr_t = std::remove_pointer_t<typename Container::value_type>;
144 
145  template <typename Container, typename Value>
146  auto operator()( Container& c, Value&& v ) const -> decltype( c.push_back( v ) ) {
147  return c.push_back( std::forward<Value>( v ) );
148  }
149 
150  template <typename Container, typename Value>
151  auto operator()( Container& c, Value&& v ) const -> decltype( c.insert( v ) ) {
152  return c.insert( std::forward<Value>( v ) );
153  }
154 
155  // Container<T*> with T&& as argument
156  template <typename Container, typename Value,
157  typename = std::enable_if_t<std::is_pointer_v<typename Container::value_type>>,
158  typename = std::enable_if_t<std::is_convertible_v<Value, c_remove_ptr_t<Container>>>>
159  auto operator()( Container& c, Value&& v ) const {
160  return operator()( c, new c_remove_ptr_t<Container>{std::forward<Value>( v )} );
161  }
162 
163  } insert{};
164 
166 
167  constexpr struct deref_t {
168  template <typename In, typename = std::enable_if_t<!std::is_pointer_v<In>>>
169  const In& operator()( const In& in ) const {
170  return in;
171  }
172 
173  template <typename In>
174  const In& operator()( const In* in ) const {
175  assert( in != nullptr );
176  return *in;
177  }
178  } deref{};
179 
181  // if Container is a pointer, then we're optional items
182  namespace details2 {
183  template <typename Container, typename Value>
184  void push_back( Container& c, const Value& v, std::true_type ) {
185  c.push_back( v );
186  }
187  template <typename Container, typename Value>
188  void push_back( Container& c, const Value& v, std::false_type ) {
189  c.push_back( &v );
190  }
191 
192  template <typename In>
194  template <template <typename> class Handle, typename I, typename = std::enable_if_t<std::is_convertible_v<I, In>>>
195  auto operator()( const Handle<I>& h ) -> const In& {
196  return *h.get();
197  }
198  template <template <typename> class Handle, typename I,
199  typename = std::enable_if_t<std::is_convertible_v<I*, In>>>
200  auto operator()( const Handle<I>& h ) -> const In {
201  return h.getIfExists();
202  } // In is-a pointer
203  };
204 
205  template <typename T>
206  T* deref_if( T* const t, std::false_type ) {
207  return t;
208  }
209  template <typename T>
210  T& deref_if( T* const t, std::true_type ) {
211  return *t;
212  }
213  } // namespace details2
214 
215  template <typename Container>
217  static constexpr bool is_pointer = std::is_pointer_v<Container>;
218  using val_t = std::add_const_t<std::remove_pointer_t<Container>>;
219  using ptr_t = std::add_pointer_t<val_t>;
220  using ref_t = std::add_lvalue_reference_t<val_t>;
223 
224  public:
225  using value_type = std::conditional_t<is_pointer, ptr_t, val_t>;
226  using size_type = typename ContainerVector::size_type;
227  class iterator {
228  using it_t = typename ContainerVector::const_iterator;
230  friend class vector_of_const_;
231  iterator( it_t iter ) : m_i( iter ) {}
232  using ret_t = std::conditional_t<is_pointer, ptr_t, ref_t>;
233 
234  public:
235  using iterator_category = typename it_t::iterator_category;
236  using value_type = typename it_t::iterator_category;
237  using reference = typename it_t::reference;
238  using pointer = typename it_t::pointer;
239  using difference_type = typename it_t::difference_type;
240 
241  friend bool operator!=( const iterator& lhs, const iterator& rhs ) { return lhs.m_i != rhs.m_i; }
242  friend bool operator==( const iterator& lhs, const iterator& rhs ) { return lhs.m_i == rhs.m_i; }
243  friend auto operator-( const iterator& lhs, const iterator& rhs ) { return lhs.m_i - rhs.m_i; }
244  ret_t operator*() const { return details2::deref_if( *m_i, std::bool_constant<!is_pointer>{} ); }
246  ++m_i;
247  return *this;
248  }
250  --m_i;
251  return *this;
252  }
253  bool is_null() const { return !*m_i; }
254  explicit operator bool() const { return !is_null(); }
255  };
256  vector_of_const_() = default;
257  void reserve( size_type size ) { m_containers.reserve( size ); }
258  template <typename T> // , typename = std::is_convertible<T,std::conditional_t<is_pointer,ptr_t,val_t>>
259  void push_back( T&& container ) {
260  details2::push_back( m_containers, std::forward<T>( container ), std::bool_constant<is_pointer>{} );
261  } // note: does not copy its argument, so we're not really a container...
262  iterator begin() const { return m_containers.begin(); }
263  iterator end() const { return m_containers.end(); }
264  size_type size() const { return m_containers.size(); }
265 
266  template <typename X = Container>
267  std::enable_if_t<!std::is_pointer_v<X>, ref_t> operator[]( size_type i ) const {
268  return *m_containers[i];
269  }
270 
271  template <typename X = Container>
272  std::enable_if_t<std::is_pointer_v<X>, ptr_t> operator[]( size_type i ) const {
273  return m_containers[i];
274  }
275 
276  template <typename X = Container>
277  std::enable_if_t<!std::is_pointer_v<X>, ref_t> at( size_type i ) const {
278  return *m_containers[i];
279  }
280 
281  template <typename X = Container>
282  std::enable_if_t<std::is_pointer_v<X>, ptr_t> at( size_type i ) const {
283  return m_containers[i];
284  }
285 
286  bool is_null( size_type i ) const { return !m_containers[i]; }
287  };
288 
290  namespace detail2 { // utilities for detected_or_t{,_} usage
291  template <typename Tr>
292  using BaseClass_t = typename Tr::BaseClass;
293  template <typename Tr, typename T>
294  using OutputHandle_t = typename Tr::template OutputHandle<T>;
295  template <typename Tr, typename T>
296  using InputHandle_t = typename Tr::template InputHandle<T>;
297  } // namespace detail2
298 
299  // check whether Traits::BaseClass is a valid type,
300  // if so, define BaseClass_t<Traits> as being Traits::BaseClass
301  // else define as being GaudiAlgorithm
302  template <typename Tr>
303  using BaseClass_t = Gaudi::cpp17::detected_or_t<GaudiAlgorithm, detail2::BaseClass_t, Tr>;
304 
305  // check whether Traits::{Input,Output}Handle<T> is a valid type,
306  // if so, define {Input,Output}Handle_t<Traits,T> as being Traits::{Input,Output}Handle<T>
307  // else define as being DataObject{Read,,Write}Handle<T>
308  template <typename Tr, typename T>
309  using OutputHandle_t = Gaudi::cpp17::detected_or_t<DataObjectWriteHandle<T>, detail2::OutputHandle_t, Tr, T>;
310  template <typename Tr, typename T>
311  using InputHandle_t = Gaudi::cpp17::detected_or_t<DataObjectReadHandle<T>, detail2::InputHandle_t, Tr, T>;
312 
313  template <typename Traits>
314  inline constexpr bool isLegacy =
315  std::is_base_of_v<Gaudi::details::LegacyAlgorithmAdapter, details::BaseClass_t<Traits>>;
316 
318 
319  template <typename Handles>
321  Handles handles;
322  handles.reserve( init.size() );
324  init.begin(), init.end(),
325  std::back_inserter( handles ), [&]( const std::string& loc ) -> typename Handles::value_type {
326  return {loc, owner};
327  } );
328  return handles;
329  }
330 
331  template <typename Handle, typename Algo>
332  auto get( const Handle& handle, const Algo&, const EventContext& )
333  -> decltype( details::deref( handle.get() ) ) // make it SFINAE friendly...
334  {
335  return details::deref( handle.get() );
336  }
337 
338  template <typename Handle>
339  auto getKey( const Handle& h ) -> decltype( h.objKey() ) {
340  return h.objKey();
341  }
342 
344  // given a pack, return a corresponding tuple
345  template <typename... In>
347  using type = std::tuple<In...>;
348 
349  static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
350  "EventContext can only appear as first argument" );
351 
352  template <typename Algorithm, typename Handles>
353  static auto apply( const Algorithm& algo, Handles& handles ) {
354  return std::apply( [&]( const auto&... handle ) { return algo( details::deref( handle.get() )... ); }, handles );
355  }
356  template <typename Algorithm, typename Handles>
357  static auto apply( const Algorithm& algo, const EventContext& ctx, Handles& handles ) {
358  return std::apply( [&]( const auto&... handle ) { return algo( get( handle, algo, ctx )... ); }, handles );
359  }
360  };
361 
362  // except when it starts with EventContext, then drop it
363  template <typename... In>
365  using type = std::tuple<In...>;
366 
367  static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
368  "EventContext can only appear as first argument" );
369 
370  template <typename Algorithm, typename Handles>
371  static auto apply( const Algorithm& algo, Handles& handles ) {
372  return std::apply(
373  [&]( const auto&... handle ) {
374  const auto& ctx = Gaudi::Hive::currentContext();
375  return algo( ctx, get( handle, algo, ctx )... );
376  },
377  handles );
378  }
379 
380  template <typename Algorithm, typename Handles>
381  static auto apply( const Algorithm& algo, const EventContext& ctx, Handles& handles ) {
382  return std::apply( [&]( const auto&... handle ) { return algo( ctx, get( handle, algo, ctx )... ); }, handles );
383  }
384  };
385 
386  template <typename... In>
388 
389  template <typename OutputSpec, typename InputSpec, typename Traits_>
391 
392  template <typename Out, typename In, typename Tr>
394  const std::string& newLoc ) {
395  auto sc = parent.setProperty( prop, newLoc );
396  if ( sc.isFailure() ) throw GaudiException( "Could not set Property", prop + " -> " + newLoc, sc );
397  }
398 
399  template <typename Out, typename In, typename Tr>
401  const std::vector<std::string>& newLocs ) {
404  ss << '[', newLocs, ", ", []( std::ostream & os, const auto& i ) -> auto& { return os << "'" << i << "'"; } )
405  << ']';
406  auto sc = parent.setProperty( prop, ss.str() );
407  if ( sc.isFailure() ) throw GaudiException( "Could not set Property", prop + " -> " + ss.str(), sc );
408  }
409 
410  template <typename... Out, typename... In, typename Traits_>
411  class DataHandleMixin<std::tuple<Out...>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
412  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
413 
414  template <typename IArgs, typename OArgs, std::size_t... I, std::size_t... J>
415  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator, const IArgs& inputs, std::index_sequence<I...>,
416  const OArgs& outputs, std::index_sequence<J...> )
417  : BaseClass_t<Traits_>( name, pSvcLocator )
418  , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... )
419  , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
420  this->setProperty( "Cardinality", 0 ); // make sure this algorithm is seen as reentrant by Gaudi
421  }
422 
423  public:
424  constexpr static std::size_t N_in = sizeof...( In );
425  constexpr static std::size_t N_out = sizeof...( Out );
426 
429 
430  // generic constructor: N -> M
432  const std::array<KeyValue, N_out>& outputs )
433  : DataHandleMixin( name, pSvcLocator, inputs, std::index_sequence_for<In...>{}, outputs,
434  std::index_sequence_for<Out...>{} ) {}
435 
436  // special cases: forward to the generic case...
437  // 1 -> 1
438  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input, const KeyValue& output )
439  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input}, std::array<KeyValue, 1>{output} ) {}
440  // 1 -> N
441  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input,
442  const std::array<KeyValue, N_out>& outputs )
443  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input}, outputs ) {}
444  // N -> 1
446  const KeyValue& output )
447  : DataHandleMixin( name, locator, inputs, std::array<KeyValue, 1>{output} ) {}
448 
449  template <std::size_t N = 0>
450  decltype( auto ) inputLocation() const {
451  return getKey( std::get<N>( m_inputs ) );
452  }
453  constexpr unsigned int inputLocationSize() const { return N_in; }
454 
455  template <std::size_t N = 0>
456  decltype( auto ) outputLocation() const {
457  return getKey( std::get<N>( m_outputs ) );
458  }
459  constexpr unsigned int outputLocationSize() const { return N_out; }
460 
461  protected:
462  bool isReEntrant() const override { return true; }
463 
466  };
467 
468  template <typename Traits_>
469  class DataHandleMixin<void, std::tuple<>, Traits_> : public BaseClass_t<Traits_> {
470  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
471 
472  public:
473  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator ) : BaseClass_t<Traits_>( name, pSvcLocator ) {
474  this->setProperty( "Cardinality", 0 ); // make sure this algorithm is seen as reentrant by Gaudi
475  }
476 
477  protected:
478  bool isReEntrant() const override { return true; }
479 
481  };
482 
483  template <typename... In, typename Traits_>
484  class DataHandleMixin<void, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
485  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
486 
487  template <typename IArgs, std::size_t... I>
488  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator, const IArgs& inputs, std::index_sequence<I...> )
489  : BaseClass_t<Traits_>( name, pSvcLocator )
490  , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... ) {
491  this->setProperty( "Cardinality", 0 ); // make sure this algorithm is seen as reentrant by Gaudi
492  }
493 
494  public:
497  constexpr static std::size_t N_in = sizeof...( In );
498 
499  // generic constructor: N -> 0
501  : DataHandleMixin( name, pSvcLocator, inputs, std::index_sequence_for<In...>{} ) {}
502 
503  // special cases: forward to the generic case...
504  // 1 -> 0
505  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input )
506  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input} ) {}
507 
508  template <std::size_t N = 0>
509  decltype( auto ) inputLocation() const {
510  return getKey( std::get<N>( m_inputs ) );
511  }
512 
513  constexpr unsigned int inputLocationSize() const { return N_in; }
514 
515  protected:
516  bool isReEntrant() const override { return true; }
517 
519  };
520 
521  template <typename... Out, typename Traits_>
522  class DataHandleMixin<std::tuple<Out...>, void, Traits_> : public BaseClass_t<Traits_> {
523  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
524 
525  template <typename OArgs, std::size_t... J>
526  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator, const OArgs& outputs,
527  std::index_sequence<J...> )
528  : BaseClass_t<Traits_>( name, pSvcLocator )
529  , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
530  this->setProperty( "Cardinality", 0 ); // make sure this algorithm is seen as reentrant by Gaudi
531  }
532 
533  public:
534  constexpr static std::size_t N_out = sizeof...( Out );
537 
538  // generic constructor: 0 -> N
540  : DataHandleMixin( name, pSvcLocator, outputs, std::index_sequence_for<Out...>{} ) {}
541 
542  // 0 -> 1
544  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{output} ) {}
545 
546  template <std::size_t N = 0>
547  decltype( auto ) outputLocation() const {
548  return getKey( std::get<N>( m_outputs ) );
549  }
550  constexpr unsigned int outputLocationSize() const { return N_out; }
551 
552  protected:
553  bool isReEntrant() const override { return true; }
554 
556  };
557 
559  template <typename Fun, typename Container, typename... Args>
560  constexpr void applyPostProcessing( const Fun&, Container&, Args... ) {
561  static_assert( sizeof...( Args ) == 0, "Args should not be used!" );
562  }
563 
564  template <typename Fun, typename Container>
565  auto applyPostProcessing( const Fun& fun, Container& c ) -> decltype( fun.postprocess( c ), void() ) {
566  fun.postprocess( c );
567  }
568 
569 } // namespace Gaudi::Functional::details
570 
571 #endif
typename Tr::template InputHandle< T > InputHandle_t
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_out > &outputs)
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_in > &inputs)
StatusCode setProperty(IProperty *component, const std::string &name, const TYPE &value, const std::string &doc)
simple function to set the property of the given object from the value
Definition: Property.h:1180
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
#define UNLIKELY(x)
Definition: Kernel.h:89
constexpr auto size(const T &, Args &&...) noexcept
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >, const OArgs &outputs, std::index_sequence< J... >)
const In & operator()(const In &in) const
Define general base for Gaudi exception.
DataHandleMixin(const std::string &name, ISvcLocator *locator, const std::array< KeyValue, N_in > &inputs, const KeyValue &output)
friend bool operator==(const iterator &lhs, const iterator &rhs)
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
auto operator()(const Handle< I > &h) -> const In &
friend bool operator!=(const iterator &lhs, const iterator &rhs)
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
auto operator()(Container &c, Value &&v) const
typename ContainerVector::const_iterator it_t
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:298
void printSizes(OS &out, Arg &&arg)
Print the parameter.
constexpr struct Gaudi::Functional::details::insert_t insert
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_in > &inputs, const std::array< KeyValue, N_out > &outputs)
Header file for class GaudiAlgorithm.
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &input, const KeyValue &output)
std::add_const_t< std::remove_pointer_t< Container >> val_t
STL namespace.
typename filter_evtcontext_t< In... >::type filter_evtcontext
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
T end(T...args)
auto getKey(const Handle &h) -> decltype(h.objKey())
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const OArgs &outputs, std::index_sequence< J... >)
void push_back(Container &c, const Value &v, std::true_type)
std::enable_if_t<!std::is_pointer_v< X >, ref_t > at(size_type i) const
std::remove_pointer_t< typename Container::value_type > c_remove_ptr_t
std::add_lvalue_reference_t< val_t > ref_t
This class represents an entry point to all the event specific data.
Definition: EventContext.h:24
T * deref_if(T *const t, std::false_type)
constexpr struct Gaudi::Functional::details::deref_t deref
std::vector< InputHandle_t< In > > m_inputs
STL class.
DataObjectHandle.h GaudiKernel/DataObjectHandle.h.
Definition: AlgTool.h:26
constexpr struct Gaudi::Functional::details::invoke_optionally_t invoke_optionally
typename Tr::template OutputHandle< T > OutputHandle_t
class MergingTransformer< Out(const vector_of_const_< In > Traits_
constexpr void applyPostProcessing(const Fun &, Container &, Args...)
Gaudi::cpp17::detected_or_t< DataObjectReadHandle< T >, detail2::InputHandle_t, Tr, T > InputHandle_t
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &input, const std::array< KeyValue, N_out > &outputs)
void updateHandleLocations(DataHandleMixin< Out, In, Tr > &parent, const std::string &prop, const std::vector< std::string > &newLocs)
static auto apply(const Algorithm &algo, Handles &handles)
friend auto operator-(const iterator &lhs, const iterator &rhs)
T * put(std::unique_ptr< T > object) const
Register object in transient store.
GAUDI_API const EventContext & currentContext()
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &output)
static auto apply(const Algorithm &algo, Handles &handles)
decltype(auto) range(Args &&...args)
Zips multiple containers together to form a single range.
std::enable_if_t<!is_optional_v< Arg >> require_is_not_optional
std::conditional_t< is_pointer, ptr_t, ref_t > ret_t
decltype(bool{std::declval< T >()}, std::declval< T >().value()) is_optional_
auto operator()(Container &c, Value &&v) const -> decltype(c.insert(v))
std::conditional_t< is_optional_v< T >, typename T::value_type, T > remove_optional_t
std::conditional_t< is_pointer, ptr_t, val_t > value_type
Stream & ostream_joiner(Stream &os, Iterator first, Iterator last, Separator sep, OutputElement output=OutputElement{})
Definition: SerializeSTL.h:37
decltype(auto) verifySizes(Args &...args)
Verify the data container sizes have the same sizes.
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator)
T size(T...args)
struct GAUDI_API array
Parametrisation class for redirection array - like implementation.
T begin(T...args)
bool check_sizes(const A &) noexcept
Resolve case there is only one container in the range.
Gaudi::cpp17::detected_or_t< DataObjectWriteHandle< T >, detail2::OutputHandle_t, Tr, T > OutputHandle_t
auto operator()(Container &c, Value &&v) const -> decltype(c.push_back(v))
T back_inserter(T...args)
Out1 * put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
std::tuple< details::OutputHandle_t< Traits_, Out >... > m_outputs
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:79
std::enable_if_t< is_optional_v< Arg >> require_is_optional
class MergingTransformer< Out(const vector_of_const_< In > void
STL class.
constexpr static const auto FAILURE
Definition: StatusCode.h:86
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &input)
std::enable_if_t< std::is_pointer_v< X >, ptr_t > at(size_type i) const
T transform(T...args)
const std::string & inputLocation(unsigned int n) const
std::enable_if_t<!std::is_pointer_v< X >, ref_t > operator[](size_type i) const
const In & operator()(const In *in) const
STL class.
decltype(auto) const_range(Args &&...args)
Zips multiple containers together to form a single const range.
Handles make_vector_of_handles(IDataHandleHolder *owner, const std::vector< std::string > &init)
T & deref_if(T *const t, std::true_type)
auto operator()(const Handle< I > &h) -> const In
Gaudi::cpp17::detected_or_t< GaudiAlgorithm, detail2::BaseClass_t, Tr > BaseClass_t
void push_back(Container &c, const Value &v, std::false_type)
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >)
T reserve(T...args)
void updateHandleLocation(DataHandleMixin< Out, In, Tr > &parent, const std::string &prop, const std::string &newLoc)
typename ContainerVector::size_type size_type
std::enable_if_t< std::is_pointer_v< X >, ptr_t > operator[](size_type i) const