The Gaudi Framework  v30r0 (c919700c)
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 
16 // Boost
17 #include "boost/optional.hpp"
18 
19 // Range V3
20 #include <range/v3/view/const.hpp>
21 #include <range/v3/view/zip.hpp>
22 
23 namespace Gaudi
24 {
25  namespace Functional
26  {
27  namespace details
28  {
29 
30  // CRJ : Stuff for zipping
31  namespace zip
32  {
33 
35  template <typename OS, typename Arg>
36  void printSizes( OS& out, Arg&& arg )
37  {
38  out << "SizeOf'" << System::typeinfoName( typeid( Arg ) ) << "'=" << std::forward<Arg>( arg ).size();
39  }
40 
42  template <typename OS, typename Arg, typename... Args>
43  void printSizes( OS& out, Arg&& arg, Args&&... args )
44  {
45  printSizes( out, arg );
46  out << ", ";
47  printSizes( out, args... );
48  }
49 
51  template <typename A>
52  inline bool check_sizes( const A& ) noexcept
53  {
54  return true;
55  }
56 
58  template <typename A, typename B>
59  inline bool check_sizes( const A& a, const B& b ) noexcept
60  {
61  return a.size() == b.size();
62  }
63 
65  template <typename A, typename B, typename... C>
66  inline bool check_sizes( const A& a, const B& b, const C&... c ) noexcept
67  {
68  return ( check_sizes( a, b ) && check_sizes( b, c... ) );
69  }
70 
72  template <typename... Args>
73  inline decltype( auto ) verifySizes( Args&... args )
74  {
75  if ( UNLIKELY( !check_sizes( args... ) ) ) {
76  std::ostringstream mess;
77  mess << "Zipped containers have different sizes : ";
78  printSizes( mess, args... );
79  throw GaudiException( mess.str(), "Gaudi::Functional::details::zip::verifySizes", StatusCode::FAILURE );
80  }
81  }
82 
84  template <typename... Args>
85  inline decltype( auto ) range( Args&&... args )
86  {
87  // assert( check_sizes( args... ) );
88  verifySizes( args... );
89  return ranges::view::zip( std::forward<Args>( args )... );
90  }
91 
93  template <typename... Args>
94  inline decltype( auto ) const_range( Args&&... args )
95  {
96  // assert( check_sizes( args... ) );
97  verifySizes( args... );
98  return ranges::view::const_( ranges::view::zip( std::forward<Args>( args )... ) );
99  }
100  }
101 
102  // implementation of C++17 std::as_const, see http://en.cppreference.com/w/cpp/utility/as_const
103  template <typename T>
104  constexpr std::add_const_t<T>& as_const( T& t ) noexcept
105  {
106  return t;
107  }
108 
109  template <typename T>
110  void as_const( T&& t ) = delete;
111 
113 
114  template <typename Out1, typename Out2, typename = std::enable_if_t<std::is_constructible<Out1, Out2>::value>>
115  Out1* put( DataObjectHandle<Out1>& out_handle, Out2&& out )
116  {
117  return out_handle.put( new Out1( std::forward<Out2>( out ) ) );
118  }
119 
120  template <typename Out1, typename Out2, typename = std::enable_if_t<std::is_constructible<Out1, Out2>::value>>
121  void put( AnyDataHandle<Out1>& out_handle, Out2&& out )
122  {
123  out_handle.put( std::forward<Out2>( out ) );
124  }
125 
126  // optional put
127  template <typename OutHandle, typename Out>
128  void put( OutHandle& out_handle, boost::optional<Out>&& out )
129  {
130  if ( out ) put( out_handle, std::move( *out ) );
131  }
133  // adapt to differences between eg. std::vector (which has push_back) and KeyedContainer (which has insert)
134  // adapt to getting a T, and a container wanting T* by doing new T{ std::move(out) }
135  // adapt to getting a boost::optional<T>
136 
137  constexpr struct insert_t {
138  // for Container<T*>, return T
139  template <typename Container>
140  using c_remove_ptr_t = std::remove_pointer_t<typename Container::value_type>;
141 
142  template <typename Container, typename Value>
143  auto operator()( Container& c, Value&& v ) const -> decltype( c.push_back( v ) )
144  {
145  return c.push_back( std::forward<Value>( v ) );
146  }
147 
148  template <typename Container, typename Value>
149  auto operator()( Container& c, Value&& v ) const -> decltype( c.insert( v ) )
150  {
151  return c.insert( std::forward<Value>( v ) );
152  }
153 
154  // Container<T*> with T&& as argument
155  template <typename Container,
156  typename = std::enable_if_t<std::is_pointer<typename Container::value_type>::value>>
157  auto operator()( Container& c, c_remove_ptr_t<Container>&& v ) const
158  {
159  return operator()( c, new c_remove_ptr_t<Container>{std::move( v )} );
160  }
161 
162  template <typename Container, typename Value>
163  void operator()( Container& c, boost::optional<Value>&& v ) const
164  {
165  if ( v ) operator()( c, std::move( *v ) );
166  }
167  } insert{};
168 
170 
171  constexpr struct deref_t {
172  template <typename In, typename = std::enable_if_t<!std::is_pointer<In>::value>>
173  In& operator()( In& in ) const
174  {
175  return in;
176  }
177 
178  template <typename In>
179  In& operator()( In* in ) const
180  {
181  assert( in != nullptr );
182  return *in;
183  }
184  } deref{};
185 
187 
188  namespace details2
189  {
190  template <typename T>
192  typedef T type;
193  };
194  template <typename T>
195  struct remove_optional<boost::optional<T>> {
196  typedef T type;
197  };
198  // template< typename T > struct remove_optional< std::optional<T> > {typedef T type;};
199  }
200  template <typename T>
202  template <typename T>
204  };
205  template <typename T>
206  struct is_optional<boost::optional<T>> : std::true_type {
207  };
208  // C++17: template <typename T> constexpr bool is_optional_v = is_optional<T>::value;
209 
211  // if Container is a pointer, then we're optional items
212  namespace details2
213  {
214  template <typename Container, typename Value>
215  void push_back( Container& c, const Value& v, std::true_type )
216  {
217  c.push_back( v );
218  }
219  template <typename Container, typename Value>
220  void push_back( Container& c, const Value& v, std::false_type )
221  {
222  c.push_back( &v );
223  }
224 
225  template <typename In>
227  template <template <typename> class Handle, typename I,
228  typename = std::enable_if_t<std::is_convertible<I, In>::value>>
229  auto operator()( const Handle<I>& h ) -> const In&
230  {
231  return *h.get();
232  }
233  template <template <typename> class Handle, typename I,
234  typename = std::enable_if_t<std::is_convertible<I*, In>::value>>
235  auto operator()( const Handle<I>& h ) -> const In
236  {
237  return h.getIfExists();
238  } // In is-a pointer
239  };
240 
241  template <typename T>
242  T* deref_if( T* const t, std::false_type )
243  {
244  return t;
245  }
246  template <typename T>
247  T& deref_if( T* const t, std::true_type )
248  {
249  return *t;
250  }
251  }
252 
253  template <typename Container>
255  {
257  using val_t = std::add_const_t<std::remove_pointer_t<Container>>;
258  using ptr_t = std::add_pointer_t<val_t>;
259  using ref_t = std::add_lvalue_reference_t<val_t>;
262 
263  public:
264  using value_type = std::conditional_t<is_optional, ptr_t, val_t>;
265  using size_type = typename ContainerVector::size_type;
266  class iterator
267  {
268  typename ContainerVector::const_iterator m_i;
269  friend class vector_of_const_;
270  iterator( typename ContainerVector::const_iterator iter ) : m_i( iter ) {}
271  using ret_t = std::conditional_t<is_optional, ptr_t, ref_t>;
272 
273  public:
274  friend bool operator!=( const iterator& lhs, const iterator& rhs ) { return lhs.m_i != rhs.m_i; }
277  {
278  ++m_i;
279  return *this;
280  }
282  {
283  --m_i;
284  return *this;
285  }
286  bool is_null() const { return !*m_i; }
287  explicit operator bool() const { return !is_null(); }
288  };
289  vector_of_const_() = default;
290  void reserve( size_type size ) { m_containers.reserve( size ); }
291  template <typename T> // , typename = std::is_convertible<T,std::conditional_t<is_optional,ptr_t,val_t>>
292  void push_back( T&& container )
293  {
294  details2::push_back( m_containers, std::forward<T>( container ),
296  } // note: does not copy its argument, so we're not really a container...
297  iterator begin() const { return m_containers.begin(); }
298  iterator end() const { return m_containers.end(); }
299  size_type size() const { return m_containers.size(); }
300  const Container& operator[]( size_type i ) const { return *m_containers[i]; }
301  const Container& at( size_type i ) const
302  {
303  if ( i >= size() ) throw std::out_of_range{"vector_of_const_::at"};
304  return *m_containers[i];
305  }
306  bool is_null( size_type i ) const { return !m_containers[i]; }
307  };
308 
310 
311  // detect whether a traits class defines the requested type,
312  // if so, use it,
313  // otherwise use the default
314  //
315  // based on http://en.cppreference.com/w/cpp/experimental/is_detected
316  // and the libstdc++ source, specificially libstdc++-v3/include/std/type_traits
317 
318  namespace detail2
319  {
320 #ifdef HAVE_CPP17
321  template <typename...>
322  using void_t = void;
323 #else
324  template <typename...>
325  struct void_t_ {
326  using type = void;
327  };
328  template <typename... T>
329  using void_t = typename void_t_<T...>::type;
330 #endif
331 
333  template <typename Default, typename AlwaysVoid, template <typename...> class Op, typename... Args>
334  struct detector {
335  using type = Default;
336  };
337 
339  template <typename Default, template <typename...> class Op, typename... Args>
340  struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
341  using type = Op<Args...>;
342  };
343  }
344 
345  // Op<Args...> if that is a valid type, otherwise Default.
346  template <typename Default, template <typename...> class Op, typename... Args>
347  using detected_or_t = typename detail2::detector<Default, void, Op, Args...>::type;
348 
349  // Op<Args...> if that is a valid type, otherwise Default<Args...>.
350  template <template <typename...> class Default, template <typename...> class Op, typename Tr, typename T>
352 
354  namespace detail2
355  { // utilities for detected_or_t{,_} usage
356 
357  template <typename Tr>
358  using BaseClass_ = typename Tr::BaseClass;
359  template <typename Tr, typename T>
360  using defaultHandle_ =
361  std::conditional_t<std::is_base_of<DataObject, T>::value, DataObjectHandle<T>, AnyDataHandle<T>>;
362  template <typename Tr, typename T>
363  using OutputHandle_ = typename Tr::template OutputHandle<T>;
364  template <typename Tr, typename T>
365  using InputHandle_ = typename Tr::template InputHandle<T>;
366  }
367 
368  // check whether Traits::BaseClass is a valid type,
369  // if so, define BaseClass_t<Traits> as being Traits::BaseClass
370  // else define as being GaudiAlgorithm
371  template <typename Tr>
373 
374  // check whether Traits::{Input,Output}Handle<T> is a valid type,
375  // if so, define {Input,Output}Handle_t<Traits,T> as being Traits::{Input,Output}Handle<T>
376  // else define as being DataObjectHandle<T> if T derives from DataObject, else
377  // AnyDataHandle<T>
378  template <typename Tr, typename T>
380  template <typename Tr, typename T>
382 
384 
385  namespace details2
386  {
387  template <typename Tuple, typename KeyValues, std::size_t... I>
389  std::index_sequence<I...> )
390  {
391  return std::make_tuple( std::tuple_element_t<I, Tuple>{std::get<I>( initvalue ).second, m, o}... );
392  }
393  template <typename KeyValues, typename Properties, std::size_t... I>
394  void declare_tuple_of_properties_helper( Algorithm& owner, const KeyValues& inputs, Properties& props,
395  std::index_sequence<I...> )
396  {
398  ( owner.declareProperty( std::get<I>( inputs ).first, std::get<I>( props ) ), 0 )...};
399  }
400  }
401 
402  template <typename Tuple, typename KeyValues>
404  {
405  return details2::make_tuple_of_handles_helper<Tuple>(
406  owner, initvalue, mode, std::make_index_sequence<std::tuple_size<Tuple>::value>{} );
407  }
408 
409  template <typename KeyValues, typename Properties>
410  void declare_tuple_of_properties( Algorithm& owner, const KeyValues& inputs, Properties& props )
411  {
412  constexpr auto N = std::tuple_size<KeyValues>::value;
413  static_assert( N == std::tuple_size<Properties>::value, "Inconsistent lengths" );
414  details2::declare_tuple_of_properties_helper( owner, inputs, props, std::make_index_sequence<N>{} );
415  }
416 
417  template <typename Handles>
420  {
421  Handles handles;
422  handles.reserve( init.size() );
423  std::transform( init.begin(), init.end(), std::back_inserter( handles ),
424  [&]( const std::string& loc ) -> typename Handles::value_type {
425  return {loc, mode, owner};
426  } );
427  return handles;
428  }
429 
431 
432  template <typename OutputSpec, typename InputSpec, typename Traits_>
434 
435  template <typename... Out, typename... In, typename Traits_>
436  class DataHandleMixin<std::tuple<Out...>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_>
437  {
438  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
439  "BaseClass must inherit from Algorithm" );
440 
441  public:
443  constexpr static std::size_t N_in = sizeof...( In );
444  constexpr static std::size_t N_out = sizeof...( Out );
445 
446  // generic constructor: N -> M
448  const std::array<KeyValue, N_out>& outputs )
449  : BaseClass_t<Traits_>( name, pSvcLocator )
450  , m_inputs( make_tuple_of_handles<decltype( m_inputs )>( this, inputs, Gaudi::DataHandle::Reader ) )
451  , m_outputs( make_tuple_of_handles<decltype( m_outputs )>( this, outputs, Gaudi::DataHandle::Writer ) )
452  {
453  declare_tuple_of_properties( *this, inputs, m_inputs );
454  declare_tuple_of_properties( *this, outputs, m_outputs );
455  // make sure this algorithm is seen as reentrant by Gaudi
456  BaseClass_t<Traits_>::setProperty( "Cardinality", 0 );
457  }
458 
459  // special cases: forward to the generic case...
460  // 1 -> 1
461  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input, const KeyValue& output )
462  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input}, std::array<KeyValue, 1>{output} )
463  {
464  }
465  // 1 -> N
466  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input,
467  const std::array<KeyValue, N_out>& outputs )
468  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input}, outputs )
469  {
470  }
471  // N -> 1
473  const KeyValue& output )
474  : DataHandleMixin( name, locator, inputs, std::array<KeyValue, 1>{output} )
475  {
476  }
477 
478  template <std::size_t N = 0>
479  const std::string& inputLocation() const
480  {
481  return std::get<N>( m_inputs ).objKey();
482  }
483  unsigned int inputLocationSize() const { return std::tuple_size<decltype( m_inputs )>::value; }
484 
485  template <std::size_t N = 0>
487  {
488  return std::get<N>( m_outputs ).objKey();
489  }
490  unsigned int outputLocationSize() const { return std::tuple_size<decltype( m_outputs )>::value; }
491 
492  protected:
495  };
496 
497  template <typename... In, typename Traits_>
498  class DataHandleMixin<void, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_>
499  {
500  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
501  "BaseClass must inherit from Algorithm" );
502 
503  public:
505  constexpr static std::size_t N_in = sizeof...( In );
506 
507  // generic constructor: N -> 0
509  : BaseClass_t<Traits_>( name, pSvcLocator )
510  , m_inputs( make_tuple_of_handles<decltype( m_inputs )>( this, inputs, Gaudi::DataHandle::Reader ) )
511  {
512  declare_tuple_of_properties( *this, inputs, m_inputs );
513  // make sure this algorithm is seen as reentrant by Gaudi
514  BaseClass_t<Traits_>::setProperty( "Cardinality", 0 );
515  }
516 
517  // special cases: forward to the generic case...
518  // 1 -> 0
519  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input )
520  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input} )
521  {
522  }
523 
524  template <std::size_t N = 0>
525  const std::string& inputLocation() const
526  {
527  return std::get<N>( m_inputs ).objKey();
528  }
529  unsigned int inputLocationSize() const { return std::tuple_size<decltype( m_inputs )>::value; }
530 
531  protected:
533  };
534 
535  template <typename... Out, typename Traits_>
536  class DataHandleMixin<std::tuple<Out...>, void, Traits_> : public BaseClass_t<Traits_>
537  {
538  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
539  "BaseClass must inherit from Algorithm" );
540 
541  public:
543  constexpr static std::size_t N_out = sizeof...( Out );
544 
545  // generic constructor: 0 -> N
547  : BaseClass_t<Traits_>( name, pSvcLocator )
548  , m_outputs( make_tuple_of_handles<decltype( m_outputs )>( this, outputs, Gaudi::DataHandle::Writer ) )
549  {
550  declare_tuple_of_properties( *this, outputs, m_outputs );
551  // make sure this algorithm is seen as reentrant by Gaudi
552  BaseClass_t<Traits_>::setProperty( "Cardinality", 0 );
553  }
554 
555  // 0 -> 1
557  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{output} )
558  {
559  }
560 
561  template <std::size_t N = 0>
563  {
564  return std::get<N>( m_outputs ).objKey();
565  }
566  unsigned int outputLocationSize() const { return std::tuple_size<decltype( m_outputs )>::value; }
567 
568  protected:
570  };
571 
573  template <typename Fun, typename Container, typename... Args>
574  constexpr void applyPostProcessing( const Fun&, Container&, Args... )
575  {
576  static_assert( sizeof...( Args ) == 0, "Args should not be used!" );
577  }
578 
579  template <typename Fun, typename Container>
580  auto applyPostProcessing( const Fun& fun, Container& c ) -> decltype( fun.postprocess( c ), void() )
581  {
582  fun.postprocess( c );
583  }
584 
586  }
587  }
588 }
589 
590 #endif
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_out > &outputs)
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_in > &inputs)
auto operator()(Container &c, Value &&v) const -> decltype(c.insert(v))
StatusCode setProperty(IProperty *component, const std::string &name, const TYPE &value, const std::string &doc)
simple function to set the property of the given object from the value
Definition: Property.h:1172
Tuple make_tuple_of_handles_helper(IDataHandleHolder *o, const KeyValues &initvalue, Gaudi::DataHandle::Mode m, std::index_sequence< I... >)
#define UNLIKELY(x)
Definition: Kernel.h:128
detected_or_t_< detail2::defaultHandle_, detail2::OutputHandle_, Tr, T > OutputHandle_t
Define general base for Gaudi exception.
DataHandleMixin(const std::string &name, ISvcLocator *locator, const std::array< KeyValue, N_in > &inputs, const KeyValue &output)
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
Handles make_vector_of_handles(IDataHandleHolder *owner, const std::vector< std::string > &init, Gaudi::DataHandle::Mode mode)
The namespace threadpool contains a thread pool and related utility classes.
Definition: iter_pos.hpp:13
friend bool operator!=(const iterator &lhs, const iterator &rhs)
void declare_tuple_of_properties(Algorithm &owner, const KeyValues &inputs, Properties &props)
detected_or_t< GaudiAlgorithm, detail2::BaseClass_, Tr > BaseClass_t
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:336
void declare_tuple_of_properties_helper(Algorithm &owner, const KeyValues &inputs, Properties &props, std::index_sequence< I... >)
auto operator()(Container &c, c_remove_ptr_t< Container > &&v) const
void printSizes(OS &out, Arg &&arg)
Print the parameter.
constexpr struct Gaudi::Functional::details::insert_t insert
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_in > &inputs, const std::array< KeyValue, N_out > &outputs)
typename Tr::template InputHandle< T > InputHandle_
Header file for class GaudiAlgorithm.
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &input, const KeyValue &output)
std::add_const_t< std::remove_pointer_t< Container >> val_t
STL namespace.
class MergingTransformer< Out(const vector_of_const_< In > void
T make_tuple(T...args)
auto operator()(Container &c, Value &&v) const -> decltype(c.push_back(v))
T end(T...args)
void push_back(Container &c, const Value &v, std::true_type)
std::vector< Gaudi::Details::PropertyBase * > Properties
Definition: PropertyMgr.h:134
std::remove_pointer_t< typename Container::value_type > c_remove_ptr_t
iterator(typename ContainerVector::const_iterator iter)
std::add_lvalue_reference_t< val_t > ref_t
T * deref_if(T *const t, std::false_type)
typename void_t_< T... >::type void_t
const Container & operator[](size_type i) const
constexpr struct Gaudi::Functional::details::deref_t deref
const T * put(T &&object)
Register object in transient store.
Definition: AnyDataHandle.h:41
constexpr double second
STL class.
std::conditional_t< is_optional, ptr_t, val_t > value_type
DataObjectHandle.h GaudiKernel/DataObjectHandle.h.
Definition: AlgTool.h:27
Implementation of the detection idiom (negative case).
int N
Definition: IOTest.py:101
std::conditional_t< std::is_base_of< DataObject, T >::value, DataObjectHandle< T >, AnyDataHandle< T >> defaultHandle_
constexpr void applyPostProcessing(const Fun &, Container &, Args...)
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &input, const std::array< KeyValue, N_out > &outputs)
Definition: compose.h:3
constexpr double m
Definition: SystemOfUnits.h:94
auto operator()(const Handle< I > &h) -> const In &
T * put(T *object)
Register object in transient store.
typename details2::remove_optional< T >::type remove_optional_t
auto operator()(const Handle< I > &h) -> const In
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &output)
decltype(auto) range(Args &&...args)
Zips multiple containers together to form a single range.
Tuple make_tuple_of_handles(IDataHandleHolder *owner, const KeyValues &initvalue, Gaudi::DataHandle::Mode mode)
T move(T...args)
decltype(auto) verifySizes(Args &...args)
Verify the data container sizes have the same sizes.
constexpr std::add_const_t< T > & as_const(T &t) noexcept
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:79
T size(T...args)
std::vector< InputHandle_t< In > > m_inputs
struct GAUDI_API array
Parametrisation class for redirection array - like implementation.
std::conditional_t< is_optional, ptr_t, ref_t > ret_t
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
detected_or_t< Default< Tr, T >, Op, Tr, T > detected_or_t_
void operator()(Container &c, boost::optional< Value > &&v) const
T begin(T...args)
bool check_sizes(const A &) noexcept
Resolve case there is only one container in the range.
T back_inserter(T...args)
const Container & at(size_type i) const
std::tuple< details::OutputHandle_t< Traits_, Out >... > m_outputs
double fun(const std::vector< double > &x)
Definition: PFuncTest.cpp:26
STL class.
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &input)
typename Tr::template OutputHandle< T > OutputHandle_
struct[[deprecated("use MergingTransformer instead")]] Traits_
Gaudi::Details::PropertyBase * declareProperty(const std::string &name, ToolHandle< T > &hndl, const std::string &doc="none")
Definition: Algorithm.h:372
T transform(T...args)
detected_or_t_< detail2::defaultHandle_, detail2::InputHandle_, Tr, T > InputHandle_t
decltype(auto) const_range(Args &&...args)
Zips multiple containers together to form a single const range.
T & deref_if(T *const t, std::true_type)
Helper functions to set/get the application return code.
Definition: __init__.py:1
def Reader(readerType, filename, qacross, qToEngine)
Out1 * put(DataObjectHandle< Out1 > &out_handle, Out2 &&out)
void push_back(Container &c, const Value &v, std::false_type)
typename detail2::detector< Default, void, Op, Args... >::type detected_or_t
std::pair< std::string, std::vector< std::string >> KeyValues
T reserve(T...args)
typename ContainerVector::size_type size_type