The Gaudi Framework  v33r2 (a6f0ec87)
FunctionalDetails.h
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #ifndef FUNCTIONAL_DETAILS_H
12 #define FUNCTIONAL_DETAILS_H
13 
14 #include <cassert>
15 #include <sstream>
16 #include <stdexcept>
17 #include <type_traits>
18 
19 // TODO: fwd declare instead?
21 #include "GaudiKernel/Algorithm.h"
25 #include "GaudiKernel/detected.h"
26 
27 // Range V3
28 #include <range/v3/version.hpp>
29 #include <range/v3/view/const.hpp>
30 #include <range/v3/view/zip.hpp>
31 // upstream has renamed namespace ranges::view ranges::views
32 #if RANGE_V3_VERSION < 900
33 namespace ranges::views {
34  using namespace ranges::view;
35 }
36 #endif
37 
38 #if defined( __clang__ ) && ( __clang_major__ < 9 ) || defined( __APPLE__ ) && ( __clang_major__ < 12 )
39 # define GF_SUPPRESS_SPURIOUS_CLANG_WARNING_BEGIN \
40  _Pragma( "clang diagnostic push" ) _Pragma( "clang diagnostic ignored \"-Wunused-lambda-capture\"" )
41 # define GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END _Pragma( "clang diagnostic pop" )
42 #else
43 # define GF_SUPPRESS_SPURIOUS_CLANG_WARNING_BEGIN
44 # define GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END
45 #endif
46 
48 
49  // CRJ : Stuff for zipping
50  namespace zip {
51 
53  template <typename OS, typename Arg>
54  void printSizes( OS& out, Arg&& arg ) {
55  out << "SizeOf'" << System::typeinfoName( typeid( Arg ) ) << "'=" << std::forward<Arg>( arg ).size();
56  }
57 
59  template <typename OS, typename Arg, typename... Args>
60  void printSizes( OS& out, Arg&& arg, Args&&... args ) {
61  printSizes( out, arg );
62  out << ", ";
63  printSizes( out, args... );
64  }
65 
67  template <typename A>
68  inline bool check_sizes( const A& ) noexcept {
69  return true;
70  }
71 
73  template <typename A, typename B>
74  inline bool check_sizes( const A& a, const B& b ) noexcept {
75  return a.size() == b.size();
76  }
77 
79  template <typename A, typename B, typename... C>
80  inline bool check_sizes( const A& a, const B& b, const C&... c ) noexcept {
81  return ( check_sizes( a, b ) && check_sizes( b, c... ) );
82  }
83 
85  template <typename... Args>
86  inline decltype( auto ) verifySizes( Args&... args ) {
87  if ( UNLIKELY( !check_sizes( args... ) ) ) {
88  std::ostringstream mess;
89  mess << "Zipped containers have different sizes : ";
90  printSizes( mess, args... );
91  throw GaudiException( mess.str(), "Gaudi::Functional::details::zip::verifySizes", StatusCode::FAILURE );
92  }
93  }
94 
96  template <typename... Args>
97  inline decltype( auto ) range( Args&&... args ) {
98 #ifndef NDEBUG
99  verifySizes( args... );
100 #endif
101  return ranges::views::zip( std::forward<Args>( args )... );
102  }
103 
105  template <typename... Args>
106  inline decltype( auto ) const_range( Args&&... args ) {
107 #ifndef NDEBUG
108  verifySizes( args... );
109 #endif
110  return ranges::views::const_( ranges::views::zip( std::forward<Args>( args )... ) );
111  }
112  } // namespace zip
113 
115  namespace details2 {
116  // note: boost::optional in boost 1.66 does not have 'has_value()'...
117  // that requires boost 1.68 or later... so for now, use operator bool() instead ;-(
118  template <typename T>
119  using is_optional_ = decltype( bool{std::declval<T>()}, std::declval<T>().value() );
120  } // namespace details2
121  template <typename Arg>
122  constexpr bool is_optional_v = Gaudi::cpp17::is_detected_v<details2::is_optional_, Arg>;
123 
124  template <typename Arg>
125  using require_is_optional = std::enable_if_t<is_optional_v<Arg>>;
126 
127  template <typename Arg>
128  using require_is_not_optional = std::enable_if_t<!is_optional_v<Arg>>;
129 
130  template <typename T>
131  using remove_optional_t = std::conditional_t<is_optional_v<T>, typename T::value_type, T>;
132 
133  constexpr struct invoke_optionally_t {
134  template <typename F, typename Arg, typename = require_is_not_optional<Arg>>
135  decltype( auto ) operator()( F&& f, Arg&& arg ) const {
136  return std::invoke( std::forward<F>( f ), std::forward<Arg>( arg ) );
137  }
138  template <typename F, typename Arg, typename = require_is_optional<Arg>>
139  void operator()( F&& f, Arg&& arg ) const {
140  if ( arg ) std::invoke( std::forward<F>( f ), *std::forward<Arg>( arg ) );
141  }
142  } invoke_optionally{};
144 
145  template <typename Out1, typename Out2,
146  typename = std::enable_if_t<std::is_constructible_v<Out1, Out2> && std::is_base_of_v<DataObject, Out1>>>
147  Out1* put( const DataObjectHandle<Out1>& out_handle, Out2&& out ) {
148  return out_handle.put( std::make_unique<Out1>( std::forward<Out2>( out ) ) );
149  }
150 
151  template <typename Out1, typename Out2, typename = std::enable_if_t<std::is_constructible_v<Out1, Out2>>>
152  void put( const DataObjectHandle<AnyDataWrapper<Out1>>& out_handle, Out2&& out ) {
153  out_handle.put( std::forward<Out2>( out ) );
154  }
155 
156  // optional put
157  template <typename OutHandle, typename OptOut, typename = require_is_optional<OptOut>>
158  void put( const OutHandle& out_handle, OptOut&& out ) {
159  if ( out ) put( out_handle, *std::forward<OptOut>( out ) );
160  }
162  // adapt to differences between eg. std::vector (which has push_back) and KeyedContainer (which has insert)
163  // adapt to getting a T, and a container wanting T* by doing new T{ std::move(out) }
164  // adapt to getting a optional<T>
165 
166  constexpr struct insert_t {
167  // for Container<T*>, return T
168  template <typename Container>
169  using c_remove_ptr_t = std::remove_pointer_t<typename Container::value_type>;
170 
171  template <typename Container, typename Value>
172  auto operator()( Container& c, Value&& v ) const -> decltype( c.push_back( v ) ) {
173  return c.push_back( std::forward<Value>( v ) );
174  }
175 
176  template <typename Container, typename Value>
177  auto operator()( Container& c, Value&& v ) const -> decltype( c.insert( v ) ) {
178  return c.insert( std::forward<Value>( v ) );
179  }
180 
181  // Container<T*> with T&& as argument
182  template <typename Container, typename Value,
183  typename = std::enable_if_t<std::is_pointer_v<typename Container::value_type>>,
184  typename = std::enable_if_t<std::is_convertible_v<Value, c_remove_ptr_t<Container>>>>
185  auto operator()( Container& c, Value&& v ) const {
186  return operator()( c, new c_remove_ptr_t<Container>{std::forward<Value>( v )} );
187  }
188 
189  } insert{};
190 
192 
193  constexpr struct deref_t {
194  template <typename In, typename = std::enable_if_t<!std::is_pointer_v<In>>>
195  const In& operator()( const In& in ) const {
196  return in;
197  }
198 
199  template <typename In, typename = std::enable_if_t<!std::is_pointer_v<std::decay_t<In>>>>
200  In operator()( In&& in ) const {
201  return std::forward<In>( in );
202  }
203 
204  template <typename In>
205  const In& operator()( const In* in ) const {
206  assert( in != nullptr );
207  return *in;
208  }
209  } deref{};
210 
212  // if Container is a pointer, then we're optional items
213  namespace details2 {
214  template <typename T>
216 
217  template <typename T, typename IT>
218  struct is_gaudi_range<Gaudi::Range_<T, IT>> : std::true_type {};
219 
220  template <typename T, typename IT>
221  struct is_gaudi_range<Gaudi::NamedRange_<T, IT>> : std::true_type {};
222 
223  template <typename T>
224  constexpr static bool is_gaudi_range_v = is_gaudi_range<T>::value;
225 
226  template <typename Container, typename Value>
227  void push_back( Container& c, const Value& v, std::true_type ) {
228  c.push_back( v );
229  }
230  template <typename Container, typename Value>
231  void push_back( Container& c, const Value& v, std::false_type ) {
232  c.push_back( &v );
233  }
234 
235  template <typename In>
237  template <template <typename> class Handle, typename I, typename = std::enable_if_t<std::is_convertible_v<I, In>>>
238  auto operator()( const Handle<I>& h ) -> const In& {
239  return *h.get();
240  }
241  template <template <typename> class Handle, typename I, typename IT>
242  auto operator()( const Handle<Gaudi::Range_<I, IT>>& h ) -> const In {
243  return h.get();
244  }
245  template <template <typename> class Handle, typename I, typename IT>
246  auto operator()( const Handle<Gaudi::NamedRange_<I, IT>>& h ) -> const In {
247  return h.get();
248  }
249  template <template <typename> class Handle, typename I,
250  typename = std::enable_if_t<std::is_convertible_v<I*, In>>>
251  auto operator()( const Handle<I>& h ) -> const In {
252  return h.getIfExists();
253  } // In is-a pointer
254  };
255 
256  template <typename T>
257  T* deref_if( T* const t, std::false_type ) {
258  return t;
259  }
260  template <typename T>
261  T& deref_if( T* const t, std::true_type ) {
262  return *t;
263  }
264  } // namespace details2
265 
266  template <typename Container>
268  static constexpr bool is_pointer = std::is_pointer_v<Container>;
269  static constexpr bool is_range = details2::is_gaudi_range_v<Container>;
270  using val_t = std::add_const_t<std::remove_pointer_t<Container>>;
271  using ptr_t = std::add_pointer_t<val_t>;
272  using ref_t = std::add_lvalue_reference_t<val_t>;
275 
276  public:
277  using value_type = std::conditional_t<is_pointer, ptr_t, val_t>;
278  using size_type = typename ContainerVector::size_type;
279  class iterator {
280  using it_t = typename ContainerVector::const_iterator;
282  friend class vector_of_const_;
283  iterator( it_t iter ) : m_i( iter ) {}
284  using ret_t = std::conditional_t<is_pointer, ptr_t, ref_t>;
285 
286  public:
287  using iterator_category = typename it_t::iterator_category;
288  using value_type = typename it_t::iterator_category;
289  using reference = typename it_t::reference;
290  using pointer = typename it_t::pointer;
291  using difference_type = typename it_t::difference_type;
292 
293  friend bool operator!=( const iterator& lhs, const iterator& rhs ) { return lhs.m_i != rhs.m_i; }
294  friend bool operator==( const iterator& lhs, const iterator& rhs ) { return lhs.m_i == rhs.m_i; }
295  friend auto operator-( const iterator& lhs, const iterator& rhs ) { return lhs.m_i - rhs.m_i; }
296  ret_t operator*() const {
297  if constexpr ( is_range ) {
298  return *m_i;
299  } else {
300  return details2::deref_if( *m_i, std::bool_constant<!is_pointer>{} );
301  }
302  }
304  ++m_i;
305  return *this;
306  }
308  --m_i;
309  return *this;
310  }
311  bool is_null() const { return !*m_i; }
312  explicit operator bool() const { return !is_null(); }
313  };
314  vector_of_const_() = default;
315  void reserve( size_type size ) { m_containers.reserve( size ); }
316  template <typename T> // , typename = std::is_convertible<T,std::conditional_t<is_pointer,ptr_t,val_t>>
317  void push_back( T&& container ) {
318  details2::push_back( m_containers, std::forward<T>( container ),
319  std::bool_constant < is_pointer or is_range > {} );
320  } // note: does not copy its argument, so we're not really a container...
321  iterator begin() const { return m_containers.begin(); }
322  iterator end() const { return m_containers.end(); }
323  size_type size() const { return m_containers.size(); }
324 
325  template <typename X = Container>
326  std::enable_if_t<!std::is_pointer_v<X>, ref_t> operator[]( size_type i ) const {
327  return *m_containers[i];
328  }
329 
330  template <typename X = Container>
331  std::enable_if_t<std::is_pointer_v<X>, ptr_t> operator[]( size_type i ) const {
332  return m_containers[i];
333  }
334 
335  template <typename X = Container>
336  std::enable_if_t<!std::is_pointer_v<X>, ref_t> at( size_type i ) const {
337  return *m_containers[i];
338  }
339 
340  template <typename X = Container>
341  std::enable_if_t<std::is_pointer_v<X>, ptr_t> at( size_type i ) const {
342  return m_containers[i];
343  }
344 
345  bool is_null( size_type i ) const { return !m_containers[i]; }
346  };
347 
349  namespace detail2 { // utilities for detected_or_t{,_} usage
350  template <typename Tr>
351  using BaseClass_t = typename Tr::BaseClass;
352  template <typename Tr, typename T>
353  using OutputHandle_t = typename Tr::template OutputHandle<T>;
354  template <typename Tr, typename T>
355  using InputHandle_t = typename Tr::template InputHandle<T>;
356  } // namespace detail2
357 
358  // check whether Traits::BaseClass is a valid type,
359  // if so, define BaseClass_t<Traits> as being Traits::BaseClass
360  // else define as being GaudiAlgorithm
361  template <typename Tr>
362  using BaseClass_t = Gaudi::cpp17::detected_or_t<GaudiAlgorithm, detail2::BaseClass_t, Tr>;
363 
364  // check whether Traits::{Input,Output}Handle<T> is a valid type,
365  // if so, define {Input,Output}Handle_t<Traits,T> as being Traits::{Input,Output}Handle<T>
366  // else define as being DataObject{Read,,Write}Handle<T>
367  template <typename Tr, typename T>
368  using OutputHandle_t = Gaudi::cpp17::detected_or_t<DataObjectWriteHandle<T>, detail2::OutputHandle_t, Tr, T>;
369  template <typename Tr, typename T>
370  using InputHandle_t = Gaudi::cpp17::detected_or_t<DataObjectReadHandle<T>, detail2::InputHandle_t, Tr, T>;
371 
372  template <typename Traits>
373  inline constexpr bool isLegacy =
374  std::is_base_of_v<Gaudi::details::LegacyAlgorithmAdapter, details::BaseClass_t<Traits>>;
375 
377 
378  template <typename Handles>
380  Handles handles;
381  handles.reserve( init.size() );
383  init.begin(), init.end(),
384  std::back_inserter( handles ), [&]( const std::string& loc ) -> typename Handles::value_type {
385  return {loc, owner};
386  } );
387  return handles;
388  }
389 
390  template <typename Handle, typename Algo>
391  auto get( const Handle& handle, const Algo&, const EventContext& )
392  -> decltype( details::deref( handle.get() ) ) // make it SFINAE friendly...
393  {
394  return details::deref( handle.get() );
395  }
396 
397  template <typename Handle>
398  auto getKey( const Handle& h ) -> decltype( h.objKey() ) {
399  return h.objKey();
400  }
401 
403  // given a pack, return a corresponding tuple
404  template <typename... In>
406  using type = std::tuple<In...>;
407 
408  static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
409  "EventContext can only appear as first argument" );
410 
411  template <typename Algorithm, typename Handles>
412  static auto apply( const Algorithm& algo, Handles& handles ) {
413  return std::apply(
414  [&]( const auto&... handle ) { return algo( get( handle, algo, Gaudi::Hive::currentContext() )... ); },
415  handles );
416  }
417  template <typename Algorithm, typename Handles>
418  static auto apply( const Algorithm& algo, const EventContext& ctx, Handles& handles ) {
419  return std::apply( [&]( const auto&... handle ) { return algo( get( handle, algo, ctx )... ); }, handles );
420  }
421  };
422 
423  // except when it starts with EventContext, then drop it
424  template <typename... In>
426  using type = std::tuple<In...>;
427 
428  static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
429  "EventContext can only appear as first argument" );
430 
431  template <typename Algorithm, typename Handles>
432  static auto apply( const Algorithm& algo, const EventContext& ctx, Handles& handles ) {
433  return std::apply( [&]( const auto&... handle ) { return algo( ctx, get( handle, algo, ctx )... ); }, handles );
434  }
435 
436  template <typename Algorithm, typename Handles>
437  static auto apply( const Algorithm& algo, Handles& handles ) {
438  return apply( algo, Gaudi::Hive::currentContext(), handles );
439  }
440  };
441 
442  template <typename... In>
444 
445  template <typename OutputSpec, typename InputSpec, typename Traits_>
447 
448  template <typename Out, typename In, typename Tr>
450  const std::string& newLoc ) {
451  auto sc = parent.setProperty( prop, newLoc );
452  if ( sc.isFailure() ) throw GaudiException( "Could not set Property", prop + " -> " + newLoc, sc );
453  }
454 
455  template <typename Out, typename In, typename Tr>
457  const std::vector<std::string>& newLocs ) {
460  ss << '[', newLocs, ", ", []( std::ostream & os, const auto& i ) -> auto& { return os << "'" << i << "'"; } )
461  << ']';
462  auto sc = parent.setProperty( prop, ss.str() );
463  if ( sc.isFailure() ) throw GaudiException( "Could not set Property", prop + " -> " + ss.str(), sc );
464  }
465 
466  template <typename... Out, typename... In, typename Traits_>
467  class DataHandleMixin<std::tuple<Out...>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
468  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
469 
470  template <typename IArgs, typename OArgs, std::size_t... I, std::size_t... J>
471  DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const IArgs& inputs, std::index_sequence<I...>,
472  const OArgs& outputs, std::index_sequence<J...> )
473  : BaseClass_t<Traits_>( std::move( name ), pSvcLocator )
474  , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... )
475  , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
476  // make sure this algorithm is seen as reentrant by Gaudi
477  this->setProperty( "Cardinality", 0 ).ignore();
478  }
479 
480  public:
481  constexpr static std::size_t N_in = sizeof...( In );
482  constexpr static std::size_t N_out = sizeof...( Out );
483 
486 
487  // generic constructor: N -> M
489  const std::array<KeyValue, N_out>& outputs )
490  : DataHandleMixin( std::move( name ), pSvcLocator, inputs, std::index_sequence_for<In...>{}, outputs,
491  std::index_sequence_for<Out...>{} ) {}
492 
493  // special cases: forward to the generic case...
494  // 1 -> 1
496  : DataHandleMixin( std::move( name ), locator, std::array<KeyValue, 1>{input},
498  // 1 -> N
500  const std::array<KeyValue, N_out>& outputs )
501  : DataHandleMixin( std::move( name ), locator, std::array<KeyValue, 1>{input}, outputs ) {}
502  // N -> 1
504  const KeyValue& output )
505  : DataHandleMixin( std::move( name ), locator, inputs, std::array<KeyValue, 1>{output} ) {}
506 
507  template <std::size_t N = 0>
508  decltype( auto ) inputLocation() const {
509  return getKey( std::get<N>( m_inputs ) );
510  }
511  template <typename T>
512  decltype( auto ) inputLocation() const {
513  return getKey( std::get<details::InputHandle_t<Traits_, std::decay_t<T>>>( m_inputs ) );
514  }
515  constexpr unsigned int inputLocationSize() const { return N_in; }
516 
517  template <std::size_t N = 0>
518  decltype( auto ) outputLocation() const {
519  return getKey( std::get<N>( m_outputs ) );
520  }
521  template <typename T>
522  decltype( auto ) outputLocation() const {
523  return getKey( std::get<details::OutputHandle_t<Traits_, std::decay_t<T>>>( m_outputs ) );
524  }
525  constexpr unsigned int outputLocationSize() const { return N_out; }
526 
527  protected:
528  bool isReEntrant() const override { return true; }
529 
532  };
533 
534  template <typename Traits_>
535  class DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> : public BaseClass_t<Traits_> {
536  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
537 
538  public:
540  : BaseClass_t<Traits_>( std::move( name ), pSvcLocator ) {
541  // make sure this algorithm is seen as reentrant by Gaudi
542  this->setProperty( "Cardinality", 0 ).ignore();
543  }
544 
545  protected:
546  bool isReEntrant() const override { return true; }
547 
549  };
550 
551  template <typename... In, typename Traits_>
552  class DataHandleMixin<std::tuple<>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
553  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
554 
555  template <typename IArgs, std::size_t... I>
556  DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const IArgs& inputs, std::index_sequence<I...> )
557  : BaseClass_t<Traits_>( std::move( name ), pSvcLocator )
558  , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... ) {
559  // make sure this algorithm is seen as reentrant by Gaudi
560  this->setProperty( "Cardinality", 0 ).ignore();
561  }
562 
563  public:
566  constexpr static std::size_t N_in = sizeof...( In );
567 
568  // generic constructor: N -> 0
570  : DataHandleMixin( std::move( name ), pSvcLocator, inputs, std::index_sequence_for<In...>{} ) {}
571 
572  // special cases: forward to the generic case...
573  // 1 -> 0
575  : DataHandleMixin( std::move( name ), locator, std::array<KeyValue, 1>{input} ) {}
576 
577  template <std::size_t N = 0>
578  decltype( auto ) inputLocation() const {
579  return getKey( std::get<N>( m_inputs ) );
580  }
581  template <typename T>
582  decltype( auto ) inputLocation() const {
583  return getKey( std::get<details::InputHandle_t<Traits_, std::decay_t<T>>>( m_inputs ) );
584  }
585  constexpr unsigned int inputLocationSize() const { return N_in; }
586 
587  protected:
588  bool isReEntrant() const override { return true; }
589 
591  };
592 
593  template <typename... Out, typename Traits_>
594  class DataHandleMixin<std::tuple<Out...>, std::tuple<>, Traits_> : public BaseClass_t<Traits_> {
595  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
596 
597  template <typename OArgs, std::size_t... J>
598  DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const OArgs& outputs, std::index_sequence<J...> )
599  : BaseClass_t<Traits_>( std::move( name ), pSvcLocator )
600  , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
601  // make sure this algorithm is seen as reentrant by Gaudi
602  this->setProperty( "Cardinality", 0 ).ignore();
603  }
604 
605  public:
606  constexpr static std::size_t N_out = sizeof...( Out );
609 
610  // generic constructor: 0 -> N
612  : DataHandleMixin( std::move( name ), pSvcLocator, outputs, std::index_sequence_for<Out...>{} ) {}
613 
614  // 0 -> 1
616  : DataHandleMixin( std::move( name ), locator, std::array<KeyValue, 1>{output} ) {}
617 
618  template <std::size_t N = 0>
619  decltype( auto ) outputLocation() const {
620  return getKey( std::get<N>( m_outputs ) );
621  }
622  constexpr unsigned int outputLocationSize() const { return N_out; }
623 
624  protected:
625  bool isReEntrant() const override { return true; }
626 
628  };
629 
631  template <typename Fun, typename Container, typename... Args>
632  constexpr void applyPostProcessing( const Fun&, Container&, Args... ) {
633  static_assert( sizeof...( Args ) == 0, "Args should not be used!" );
634  }
635 
636  template <typename Fun, typename Container>
637  auto applyPostProcessing( const Fun& fun, Container& c ) -> decltype( fun.postprocess( c ), void() ) {
638  fun.postprocess( c );
639  }
640 
641 } // namespace Gaudi::Functional::details
642 
643 #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.
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_in > &inputs, const std::array< KeyValue, N_out > &outputs)
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >)
#define UNLIKELY(x)
Definition: Kernel.h:106
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
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:35
StatusCode setProperty(const Gaudi::Details::PropertyBase &p) override
set the property form another property
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:308
Header file for class GaudiAlgorithm.
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_out > &outputs)
T * put(std::unique_ptr< T > object) const
Register object in transient store.
auto operator()(const Handle< Gaudi::NamedRange_< I, IT >> &h) -> const In
static auto apply(const Algorithm &algo, Handles &handles)
void push_back(Container &c, const Value &v, std::false_type)
STL namespace.
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_in > &inputs)
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:34
auto operator()(const Handle< Gaudi::Range_< I, IT >> &h) -> const In
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:40
STL class.
typename Tr::template InputHandle< T > InputHandle_t
DataObjectHandle.h GaudiKernel/DataObjectHandle.h.
Definition: AlgTool.h:36
decltype(auto) verifySizes(Args &... args)
Verify the data container sizes have the same sizes.
decltype(auto) const_range(Args &&... args)
Zips multiple containers together to form a single const range.
typename filter_evtcontext_t< In... >::type filter_evtcontext
T & deref_if(T *const t, std::true_type)
bool PyHelper() setProperty(IInterface *p, char *name, char *value)
Definition: Bootstrap.cpp:243
typename Tr::template OutputHandle< T > OutputHandle_t
GAUDI_API const EventContext & currentContext()
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:73
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
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input, const KeyValue &output)
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
Alias for backward compatibility.
Definition: Algorithm.h:58
T size(T... args)
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const OArgs &outputs, std::index_sequence< J... >)
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)
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)
std::conditional_t< is_pointer, ptr_t, ref_t > ret_t
std::remove_pointer_t< typename Container::value_type > c_remove_ptr_t
Useful class for representation of "sequence" of the objects through the range of valid iterators.
Definition: Range.h:95
DataHandleMixin(std::string name, ISvcLocator *locator, const std::array< KeyValue, N_in > &inputs, const KeyValue &output)
STL class.
auto operator()(Container &c, Value &&v) const -> decltype(c.push_back(v))
constexpr static const auto FAILURE
Definition: StatusCode.h:101
const Gaudi::Algorithm & parent
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.
constexpr struct ranges::Gaudi::Functional::details::deref_t deref
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input, const std::array< KeyValue, N_out > &outputs)
auto getKey(const Handle &h) -> decltype(h.objKey())
friend bool operator!=(const iterator &lhs, const iterator &rhs)
const In & operator()(const In *in) const
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
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >, const OArgs &outputs, std::index_sequence< J... >)
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