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