The Gaudi Framework  v30r3 (a5ef0a68)
FunctionalDetails.h
Go to the documentation of this file.
1 #ifndef FUNCTIONAL_DETAILS_H
2 #define FUNCTIONAL_DETAILS_H
3 
4 #include <cassert>
5 #include <sstream>
6 #include <stdexcept>
7 #include <type_traits>
8 
9 // TODO: fwd declare instead?
11 #include "GaudiKernel/Algorithm.h"
15 #include "GaudiKernel/apply.h"
16 #include "GaudiKernel/detected.h"
17 
18 // Boost
19 #include "boost/optional.hpp"
20 
21 // Range V3
22 #include <range/v3/view/const.hpp>
23 #include <range/v3/view/zip.hpp>
24 
25 namespace Gaudi
26 {
27  namespace Functional
28  {
29  namespace details
30  {
31 
32  // CRJ : Stuff for zipping
33  namespace zip
34  {
35 
37  template <typename OS, typename Arg>
38  void printSizes( OS& out, Arg&& arg )
39  {
40  out << "SizeOf'" << System::typeinfoName( typeid( Arg ) ) << "'=" << std::forward<Arg>( arg ).size();
41  }
42 
44  template <typename OS, typename Arg, typename... Args>
45  void printSizes( OS& out, Arg&& arg, Args&&... args )
46  {
47  printSizes( out, arg );
48  out << ", ";
49  printSizes( out, args... );
50  }
51 
53  template <typename A>
54  inline bool check_sizes( const A& ) noexcept
55  {
56  return true;
57  }
58 
60  template <typename A, typename B>
61  inline bool check_sizes( const A& a, const B& b ) noexcept
62  {
63  return a.size() == b.size();
64  }
65 
67  template <typename A, typename B, typename... C>
68  inline bool check_sizes( const A& a, const B& b, const C&... c ) noexcept
69  {
70  return ( check_sizes( a, b ) && check_sizes( b, c... ) );
71  }
72 
74  template <typename... Args>
75  inline decltype( auto ) verifySizes( Args&... args )
76  {
77  if ( UNLIKELY( !check_sizes( args... ) ) ) {
78  std::ostringstream mess;
79  mess << "Zipped containers have different sizes : ";
80  printSizes( mess, args... );
81  throw GaudiException( mess.str(), "Gaudi::Functional::details::zip::verifySizes", StatusCode::FAILURE );
82  }
83  }
84 
86  template <typename... Args>
87  inline decltype( auto ) range( Args&&... args )
88  {
89 #ifndef NDEBUG
90  verifySizes( args... );
91 #endif
92  return ranges::view::zip( std::forward<Args>( args )... );
93  }
94 
96  template <typename... Args>
97  inline decltype( auto ) const_range( Args&&... args )
98  {
99 #ifndef NDEBUG
100  verifySizes( args... );
101 #endif
102  return ranges::view::const_( ranges::view::zip( std::forward<Args>( args )... ) );
103  }
104  }
105 
106 #if __cplusplus < 201703L
107  // implementation of C++17 std::as_const, see http://en.cppreference.com/w/cpp/utility/as_const
108  template <typename T>
109  constexpr std::add_const_t<T>& as_const( T& t ) noexcept
110  {
111  return t;
112  }
113 
114  template <typename T>
115  void as_const( T&& t ) = delete;
116 
117  template <class...>
119  };
120  template <class B1>
121  struct disjunction<B1> : B1 {
122  };
123  template <class B1, class... Bn>
124  struct disjunction<B1, Bn...> : std::conditional_t<bool( B1::value ), B1, disjunction<Bn...>> {
125  };
126 
127 #else
128  using std::as_const;
129  using std::disjunction;
130 #endif
131 
133  template <typename Out1, typename Out2, typename = std::enable_if_t<std::is_constructible<Out1, Out2>::value &&
135  Out1* put( DataObjectHandle<Out1>& out_handle, Out2&& out )
136  {
137  return out_handle.put( std::make_unique<Out1>( std::forward<Out2>( out ) ) );
138  }
139 
140  template <typename Out1, typename Out2, typename = std::enable_if_t<std::is_constructible<Out1, Out2>::value>>
141  void put( DataObjectHandle<AnyDataWrapper<Out1>>& out_handle, Out2&& out )
142  {
143  out_handle.put( std::forward<Out2>( out ) );
144  }
145 
146  // optional put
147  template <typename OutHandle, typename Out>
148  void put( OutHandle& out_handle, boost::optional<Out>&& out )
149  {
150  if ( out ) put( out_handle, std::move( *out ) );
151  }
153  // adapt to differences between eg. std::vector (which has push_back) and KeyedContainer (which has insert)
154  // adapt to getting a T, and a container wanting T* by doing new T{ std::move(out) }
155  // adapt to getting a boost::optional<T>
156 
157  constexpr struct insert_t {
158  // for Container<T*>, return T
159  template <typename Container>
160  using c_remove_ptr_t = std::remove_pointer_t<typename Container::value_type>;
161 
162  template <typename Container, typename Value>
163  auto operator()( Container& c, Value&& v ) const -> decltype( c.push_back( v ) )
164  {
165  return c.push_back( std::forward<Value>( v ) );
166  }
167 
168  template <typename Container, typename Value>
169  auto operator()( Container& c, Value&& v ) const -> decltype( c.insert( v ) )
170  {
171  return c.insert( std::forward<Value>( v ) );
172  }
173 
174  // Container<T*> with T&& as argument
175  template <typename Container,
176  typename = std::enable_if_t<std::is_pointer<typename Container::value_type>::value>>
177  auto operator()( Container& c, c_remove_ptr_t<Container>&& v ) const
178  {
179  return operator()( c, new c_remove_ptr_t<Container>{std::move( v )} );
180  }
181 
182  template <typename Container, typename Value>
183  void operator()( Container& c, boost::optional<Value>&& v ) const
184  {
185  if ( v ) operator()( c, std::move( *v ) );
186  }
187  } insert{};
188 
190 
191  constexpr struct deref_t {
192  template <typename In, typename = std::enable_if_t<!std::is_pointer<In>::value>>
193  const In& operator()( const In& in ) const
194  {
195  return in;
196  }
197 
198  template <typename In>
199  const In& operator()( const In* in ) const
200  {
201  assert( in != nullptr );
202  return *in;
203  }
204  } deref{};
205 
207 
208  namespace details2
209  {
210  template <typename T>
212  typedef T type;
213  };
214  template <typename T>
215  struct remove_optional<boost::optional<T>> {
216  typedef T type;
217  };
218  // template< typename T > struct remove_optional< std::optional<T> > {typedef T type;};
219  }
220  template <typename T>
222  template <typename T>
224  };
225  template <typename T>
226  struct is_optional<boost::optional<T>> : std::true_type {
227  };
228  // C++17: template <typename T> constexpr bool is_optional_v = is_optional<T>::value;
229 
231  // if Container is a pointer, then we're optional items
232  namespace details2
233  {
234  template <typename Container, typename Value>
235  void push_back( Container& c, const Value& v, std::true_type )
236  {
237  c.push_back( v );
238  }
239  template <typename Container, typename Value>
240  void push_back( Container& c, const Value& v, std::false_type )
241  {
242  c.push_back( &v );
243  }
244 
245  template <typename In>
247  template <template <typename> class Handle, typename I,
248  typename = std::enable_if_t<std::is_convertible<I, In>::value>>
249  auto operator()( const Handle<I>& h ) -> const In&
250  {
251  return *h.get();
252  }
253  template <template <typename> class Handle, typename I,
254  typename = std::enable_if_t<std::is_convertible<I*, In>::value>>
255  auto operator()( const Handle<I>& h ) -> const In
256  {
257  return h.getIfExists();
258  } // In is-a pointer
259  };
260 
261  template <typename T>
262  T* deref_if( T* const t, std::false_type )
263  {
264  return t;
265  }
266  template <typename T>
267  T& deref_if( T* const t, std::true_type )
268  {
269  return *t;
270  }
271  }
272 
273  template <typename Container>
275  {
277  using val_t = std::add_const_t<std::remove_pointer_t<Container>>;
278  using ptr_t = std::add_pointer_t<val_t>;
279  using ref_t = std::add_lvalue_reference_t<val_t>;
282 
283  public:
284  using value_type = std::conditional_t<is_optional, ptr_t, val_t>;
285  using size_type = typename ContainerVector::size_type;
286  class iterator
287  {
288  typename ContainerVector::const_iterator m_i;
289  friend class vector_of_const_;
290  iterator( typename ContainerVector::const_iterator iter ) : m_i( iter ) {}
291  using ret_t = std::conditional_t<is_optional, ptr_t, ref_t>;
292 
293  public:
294  friend bool operator!=( const iterator& lhs, const iterator& rhs ) { return lhs.m_i != rhs.m_i; }
297  {
298  ++m_i;
299  return *this;
300  }
302  {
303  --m_i;
304  return *this;
305  }
306  bool is_null() const { return !*m_i; }
307  explicit operator bool() const { return !is_null(); }
308  };
309  vector_of_const_() = default;
310  void reserve( size_type size ) { m_containers.reserve( size ); }
311  template <typename T> // , typename = std::is_convertible<T,std::conditional_t<is_optional,ptr_t,val_t>>
312  void push_back( T&& container )
313  {
314  details2::push_back( m_containers, std::forward<T>( container ),
316  } // note: does not copy its argument, so we're not really a container...
317  iterator begin() const { return m_containers.begin(); }
318  iterator end() const { return m_containers.end(); }
319  size_type size() const { return m_containers.size(); }
320  const Container& operator[]( size_type i ) const { return *m_containers[i]; }
321  const Container& at( size_type i ) const
322  {
323  if ( UNLIKELY( i >= size() ) ) throw std::out_of_range{"vector_of_const_::at"};
324  return *m_containers[i];
325  }
326  bool is_null( size_type i ) const { return !m_containers[i]; }
327  };
328 
330  namespace detail2
331  { // utilities for detected_or_t{,_} usage
332  template <typename Tr>
333  using BaseClass_t = typename Tr::BaseClass;
334  template <typename Tr, typename T>
335  using OutputHandle_t = typename Tr::template OutputHandle<T>;
336  template <typename Tr, typename T>
337  using InputHandle_t = typename Tr::template InputHandle<T>;
338  }
339 
340  // check whether Traits::BaseClass is a valid type,
341  // if so, define BaseClass_t<Traits> as being Traits::BaseClass
342  // else define as being GaudiAlgorithm
343  template <typename Tr>
344  using BaseClass_t = Gaudi::cpp17::detected_or_t<GaudiAlgorithm, detail2::BaseClass_t, Tr>;
345 
346  // check whether Traits::{Input,Output}Handle<T> is a valid type,
347  // if so, define {Input,Output}Handle_t<Traits,T> as being Traits::{Input,Output}Handle<T>
348  // else define as being DataObject{Read,,Write}Handle<T>
349  template <typename Tr, typename T>
350  using OutputHandle_t = Gaudi::cpp17::detected_or_t<DataObjectWriteHandle<T>, detail2::OutputHandle_t, Tr, T>;
351  template <typename Tr, typename T>
352  using InputHandle_t = Gaudi::cpp17::detected_or_t<DataObjectReadHandle<T>, detail2::InputHandle_t, Tr, T>;
353 
355 
356  template <typename Handles>
358  {
359  Handles handles;
360  handles.reserve( init.size() );
361  std::transform( init.begin(), init.end(), std::back_inserter( handles ),
362  [&]( const std::string& loc ) -> typename Handles::value_type {
363  return {loc, owner};
364  } );
365  return handles;
366  }
367 
369  // given a pack, return a corresponding tuple
370  template <typename... In>
372  using type = std::tuple<In...>;
373 
374  static_assert( !details::disjunction<std::is_same<EventContext, In>...>::value,
375  "EventContext can only appear as first argument" );
376 
377  template <typename Algorithm, typename Handles>
378  static auto apply( const Algorithm& algo, Handles& handles )
379  {
380  return Gaudi::apply( [&]( const auto&... handle ) { return algo( details::deref( handle.get() )... ); },
381  handles );
382  }
383  };
384 
385  // except when it starts with EventContext, then drop it
386  template <typename... In>
388  using type = std::tuple<In...>;
389 
390  static_assert( !details::disjunction<std::is_same<EventContext, In>...>::value,
391  "EventContext can only appear as first argument" );
392 
393  template <typename Algorithm, typename Handles>
394  static auto apply( const Algorithm& algo, Handles& handles )
395  {
396  return Gaudi::apply(
397  [&]( const auto&... handle ) {
398  return algo( Gaudi::Hive::currentContext(), details::deref( handle.get() )... );
399  },
400  handles );
401  }
402  };
403 
404  template <typename... In>
406 
407  template <typename OutputSpec, typename InputSpec, typename Traits_>
409 
410  template <typename... Out, typename... In, typename Traits_>
411  class DataHandleMixin<std::tuple<Out...>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_>
412  {
413  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
414  "BaseClass must inherit from Algorithm" );
415 
416  template <typename IArgs, typename OArgs, std::size_t... I, std::size_t... J>
417  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator, const IArgs& inputs,
418  std::index_sequence<I...>, const OArgs& outputs, std::index_sequence<J...> )
419  : BaseClass_t<Traits_>( name, pSvcLocator )
420  , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... )
421  , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... )
422  {
423  // make sure this algorithm is seen as reentrant by Gaudi
424  this->setProperty( "Cardinality", 0 );
425  }
426 
427  public:
429  constexpr static std::size_t N_in = sizeof...( In );
430  constexpr static std::size_t N_out = sizeof...( Out );
431 
432  // generic constructor: N -> M
434  const std::array<KeyValue, N_out>& outputs )
435  : DataHandleMixin( name, pSvcLocator, inputs, std::index_sequence_for<In...>{}, outputs,
436  std::index_sequence_for<Out...>{} )
437  {
438  }
439 
440  // special cases: forward to the generic case...
441  // 1 -> 1
442  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input, const KeyValue& output )
443  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input}, std::array<KeyValue, 1>{output} )
444  {
445  }
446  // 1 -> N
447  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input,
448  const std::array<KeyValue, N_out>& outputs )
449  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input}, outputs )
450  {
451  }
452  // N -> 1
454  const KeyValue& output )
455  : DataHandleMixin( name, locator, inputs, std::array<KeyValue, 1>{output} )
456  {
457  }
458 
459  template <std::size_t N = 0>
460  const std::string& inputLocation() const
461  {
462  return std::get<N>( m_inputs ).objKey();
463  }
464  constexpr unsigned int inputLocationSize() const { return N_in; }
465 
466  template <std::size_t N = 0>
468  {
469  return std::get<N>( m_outputs ).objKey();
470  }
471  constexpr unsigned int outputLocationSize() const { return N_out; }
472 
473  protected:
476  };
477 
478  template <typename Traits_>
479  class DataHandleMixin<void, std::tuple<>, Traits_> : public BaseClass_t<Traits_>
480  {
481  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
482  "BaseClass must inherit from Algorithm" );
483 
484  public:
485  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator ) : BaseClass_t<Traits_>( name, pSvcLocator )
486  {
487  // make sure this algorithm is seen as reentrant by Gaudi
488  this->setProperty( "Cardinality", 0 );
489  }
490 
491  protected:
493  };
494 
495  template <typename... In, typename Traits_>
496  class DataHandleMixin<void, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_>
497  {
498  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
499  "BaseClass must inherit from Algorithm" );
500 
501  template <typename IArgs, std::size_t... I>
502  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator, const IArgs& inputs,
503  std::index_sequence<I...> )
504  : BaseClass_t<Traits_>( name, pSvcLocator )
505  , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... )
506  {
507  // make sure this algorithm is seen as reentrant by Gaudi
508  this->setProperty( "Cardinality", 0 );
509  }
510 
511  public:
513  constexpr static std::size_t N_in = sizeof...( In );
514 
515  // generic constructor: N -> 0
517  : DataHandleMixin( name, pSvcLocator, inputs, std::index_sequence_for<In...>{} )
518  {
519  }
520 
521  // special cases: forward to the generic case...
522  // 1 -> 0
523  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input )
524  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input} )
525  {
526  }
527 
528  template <std::size_t N = 0>
529  const std::string& inputLocation() const
530  {
531  return std::get<N>( m_inputs ).objKey();
532  }
533  constexpr unsigned int inputLocationSize() const { return N_in; }
534 
535  protected:
537  };
538 
539  template <typename... Out, typename Traits_>
540  class DataHandleMixin<std::tuple<Out...>, void, Traits_> : public BaseClass_t<Traits_>
541  {
542  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
543  "BaseClass must inherit from Algorithm" );
544 
545  template <typename OArgs, std::size_t... J>
546  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator, const OArgs& outputs,
547  std::index_sequence<J...> )
548  : BaseClass_t<Traits_>( name, pSvcLocator )
549  , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... )
550  {
551  // make sure this algorithm is seen as reentrant by Gaudi
552  this->setProperty( "Cardinality", 0 );
553  }
554 
555  public:
557  constexpr static std::size_t N_out = sizeof...( Out );
558 
559  // generic constructor: 0 -> N
561  : DataHandleMixin( name, pSvcLocator, outputs, std::index_sequence_for<Out...>{} )
562  {
563  }
564 
565  // 0 -> 1
567  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{output} )
568  {
569  }
570 
571  template <std::size_t N = 0>
573  {
574  return std::get<N>( m_outputs ).objKey();
575  }
576  constexpr unsigned int outputLocationSize() const { return N_out; }
577 
578  protected:
580  };
581 
583  template <typename Fun, typename Container, typename... Args>
584  constexpr void applyPostProcessing( const Fun&, Container&, Args... )
585  {
586  static_assert( sizeof...( Args ) == 0, "Args should not be used!" );
587  }
588 
589  template <typename Fun, typename Container>
590  auto applyPostProcessing( const Fun& fun, Container& c ) -> decltype( fun.postprocess( c ), void() )
591  {
592  fun.postprocess( c );
593  }
594 
596  }
597  }
598 }
599 
600 #endif
typename Tr::template InputHandle< T > InputHandle_t
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_out > &outputs)
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_in > &inputs)
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:1243
#define UNLIKELY(x)
Definition: Kernel.h:122
constexpr static const auto FAILURE
Definition: StatusCode.h:88
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >, const OArgs &outputs, std::index_sequence< J... >)
const In & operator()(const In &in) const
Define general base for Gaudi exception.
DataHandleMixin(const std::string &name, ISvcLocator *locator, const std::array< KeyValue, N_in > &inputs, const KeyValue &output)
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
friend bool operator!=(const iterator &lhs, const iterator &rhs)
void as_const(T &&t)=delete
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:332
auto operator()(Container &c, c_remove_ptr_t< Container > &&v) const
Gaudi::cpp17::detected_or_t< DataObjectReadHandle< T >, detail2::InputHandle_t, Tr, T > InputHandle_t
void printSizes(OS &out, Arg &&arg)
Print the parameter.
constexpr struct Gaudi::Functional::details::insert_t insert
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const std::array< KeyValue, N_in > &inputs, const std::array< KeyValue, N_out > &outputs)
Header file for class GaudiAlgorithm.
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &input, const KeyValue &output)
std::add_const_t< std::remove_pointer_t< Container >> val_t
STL namespace.
class MergingTransformer< Out(const vector_of_const_< In > void
decltype(auto) constexpr apply(F &&f, Tuple &&t) noexcept(noexcept( detail::apply_impl(std::forward< F >(f), std::forward< Tuple >(t), std::make_index_sequence< std::tuple_size< std::remove_reference_t< Tuple >>::value >{})))
Definition: apply.h:31
typename filter_evtcontext_t< In... >::type filter_evtcontext
auto operator()(Container &c, Value &&v) const -> decltype(c.push_back(v))
T end(T...args)
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const OArgs &outputs, std::index_sequence< J... >)
void push_back(Container &c, const Value &v, std::true_type)
std::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
This class represents an entry point to all the event specific data.
Definition: EventContext.h:24
T * deref_if(T *const t, std::false_type)
const Container & operator[](size_type i) const
constexpr struct Gaudi::Functional::details::deref_t deref
constexpr auto size(const C &c) noexcept(noexcept(c.size())) -> decltype(c.size())
STL class.
std::conditional_t< is_optional, ptr_t, val_t > value_type
DataObjectHandle.h GaudiKernel/DataObjectHandle.h.
Definition: AlgTool.h:26
typename Tr::template OutputHandle< T > OutputHandle_t
constexpr void applyPostProcessing(const Fun &, Container &, Args...)
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &input, const std::array< KeyValue, N_out > &outputs)
auto operator()(const Handle< I > &h) -> const In &
static auto apply(const Algorithm &algo, Handles &handles)
typename details2::remove_optional< T >::type remove_optional_t
GAUDI_API const EventContext & currentContext()
auto operator()(const Handle< I > &h) -> const In
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &output)
static auto apply(const Algorithm &algo, Handles &handles)
decltype(auto) range(Args &&...args)
Zips multiple containers together to form a single range.
T move(T...args)
decltype(auto) verifySizes(Args &...args)
Verify the data container sizes have the same sizes.
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator)
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:78
T size(T...args)
T * put(std::unique_ptr< T > object)
Register object in transient store.
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
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.
Gaudi::cpp17::detected_or_t< DataObjectWriteHandle< T >, detail2::OutputHandle_t, Tr, T > OutputHandle_t
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)
struct[[deprecated("use MergingTransformer instead")]] Traits_
T transform(T...args)
const In & operator()(const In *in) const
decltype(auto) const_range(Args &&...args)
Zips multiple containers together to form a single const range.
Handles make_vector_of_handles(IDataHandleHolder *owner, const std::vector< std::string > &init)
T & deref_if(T *const t, std::true_type)
Helper functions to set/get the application return code.
Definition: __init__.py:1
Gaudi::cpp17::detected_or_t< GaudiAlgorithm, detail2::BaseClass_t, Tr > BaseClass_t
Out1 * put(DataObjectHandle< Out1 > &out_handle, Out2 &&out)
void push_back(Container &c, const Value &v, std::false_type)
DataHandleMixin(const std::string &name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >)
T reserve(T...args)
typename ContainerVector::size_type size_type