The Gaudi Framework  v36r2 (27905625)
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__ < 11 ) || 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 
47 // temporary hack to help in transition to updated constructor
48 // allows to write code which is forward and backwards compatible
49 #define GAUDI_FUNCTIONAL_CONSTRUCTOR_USES_TUPLE
50 
52 
53  // CRJ : Stuff for zipping
54  namespace zip {
55 
57  template <typename OS, typename Arg>
58  void printSizes( OS& out, Arg&& arg ) {
59  out << "SizeOf'" << System::typeinfoName( typeid( Arg ) ) << "'=" << std::forward<Arg>( arg ).size();
60  }
61 
63  template <typename OS, typename Arg, typename... Args>
64  void printSizes( OS& out, Arg&& arg, Args&&... args ) {
65  printSizes( out, arg );
66  out << ", ";
67  printSizes( out, args... );
68  }
69 
71  template <typename A>
72  inline bool check_sizes( const A& ) noexcept {
73  return true;
74  }
75 
77  template <typename A, typename B>
78  inline bool check_sizes( const A& a, const B& b ) noexcept {
79  return a.size() == b.size();
80  }
81 
83  template <typename A, typename B, typename... C>
84  inline bool check_sizes( const A& a, const B& b, const C&... c ) noexcept {
85  return ( check_sizes( a, b ) && check_sizes( b, c... ) );
86  }
87 
89  template <typename... Args>
90  inline decltype( auto ) verifySizes( Args&... args ) {
91  if ( UNLIKELY( !check_sizes( args... ) ) ) {
92  std::ostringstream mess;
93  mess << "Zipped containers have different sizes : ";
94  printSizes( mess, args... );
95  throw GaudiException( mess.str(), "Gaudi::Functional::details::zip::verifySizes", StatusCode::FAILURE );
96  }
97  }
98 
100  template <typename... Args>
101  inline decltype( auto ) range( Args&&... args ) {
102 #ifndef NDEBUG
103  verifySizes( args... );
104 #endif
105  return ranges::views::zip( std::forward<Args>( args )... );
106  }
107 
109  template <typename... Args>
110  inline decltype( auto ) const_range( Args&&... args ) {
111 #ifndef NDEBUG
112  verifySizes( args... );
113 #endif
114  return ranges::views::const_( ranges::views::zip( std::forward<Args>( args )... ) );
115  }
116  } // namespace zip
117 
119  namespace details2 {
120  // note: boost::optional in boost 1.66 does not have 'has_value()'...
121  // that requires boost 1.68 or later... so for now, use operator bool() instead ;-(
122  template <typename T>
123  using is_optional_ = decltype( bool{std::declval<T>()}, std::declval<T>().value() );
124  } // namespace details2
125  template <typename Arg>
126  constexpr bool is_optional_v = Gaudi::cpp17::is_detected_v<details2::is_optional_, Arg>;
127 
128  template <typename Arg>
129  using require_is_optional = std::enable_if_t<is_optional_v<Arg>>;
130 
131  template <typename Arg>
132  using require_is_not_optional = std::enable_if_t<!is_optional_v<Arg>>;
133 
134  template <typename T>
135  using remove_optional_t = std::conditional_t<is_optional_v<T>, typename T::value_type, T>;
136 
137  constexpr struct invoke_optionally_t {
138  template <typename F, typename Arg, typename = require_is_not_optional<Arg>>
139  decltype( auto ) operator()( F&& f, Arg&& arg ) const {
140  return std::invoke( std::forward<F>( f ), std::forward<Arg>( arg ) );
141  }
142  template <typename F, typename Arg, typename = require_is_optional<Arg>>
143  void operator()( F&& f, Arg&& arg ) const {
144  if ( arg ) std::invoke( std::forward<F>( f ), *std::forward<Arg>( arg ) );
145  }
148 
149  template <typename Value, std::size_t... I>
150  auto get_values_helper( std::index_sequence<I...> ) {
151  return std::make_tuple( ( (void)I, Value{} )... );
152  }
153 
154  template <typename Value, auto N>
155  using RepeatValues_ = decltype( get_values_helper<Value>( std::make_index_sequence<N>() ) );
156 
158 
159  template <typename Out1, typename Out2,
160  typename = std::enable_if_t<std::is_constructible_v<Out1, Out2> && std::is_base_of_v<DataObject, Out1>>>
161  auto put( const DataObjectHandle<Out1>& out_handle, Out2&& out ) {
162  return out_handle.put( std::make_unique<Out1>( std::forward<Out2>( out ) ) );
163  }
164 
165  template <typename Out1, typename Out2, typename = std::enable_if_t<std::is_constructible_v<Out1, Out2>>>
166  auto put( const DataObjectHandle<AnyDataWrapper<Out1>>& out_handle, Out2&& out ) {
167  return out_handle.put( std::forward<Out2>( out ) );
168  }
169 
170  // optional put
171  template <typename OutHandle, typename OptOut, typename = require_is_optional<OptOut>>
172  void put( const OutHandle& out_handle, OptOut&& out ) {
173  if ( out ) put( out_handle, *std::forward<OptOut>( out ) );
174  }
176  // adapt to differences between eg. std::vector (which has push_back) and KeyedContainer (which has insert)
177  // adapt to getting a T, and a container wanting T* by doing new T{ std::move(out) }
178  // adapt to getting a optional<T>
179 
180  constexpr struct insert_t {
181  // for Container<T*>, return T
182  template <typename Container>
183  using c_remove_ptr_t = std::remove_pointer_t<typename Container::value_type>;
184 
185  template <typename Container, typename Value>
186  auto operator()( Container& c, Value&& v ) const -> decltype( c.push_back( v ) ) {
187  return c.push_back( std::forward<Value>( v ) );
188  }
189 
190  template <typename Container, typename Value>
191  auto operator()( Container& c, Value&& v ) const -> decltype( c.insert( v ) ) {
192  return c.insert( std::forward<Value>( v ) );
193  }
194 
195  // Container<T*> with T&& as argument
196  template <typename Container, typename Value,
197  typename = std::enable_if_t<std::is_pointer_v<typename Container::value_type>>,
198  typename = std::enable_if_t<std::is_convertible_v<Value, c_remove_ptr_t<Container>>>>
199  auto operator()( Container& c, Value&& v ) const {
200  return operator()( c, new c_remove_ptr_t<Container>{std::forward<Value>( v )} );
201  }
202 
203  } insert{};
204 
206 
207  constexpr struct deref_t {
208  template <typename In, typename = std::enable_if_t<!std::is_pointer_v<In>>>
209  const In& operator()( const In& in ) const {
210  return in;
211  }
212 
213  template <typename In, typename = std::enable_if_t<!std::is_pointer_v<std::decay_t<In>>>>
214  In operator()( In&& in ) const {
215  return std::forward<In>( in );
216  }
217 
218  template <typename In>
219  const In& operator()( const In* in ) const {
220  assert( in != nullptr );
221  return *in;
222  }
223  } deref{};
224 
226  // if Container is a pointer, then we're optional items
227  namespace details2 {
228  template <typename T>
230 
231  template <typename T, typename IT>
233 
234  template <typename T, typename IT>
236 
237  template <typename T>
238  constexpr static bool is_gaudi_range_v = is_gaudi_range<T>::value;
239 
240  template <typename Container, typename Value>
241  void push_back( Container& c, const Value& v, std::true_type ) {
242  c.push_back( v );
243  }
244  template <typename Container, typename Value>
245  void push_back( Container& c, const Value& v, std::false_type ) {
246  c.push_back( &v );
247  }
248 
249  template <typename In>
251  template <template <typename> class Handle, typename I, typename = std::enable_if_t<std::is_convertible_v<I, In>>>
252  auto operator()( const Handle<I>& h ) -> const In& {
253  return *h.get();
254  }
255  template <template <typename> class Handle, typename I, typename IT>
256  auto operator()( const Handle<Gaudi::Range_<I, IT>>& h ) -> const In {
257  return h.get();
258  }
259  template <template <typename> class Handle, typename I, typename IT>
260  auto operator()( const Handle<Gaudi::NamedRange_<I, IT>>& h ) -> const In {
261  return h.get();
262  }
263  template <template <typename> class Handle, typename I,
264  typename = std::enable_if_t<std::is_convertible_v<I*, In>>>
265  auto operator()( const Handle<I>& h ) -> const In {
266  return h.getIfExists();
267  } // In is-a pointer
268  };
269 
270  template <typename T>
271  T* deref_if( T* const t, std::false_type ) {
272  return t;
273  }
274  template <typename T>
275  T& deref_if( T* const t, std::true_type ) {
276  return *t;
277  }
278  } // namespace details2
279 
280  template <typename Container>
282  static constexpr bool is_pointer = std::is_pointer_v<Container>;
283  static constexpr bool is_range = details2::is_gaudi_range_v<Container>;
284  using val_t = std::add_const_t<std::remove_pointer_t<Container>>;
285  using ptr_t = std::add_pointer_t<val_t>;
286  using ref_t = std::add_lvalue_reference_t<val_t>;
289 
290  public:
291  using value_type = std::conditional_t<is_pointer, ptr_t, val_t>;
292  using size_type = typename ContainerVector::size_type;
293  class iterator {
294  using it_t = typename ContainerVector::const_iterator;
296  friend class vector_of_const_;
297  iterator( it_t iter ) : m_i( iter ) {}
298  using ret_t = std::conditional_t<is_pointer, ptr_t, ref_t>;
299 
300  public:
301  using iterator_category = typename it_t::iterator_category;
302  using value_type = typename it_t::iterator_category;
303  using reference = typename it_t::reference;
304  using pointer = typename it_t::pointer;
305  using difference_type = typename it_t::difference_type;
306 
307  friend bool operator!=( const iterator& lhs, const iterator& rhs ) { return lhs.m_i != rhs.m_i; }
308  friend bool operator==( const iterator& lhs, const iterator& rhs ) { return lhs.m_i == rhs.m_i; }
309  friend auto operator-( const iterator& lhs, const iterator& rhs ) { return lhs.m_i - rhs.m_i; }
310  ret_t operator*() const {
311  if constexpr ( is_range ) {
312  return *m_i;
313  } else {
314  return details2::deref_if( *m_i, std::bool_constant<!is_pointer>{} );
315  }
316  }
318  ++m_i;
319  return *this;
320  }
322  --m_i;
323  return *this;
324  }
325  bool is_null() const { return !*m_i; }
326  explicit operator bool() const { return !is_null(); }
327  };
328  vector_of_const_() = default;
329  void reserve( size_type size ) { m_containers.reserve( size ); }
330  template <typename T> // , typename = std::is_convertible<T,std::conditional_t<is_pointer,ptr_t,val_t>>
331  void push_back( T&& container ) {
332  details2::push_back( m_containers, std::forward<T>( container ),
333  std::bool_constant < is_pointer or is_range > {} );
334  } // note: does not copy its argument, so we're not really a container...
335  iterator begin() const { return m_containers.begin(); }
336  iterator end() const { return m_containers.end(); }
337  size_type size() const { return m_containers.size(); }
338 
339  template <typename X = Container>
340  std::enable_if_t<!std::is_pointer_v<X>, ref_t> operator[]( size_type i ) const {
341  return *m_containers[i];
342  }
343 
344  template <typename X = Container>
345  std::enable_if_t<std::is_pointer_v<X>, ptr_t> operator[]( size_type i ) const {
346  return m_containers[i];
347  }
348 
349  template <typename X = Container>
350  std::enable_if_t<!std::is_pointer_v<X>, ref_t> at( size_type i ) const {
351  return *m_containers[i];
352  }
353 
354  template <typename X = Container>
355  std::enable_if_t<std::is_pointer_v<X>, ptr_t> at( size_type i ) const {
356  return m_containers[i];
357  }
358 
359  bool is_null( size_type i ) const { return !m_containers[i]; }
360  };
361 
363  namespace detail2 { // utilities for detected_or_t{,_} usage
364  template <typename Tr>
365  using BaseClass_t = typename Tr::BaseClass;
366  template <typename Tr, typename T>
367  using OutputHandle_t = typename Tr::template OutputHandle<T>;
368  template <typename Tr, typename T>
369  using InputHandle_t = typename Tr::template InputHandle<T>;
370  } // namespace detail2
371 
372  // check whether Traits::BaseClass is a valid type,
373  // if so, define BaseClass_t<Traits> as being Traits::BaseClass
374  // else define as being GaudiAlgorithm
375  template <typename Tr>
377 
378  // check whether Traits::{Input,Output}Handle<T> is a valid type,
379  // if so, define {Input,Output}Handle_t<Traits,T> as being Traits::{Input,Output}Handle<T>
380  // else define as being DataObject{Read,,Write}Handle<T>
381  template <typename Tr, typename T>
383  template <typename Tr, typename T>
385 
386  template <typename Traits>
387  inline constexpr bool isLegacy =
388  std::is_base_of_v<Gaudi::details::LegacyAlgorithmAdapter, details::BaseClass_t<Traits>>;
389 
391 
392  template <typename Handles>
394  Handles handles;
395  handles.reserve( init.size() );
397  init.begin(), init.end(),
398  std::back_inserter( handles ), [&]( const std::string& loc ) -> typename Handles::value_type {
399  return {loc, owner};
400  } );
401  return handles;
402  }
403 
404  template <typename Handle, typename Algo>
405  auto get( const Handle& handle, const Algo&, const EventContext& )
406  -> decltype( details::deref( handle.get() ) ) // make it SFINAE friendly...
407  {
408  return details::deref( handle.get() );
409  }
410 
411  template <typename Handle>
412  auto getKey( const Handle& h ) -> decltype( h.objKey() ) {
413  return h.objKey();
414  }
415 
417  // given a pack, return a corresponding tuple
418  template <typename... In>
420  using type = std::tuple<In...>;
421 
422  static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
423  "EventContext can only appear as first argument" );
424 
425  template <typename Algorithm, typename Handles>
426  static auto apply( const Algorithm& algo, Handles& handles ) {
427  return std::apply(
428  [&]( const auto&... handle ) { return algo( get( handle, algo, Gaudi::Hive::currentContext() )... ); },
429  handles );
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( get( handle, algo, ctx )... ); }, handles );
434  }
435  };
436 
437  // except when it starts with EventContext, then drop it
438  template <typename... In>
440  using type = std::tuple<In...>;
441 
442  static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
443  "EventContext can only appear as first argument" );
444 
445  template <typename Algorithm, typename Handles>
446  static auto apply( const Algorithm& algo, const EventContext& ctx, Handles& handles ) {
447  return std::apply( [&]( const auto&... handle ) { return algo( ctx, get( handle, algo, ctx )... ); }, handles );
448  }
449 
450  template <typename Algorithm, typename Handles>
451  static auto apply( const Algorithm& algo, Handles& handles ) {
452  return apply( algo, Gaudi::Hive::currentContext(), handles );
453  }
454  };
455 
456  template <typename... In>
458 
459  template <typename OutputSpec, typename InputSpec, typename Traits_>
461 
462  template <typename Out, typename In, typename Tr>
464  const std::string& newLoc ) {
465  auto sc = parent.setProperty( prop, newLoc );
466  if ( sc.isFailure() ) throw GaudiException( "Could not set Property", prop + " -> " + newLoc, sc );
467  }
468 
469  template <typename Out, typename In, typename Tr>
471  const std::vector<std::string>& newLocs ) {
474  ss << '[', newLocs, ", ", []( std::ostream & os, const auto& i ) -> auto& { return os << "'" << i << "'"; } )
475  << ']';
476  auto sc = parent.setProperty( prop, ss.str() );
477  if ( sc.isFailure() ) throw GaudiException( "Could not set Property", prop + " -> " + ss.str(), sc );
478  }
479 
480  template <typename... Out, typename... In, typename Traits_>
481  class DataHandleMixin<std::tuple<Out...>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
482  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
483 
484  template <typename IArgs, typename OArgs, std::size_t... I, std::size_t... J>
485  DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const IArgs& inputs, std::index_sequence<I...>,
486  const OArgs& outputs, std::index_sequence<J...> )
487  : BaseClass_t<Traits_>( std::move( name ), pSvcLocator )
488  , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... )
489  , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
490  // make sure this algorithm is seen as reentrant by Gaudi
491  this->setProperty( "Cardinality", 0 ).ignore();
492  }
493 
494  public:
495  constexpr static std::size_t N_in = sizeof...( In );
496  constexpr static std::size_t N_out = sizeof...( Out );
497 
500 
501  // generic constructor: N -> M
503  RepeatValues_<KeyValue, N_out> const& outputs )
504  : DataHandleMixin( std::move( name ), pSvcLocator, inputs, std::index_sequence_for<In...>{}, outputs,
505  std::index_sequence_for<Out...>{} ) {}
506 
507  // special cases: forward to the generic case...
508  // 1 -> 1
510  : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ),
511  std::forward_as_tuple( output ) ) {}
512  // 1 -> N
514  RepeatValues_<KeyValue, N_out> const& outputs )
515  : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ), outputs ) {}
516  // N -> 1
518  const KeyValue& output )
519  : DataHandleMixin( std::move( name ), locator, inputs, std::forward_as_tuple( output ) ) {}
520 
521  template <std::size_t N = 0>
522  decltype( auto ) inputLocation() const {
523  return getKey( std::get<N>( m_inputs ) );
524  }
525  template <typename T>
526  decltype( auto ) inputLocation() const {
527  return getKey( std::get<details::InputHandle_t<Traits_, std::decay_t<T>>>( m_inputs ) );
528  }
529  constexpr unsigned int inputLocationSize() const { return N_in; }
530 
531  template <std::size_t N = 0>
532  decltype( auto ) outputLocation() const {
533  return getKey( std::get<N>( m_outputs ) );
534  }
535  template <typename T>
536  decltype( auto ) outputLocation() const {
537  return getKey( std::get<details::OutputHandle_t<Traits_, std::decay_t<T>>>( m_outputs ) );
538  }
539  constexpr unsigned int outputLocationSize() const { return N_out; }
540 
541  protected:
542  bool isReEntrant() const override { return true; }
543 
546  };
547 
548  template <typename Traits_>
549  class DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> : public BaseClass_t<Traits_> {
550  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
551 
552  public:
556  : BaseClass_t<Traits_>( std::move( name ), pSvcLocator ) {
557  // make sure this algorithm is seen as reentrant by Gaudi
558  this->setProperty( "Cardinality", 0 ).ignore();
559  }
560 
561  protected:
562  bool isReEntrant() const override { return true; }
563 
565  };
566 
567  template <typename... In, typename Traits_>
568  class DataHandleMixin<std::tuple<>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
569  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
570 
571  template <typename IArgs, std::size_t... I>
572  DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const IArgs& inputs, std::index_sequence<I...> )
573  : BaseClass_t<Traits_>( std::move( name ), pSvcLocator )
574  , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... ) {
575  // make sure this algorithm is seen as reentrant by Gaudi
576  this->setProperty( "Cardinality", 0 ).ignore();
577  }
578 
579  public:
582  constexpr static std::size_t N_in = sizeof...( In );
583 
584  // generic constructor: N -> 0
586  : DataHandleMixin( std::move( name ), pSvcLocator, inputs, std::index_sequence_for<In...>{} ) {}
587 
588  // special cases: forward to the generic case...
589  // 1 -> 0
591  : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ) ) {}
592 
593  template <std::size_t N = 0>
594  decltype( auto ) inputLocation() const {
595  return getKey( std::get<N>( m_inputs ) );
596  }
597  template <typename T>
598  decltype( auto ) inputLocation() const {
599  return getKey( std::get<details::InputHandle_t<Traits_, std::decay_t<T>>>( m_inputs ) );
600  }
601  constexpr unsigned int inputLocationSize() const { return N_in; }
602 
603  protected:
604  bool isReEntrant() const override { return true; }
605 
607  };
608 
609  template <typename Traits_>
610  class DataHandleMixin<std::tuple<void>, std::tuple<>, Traits_>
611  : public DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> {
612  public:
614  };
615 
616  template <typename... Out, typename Traits_>
617  class DataHandleMixin<std::tuple<Out...>, std::tuple<>, Traits_> : public BaseClass_t<Traits_> {
618  static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
619 
620  template <typename OArgs, std::size_t... J>
621  DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const OArgs& outputs, std::index_sequence<J...> )
622  : BaseClass_t<Traits_>( std::move( name ), pSvcLocator )
623  , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
624  // make sure this algorithm is seen as reentrant by Gaudi
625  this->setProperty( "Cardinality", 0 ).ignore();
626  }
627 
628  public:
629  constexpr static std::size_t N_out = sizeof...( Out );
632 
633  // generic constructor: 0 -> N
635  : DataHandleMixin( std::move( name ), pSvcLocator, outputs, std::index_sequence_for<Out...>{} ) {}
636 
637  // 0 -> 1
639  : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( output ) ) {}
640 
641  template <std::size_t N = 0>
642  decltype( auto ) outputLocation() const {
643  return getKey( std::get<N>( m_outputs ) );
644  }
645  constexpr unsigned int outputLocationSize() const { return N_out; }
646 
647  protected:
648  bool isReEntrant() const override { return true; }
649 
651  };
652 
654  template <typename Fun, typename Container, typename... Args>
655  constexpr void applyPostProcessing( const Fun&, Container&, Args... ) {
656  static_assert( sizeof...( Args ) == 0, "Args should not be used!" );
657  }
658 
659  template <typename Fun, typename Container>
660  auto applyPostProcessing( const Fun& fun, Container& c ) -> decltype( fun.postprocess( c ), void() ) {
661  fun.postprocess( c );
662  }
663 
664 } // namespace Gaudi::Functional::details
665 
666 #endif
IDataHandleHolder
Definition: IDataHandleHolder.h:24
Gaudi::Functional::details::detail2::BaseClass_t
typename Tr::BaseClass BaseClass_t
Definition: FunctionalDetails.h:365
Gaudi::Functional::details::details2::is_optional_
decltype(bool{std::declval< T >()}, std::declval< T >().value()) is_optional_
Definition: FunctionalDetails.h:123
Gaudi::Functional::details::insert_t::operator()
auto operator()(Container &c, Value &&v) const
Definition: FunctionalDetails.h:199
Gaudi::Functional::details::invoke_optionally_t
Definition: FunctionalDetails.h:137
Gaudi::Functional::details::vector_of_const_::operator[]
std::enable_if_t< std::is_pointer_v< X >, ptr_t > operator[](size_type i) const
Definition: FunctionalDetails.h:345
Gaudi::Functional::details::vector_of_const_::val_t
std::add_const_t< std::remove_pointer_t< Container > > val_t
Definition: FunctionalDetails.h:284
Gaudi::Functional::details::vector_of_const_::iterator::is_null
bool is_null() const
Definition: FunctionalDetails.h:325
Gaudi::Functional::details::vector_of_const_::iterator
Definition: FunctionalDetails.h:293
Gaudi::Functional::details::deref_t::operator()
const In & operator()(const In *in) const
Definition: FunctionalDetails.h:219
std::is_same
Gaudi::Functional::details::vector_of_const_::iterator::operator*
ret_t operator*() const
Definition: FunctionalDetails.h:310
std::make_tuple
T make_tuple(T... args)
std::false_type
std::string
STL class.
details::size
constexpr auto size(const T &, Args &&...) noexcept
Definition: AnyDataWrapper.h:22
setProperty
bool PyHelper() setProperty(IInterface *p, char *name, char *value)
Definition: Bootstrap.cpp:242
Gaudi::Functional::details::DataHandleMixin< std::tuple<>, std::tuple< In... >, Traits_ >::m_inputs
std::tuple< details::InputHandle_t< Traits_, In >... > m_inputs
Definition: FunctionalDetails.h:606
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple< In... >, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input, const KeyValue &output)
Definition: FunctionalDetails.h:509
Gaudi::Functional::details
Definition: Consumer.h:21
Gaudi::NamedRange_
Definition: NamedRange.h:52
std::move
T move(T... args)
Gaudi::Functional::details::require_is_not_optional
std::enable_if_t<!is_optional_v< Arg > > require_is_not_optional
Definition: FunctionalDetails.h:132
Gaudi::Hive::currentContext
GAUDI_API const EventContext & currentContext()
Definition: ThreadLocalContext.cpp:30
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple< In... >, Traits_ >::isReEntrant
bool isReEntrant() const override
Definition: FunctionalDetails.h:542
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple<>, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &output)
Definition: FunctionalDetails.h:638
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple<>, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_out > const &outputs)
Definition: FunctionalDetails.h:634
Gaudi::Functional::details::make_vector_of_handles
Handles make_vector_of_handles(IDataHandleHolder *owner, const std::vector< std::string > &init)
Definition: FunctionalDetails.h:393
Gaudi::Functional::details::invoke_optionally
constexpr struct Gaudi::Functional::details::invoke_optionally_t invoke_optionally
Gaudi::Functional::details::vector_of_const_::iterator::operator--
iterator & operator--()
Definition: FunctionalDetails.h:321
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple<>, Traits_ >::isReEntrant
bool isReEntrant() const override
Definition: FunctionalDetails.h:648
std::pair< std::string, std::string >
std::vector::reserve
T reserve(T... args)
GaudiException.h
Gaudi::Functional::details::insert_t::operator()
auto operator()(Container &c, Value &&v) const -> decltype(c.push_back(v))
Definition: FunctionalDetails.h:186
Gaudi::Functional::details::isLegacy
constexpr bool isLegacy
Definition: FunctionalDetails.h:387
Gaudi::Functional::details::DataHandleMixin< std::tuple<>, std::tuple< In... >, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >)
Definition: FunctionalDetails.h:572
std::vector< std::conditional_t< is_range, std::remove_const_t< val_t >, ptr_t > >
std::string::size
T size(T... args)
Gaudi::Functional::details::deref_t
Definition: FunctionalDetails.h:207
ISvcLocator
Definition: ISvcLocator.h:46
std::back_inserter
T back_inserter(T... args)
GaudiException
Definition: GaudiException.h:31
Gaudi::Functional::details::vector_of_const_::m_containers
ContainerVector m_containers
Definition: FunctionalDetails.h:288
Algorithm.h
Gaudi::Functional::details::details2::get_from_handle::operator()
auto operator()(const Handle< I > &h) -> const In &
Definition: FunctionalDetails.h:252
Gaudi::Functional::details::vector_of_const_::iterator::iterator_category
typename it_t::iterator_category iterator_category
Definition: FunctionalDetails.h:301
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple< In... >, Traits_ >::m_inputs
std::tuple< details::InputHandle_t< Traits_, In >... > m_inputs
Definition: FunctionalDetails.h:544
Gaudi::Functional::details::vector_of_const_::reserve
void reserve(size_type size)
Definition: FunctionalDetails.h:329
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple<>, Traits_ >::outputLocationSize
constexpr unsigned int outputLocationSize() const
Definition: FunctionalDetails.h:645
Gaudi::Functional::details::DataHandleMixin< std::tuple<>, std::tuple<>, Traits_ >::isReEntrant
bool isReEntrant() const override
Definition: FunctionalDetails.h:562
Gaudi::Functional::details::vector_of_const_::size_type
typename ContainerVector::size_type size_type
Definition: FunctionalDetails.h:292
std::tuple
Gaudi::Functional::details::zip::const_range
decltype(auto) const_range(Args &&... args)
Zips multiple containers together to form a single const range.
Definition: FunctionalDetails.h:110
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple< In... >, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *locator, RepeatValues_< KeyValue, N_in > const &inputs, const KeyValue &output)
Definition: FunctionalDetails.h:517
gaudirun.c
c
Definition: gaudirun.py:509
ranges::views
Definition: FunctionalDetails.h:33
System::typeinfoName
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:308
Gaudi::Functional::details::vector_of_const_
Definition: FunctionalDetails.h:281
Gaudi::Functional::details::vector_of_const_::operator[]
std::enable_if_t<!std::is_pointer_v< X >, ref_t > operator[](size_type i) const
Definition: FunctionalDetails.h:340
gaudirun.output
output
Definition: gaudirun.py:506
Gaudi::Functional::details::vector_of_const_::iterator::operator-
friend auto operator-(const iterator &lhs, const iterator &rhs)
Definition: FunctionalDetails.h:309
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple< In... >, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >, const OArgs &outputs, std::index_sequence< J... >)
Definition: FunctionalDetails.h:485
Gaudi::Functional::details::get_values_helper
auto get_values_helper(std::index_sequence< I... >)
Definition: FunctionalDetails.h:150
Gaudi::Functional::details::deref_t::operator()
In operator()(In &&in) const
Definition: FunctionalDetails.h:214
Gaudi::Functional::details::details2::get_from_handle::operator()
auto operator()(const Handle< Gaudi::Range_< I, IT >> &h) -> const In
Definition: FunctionalDetails.h:256
DataObjectHandle
DataObjectHandle.h GaudiKernel/DataObjectHandle.h.
Definition: AlgTool.h:36
Gaudi::Functional::details::vector_of_const_::iterator::iterator
iterator(it_t iter)
Definition: FunctionalDetails.h:297
Gaudi::Functional::details::filter_evtcontext_t< EventContext, In... >::apply
static auto apply(const Algorithm &algo, Handles &handles)
Definition: FunctionalDetails.h:451
Gaudi::Functional::details::insert_t
Definition: FunctionalDetails.h:180
Gaudi::Functional::details::insert_t::c_remove_ptr_t
std::remove_pointer_t< typename Container::value_type > c_remove_ptr_t
Definition: FunctionalDetails.h:183
bug_34121.t
t
Definition: bug_34121.py:30
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple< In... >, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_in > const &inputs, RepeatValues_< KeyValue, N_out > const &outputs)
Definition: FunctionalDetails.h:502
Gaudi::Functional::details::vector_of_const_::at
std::enable_if_t<!std::is_pointer_v< X >, ref_t > at(size_type i) const
Definition: FunctionalDetails.h:350
Gaudi::Functional::details::get
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
Definition: FunctionalDetails.h:405
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple< In... >, Traits_ >::inputLocationSize
constexpr unsigned int inputLocationSize() const
Definition: FunctionalDetails.h:529
TimingHistograms.name
name
Definition: TimingHistograms.py:23
GaudiPython.Pythonizations.ctx
ctx
Definition: Pythonizations.py:566
Gaudi::Functional::details::zip::check_sizes
bool check_sizes(const A &a, const B &b, const C &... c) noexcept
Compare sizes of 3 or more containers.
Definition: FunctionalDetails.h:84
Gaudi::Functional::details::invoke_optionally_t::operator()
void operator()(F &&f, Arg &&arg) const
Definition: FunctionalDetails.h:143
Gaudi::Functional::details::filter_evtcontext_t< EventContext, In... >::apply
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
Definition: FunctionalDetails.h:446
Gaudi::Functional::details::vector_of_const_::iterator::m_i
it_t m_i
Definition: FunctionalDetails.h:295
std::ostream
STL class.
Gaudi::Functional::details::detail2::InputHandle_t
typename Tr::template InputHandle< T > InputHandle_t
Definition: FunctionalDetails.h:369
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple<>, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const OArgs &outputs, std::index_sequence< J... >)
Definition: FunctionalDetails.h:621
Gaudi::Functional::details::vector_of_const_::value_type
std::conditional_t< is_pointer, ptr_t, val_t > value_type
Definition: FunctionalDetails.h:291
Gaudi::cpp17::detected_or_t
typename details::detector< Default, void, Op, Args... >::type detected_or_t
Definition: detected.h:50
Gaudi::Algorithm
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:90
AlgSequencer.h
h
Definition: AlgSequencer.py:26
Gaudi::Functional::details::applyPostProcessing
auto applyPostProcessing(const Fun &fun, Container &c) -> decltype(fun.postprocess(c), void())
Definition: FunctionalDetails.h:660
Gaudi::Functional::details::InputHandle_t
Gaudi::cpp17::detected_or_t< DataObjectReadHandle< T >, detail2::InputHandle_t, Tr, T > InputHandle_t
Definition: FunctionalDetails.h:384
Gaudi::Functional::details::DataHandleMixin< std::tuple<>, std::tuple< In... >, Traits_ >::inputLocationSize
constexpr unsigned int inputLocationSize() const
Definition: FunctionalDetails.h:601
Gaudi::Functional::details::put
void put(const OutHandle &out_handle, OptOut &&out)
Definition: FunctionalDetails.h:172
Gaudi::Functional::details::filter_evtcontext_t::apply
static auto apply(const Algorithm &algo, Handles &handles)
Definition: FunctionalDetails.h:426
Gaudi::Functional::details::detail2::OutputHandle_t
typename Tr::template OutputHandle< T > OutputHandle_t
Definition: FunctionalDetails.h:367
Gaudi::Functional::details::deref
constexpr struct Gaudi::Functional::details::deref_t deref
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple<>, Traits_ >::m_outputs
std::tuple< details::OutputHandle_t< Traits_, Out >... > m_outputs
Definition: FunctionalDetails.h:650
Gaudi::Functional::details::vector_of_const_::iterator::operator++
iterator & operator++()
Definition: FunctionalDetails.h:317
Gaudi::Functional::details::vector_of_const_::at
std::enable_if_t< std::is_pointer_v< X >, ptr_t > at(size_type i) const
Definition: FunctionalDetails.h:355
Gaudi::Functional::details::require_is_optional
std::enable_if_t< is_optional_v< Arg > > require_is_optional
Definition: FunctionalDetails.h:129
AnyDataWrapper
Definition: AnyDataWrapper.h:34
Gaudi::Functional::details::vector_of_const_::push_back
void push_back(T &&container)
Definition: FunctionalDetails.h:331
std::transform
T transform(T... args)
Gaudi::Functional::details::updateHandleLocation
void updateHandleLocation(DataHandleMixin< Out, In, Tr > &parent, const std::string &prop, const std::string &newLoc)
Definition: FunctionalDetails.h:463
Gaudi
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
Gaudi::Functional::details::vector_of_const_::iterator::operator==
friend bool operator==(const iterator &lhs, const iterator &rhs)
Definition: FunctionalDetails.h:308
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple< In... >, Traits_ >::m_outputs
std::tuple< details::OutputHandle_t< Traits_, Out >... > m_outputs
Definition: FunctionalDetails.h:545
HistoDumpEx.v
v
Definition: HistoDumpEx.py:27
Gaudi::Functional::details::filter_evtcontext_t
Definition: FunctionalDetails.h:419
Gaudi::Functional::details::details2::is_gaudi_range
Definition: FunctionalDetails.h:229
Gaudi::Range_
Definition: Range.h:95
std::ostringstream
STL class.
Gaudi::Functional::details::DataHandleMixin< std::tuple<>, std::tuple< In... >, Traits_ >::isReEntrant
bool isReEntrant() const override
Definition: FunctionalDetails.h:604
Gaudi::Functional::details::DataHandleMixin< std::tuple<>, std::tuple<>, Traits_ >::m_inputs
std::tuple m_inputs
Definition: FunctionalDetails.h:564
gaudirun.type
type
Definition: gaudirun.py:154
ThreadLocalContext.h
Gaudi::Functional::details::deref_t::operator()
const In & operator()(const In &in) const
Definition: FunctionalDetails.h:209
DataObjectHandle::put
T * put(std::unique_ptr< T > object) const
Register object in transient store.
Definition: DataObjectHandle.h:175
Gaudi::Functional::details::zip::verifySizes
decltype(auto) verifySizes(Args &... args)
Verify the data container sizes have the same sizes.
Definition: FunctionalDetails.h:90
Gaudi::Functional::details::filter_evtcontext_t::apply
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
Definition: FunctionalDetails.h:432
Gaudi::Functional::details::details2::get_from_handle
Definition: FunctionalDetails.h:250
Gaudi::Functional::details::vector_of_const_::iterator::operator!=
friend bool operator!=(const iterator &lhs, const iterator &rhs)
Definition: FunctionalDetails.h:307
gaudirun.args
args
Definition: gaudirun.py:319
Gaudi::Functional::details::vector_of_const_::begin
iterator begin() const
Definition: FunctionalDetails.h:335
std::vector::begin
T begin(T... args)
GaudiAlgorithm.h
std
STL namespace.
Gaudi::Functional::details::remove_optional_t
std::conditional_t< is_optional_v< T >, typename T::value_type, T > remove_optional_t
Definition: FunctionalDetails.h:135
Gaudi::Functional::details::vector_of_const_::iterator::difference_type
typename it_t::difference_type difference_type
Definition: FunctionalDetails.h:305
Gaudi::Functional::details::is_optional_v
constexpr bool is_optional_v
Definition: FunctionalDetails.h:126
Gaudi::Functional::details::BaseClass_t
Gaudi::cpp17::detected_or_t< GaudiAlgorithm, detail2::BaseClass_t, Tr > BaseClass_t
Definition: FunctionalDetails.h:376
Gaudi::Functional::details::details2::push_back
void push_back(Container &c, const Value &v, std::false_type)
Definition: FunctionalDetails.h:245
Gaudi::Functional::details::details2::deref_if
T & deref_if(T *const t, std::true_type)
Definition: FunctionalDetails.h:275
EventContext
Definition: EventContext.h:34
Gaudi::Functional::details::RepeatValues_
decltype(get_values_helper< Value >(std::make_index_sequence< N >())) RepeatValues_
Definition: FunctionalDetails.h:155
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple< In... >, Traits_ >::outputLocationSize
constexpr unsigned int outputLocationSize() const
Definition: FunctionalDetails.h:539
Gaudi::Functional::Traits::BaseClass_t
Definition: FunctionalUtilities.h:72
Gaudi::Functional::details::vector_of_const_::iterator::value_type
typename it_t::iterator_category value_type
Definition: FunctionalDetails.h:302
detected.h
Gaudi::Functional::details::vector_of_const_::iterator::pointer
typename it_t::pointer pointer
Definition: FunctionalDetails.h:304
Gaudi::Functional::details::vector_of_const_::iterator::it_t
typename ContainerVector::const_iterator it_t
Definition: FunctionalDetails.h:294
Gaudi::Functional::details::updateHandleLocations
void updateHandleLocations(DataHandleMixin< Out, In, Tr > &parent, const std::string &prop, const std::vector< std::string > &newLocs)
Definition: FunctionalDetails.h:470
Gaudi::Functional::details::insert_t::operator()
auto operator()(Container &c, Value &&v) const -> decltype(c.insert(v))
Definition: FunctionalDetails.h:191
Gaudi::Functional::details::vector_of_const_::ref_t
std::add_lvalue_reference_t< val_t > ref_t
Definition: FunctionalDetails.h:286
Gaudi::Functional::details::vector_of_const_::iterator::reference
typename it_t::reference reference
Definition: FunctionalDetails.h:303
Gaudi::Functional::details::DataHandleMixin
Definition: FunctionalDetails.h:460
Gaudi::Functional::details::details2::get_from_handle::operator()
auto operator()(const Handle< Gaudi::NamedRange_< I, IT >> &h) -> const In
Definition: FunctionalDetails.h:260
Gaudi::Functional::details::vector_of_const_::end
iterator end() const
Definition: FunctionalDetails.h:336
std::ostringstream::str
T str(T... args)
std::size_t
std::vector::end
T end(T... args)
Gaudi::Functional::details::zip::printSizes
void printSizes(OS &out, Arg &&arg, Args &&... args)
Print the parameters.
Definition: FunctionalDetails.h:64
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
UNLIKELY
#define UNLIKELY(x)
Definition: Kernel.h:106
Gaudi::Functional::details::DataHandleMixin< std::tuple<>, std::tuple<>, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, std::tuple<>={}, std::tuple<>={})
Definition: FunctionalDetails.h:555
Gaudi::Functional::details::vector_of_const_::iterator::ret_t
std::conditional_t< is_pointer, ptr_t, ref_t > ret_t
Definition: FunctionalDetails.h:298
Gaudi::Functional::details::insert
constexpr struct Gaudi::Functional::details::insert_t insert
DataObjectHandle.h
Gaudi::Functional::details::details2::get_from_handle::operator()
auto operator()(const Handle< I > &h) -> const In
Definition: FunctionalDetails.h:265
Gaudi::Functional::details::OutputHandle_t
Gaudi::cpp17::detected_or_t< DataObjectWriteHandle< T >, detail2::OutputHandle_t, Tr, T > OutputHandle_t
Definition: FunctionalDetails.h:382
Gaudi::Functional::details::filter_evtcontext
typename filter_evtcontext_t< In... >::type filter_evtcontext
Definition: FunctionalDetails.h:457
Gaudi::Functional::details::DataHandleMixin< std::tuple<>, std::tuple< In... >, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_in > const &inputs)
Definition: FunctionalDetails.h:585
Gaudi::Functional::details::vector_of_const_::vector_of_const_
vector_of_const_()=default
Gaudi::Functional::details::vector_of_const_::ptr_t
std::add_pointer_t< val_t > ptr_t
Definition: FunctionalDetails.h:285
Gaudi::Functional::details::DataHandleMixin< std::tuple< Out... >, std::tuple< In... >, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input, RepeatValues_< KeyValue, N_out > const &outputs)
Definition: FunctionalDetails.h:513
Gaudi::Functional::details::zip::range
decltype(auto) range(Args &&... args)
Zips multiple containers together to form a single range.
Definition: FunctionalDetails.h:101
GaudiUtils::details::ostream_joiner
Stream & ostream_joiner(Stream &os, Iterator first, Iterator last, Separator sep, OutputElement output=OutputElement{})
Definition: SerializeSTL.h:73
Gaudi::Functional::details::DataHandleMixin< std::tuple<>, std::tuple< In... >, Traits_ >::DataHandleMixin
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input)
Definition: FunctionalDetails.h:590
PrepareBase.out
out
Definition: PrepareBase.py:20
Gaudi::Functional::details::getKey
auto getKey(const Handle &h) -> decltype(h.objKey())
Definition: FunctionalDetails.h:412
Gaudi::Functional::details::vector_of_const_::is_null
bool is_null(size_type i) const
Definition: FunctionalDetails.h:359
Gaudi::Functional::details::vector_of_const_::size
size_type size() const
Definition: FunctionalDetails.h:337