Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 #include "GaudiKernel/invoke.h"
18 
19 // Boost
20 #include "boost/optional.hpp"
21 
22 // Range V3
23 #include <range/v3/view/const.hpp>
24 #include <range/v3/view/zip.hpp>
25 
26 namespace Gaudi {
27  namespace Functional {
28  namespace details {
29 
30  // CRJ : Stuff for zipping
31  namespace zip {
32 
34  template <typename OS, typename Arg>
35  void printSizes( OS& out, Arg&& arg ) {
36  out << "SizeOf'" << System::typeinfoName( typeid( Arg ) ) << "'=" << std::forward<Arg>( arg ).size();
37  }
38 
40  template <typename OS, typename Arg, typename... Args>
41  void printSizes( OS& out, Arg&& arg, Args&&... args ) {
42  printSizes( out, arg );
43  out << ", ";
44  printSizes( out, args... );
45  }
46 
48  template <typename A>
49  inline bool check_sizes( const A& ) noexcept {
50  return true;
51  }
52 
54  template <typename A, typename B>
55  inline bool check_sizes( const A& a, const B& b ) noexcept {
56  return a.size() == b.size();
57  }
58 
60  template <typename A, typename B, typename... C>
61  inline bool check_sizes( const A& a, const B& b, const C&... c ) noexcept {
62  return ( check_sizes( a, b ) && check_sizes( b, c... ) );
63  }
64 
66  template <typename... Args>
67  inline decltype( auto ) verifySizes( Args&... args ) {
68  if ( UNLIKELY( !check_sizes( args... ) ) ) {
69  std::ostringstream mess;
70  mess << "Zipped containers have different sizes : ";
71  printSizes( mess, args... );
72  throw GaudiException( mess.str(), "Gaudi::Functional::details::zip::verifySizes", StatusCode::FAILURE );
73  }
74  }
75 
77  template <typename... Args>
78  inline decltype( auto ) range( Args&&... args ) {
79 #ifndef NDEBUG
80  verifySizes( args... );
81 #endif
82  return ranges::view::zip( std::forward<Args>( args )... );
83  }
84 
86  template <typename... Args>
87  inline decltype( auto ) const_range( Args&&... args ) {
88 #ifndef NDEBUG
89  verifySizes( args... );
90 #endif
91  return ranges::view::const_( ranges::view::zip( std::forward<Args>( args )... ) );
92  }
93  } // namespace zip
94 
95 #if __cplusplus < 201703L
96  // implementation of C++17 std::as_const, see http://en.cppreference.com/w/cpp/utility/as_const
97  template <typename T>
98  constexpr std::add_const_t<T>& as_const( T& t ) noexcept {
99  return t;
100  }
101 
102  template <typename T>
103  void as_const( T&& t ) = delete;
104 
105  template <class...>
107  template <class B1>
108  struct disjunction<B1> : B1 {};
109  template <class B1, class... Bn>
110  struct disjunction<B1, Bn...> : std::conditional_t<bool( B1::value ), B1, disjunction<Bn...>> {};
111 
112 #else
113  using std::as_const;
114  using std::disjunction;
115 #endif
116  namespace details2 {
118  // note: boost::optional in boost 1.66 does not have 'has_value()'...
119  // that requires boost 1.68 or later... so for now, use operator bool() instead ;-(
120  template <typename T>
121  using is_optional_ = decltype( bool( std::declval<T>() ), std::declval<T>().value() );
122  } // namespace details2
123  template <typename Arg>
124  using is_optional = typename Gaudi::cpp17::is_detected<details2::is_optional_, Arg>;
125 
126  template <typename Arg>
127  using require_is_optional = std::enable_if_t<is_optional<Arg>::value>;
128 
129  template <typename Arg>
130  using require_is_not_optional = std::enable_if_t<!is_optional<Arg>::value>;
131 
132  namespace details2 {
133  template <typename T, typename = void>
135  using type = T;
136  };
137 
138  template <typename T>
139  struct remove_optional<T, std::enable_if_t<is_optional<T>::value>> {
140  using type = typename T::value_type;
141  };
142  } // namespace details2
143 
144  template <typename T>
146 
147  constexpr struct invoke_optionally_t {
148  template <typename F, typename Arg, typename = require_is_not_optional<Arg>>
149  decltype( auto ) operator()( F&& f, Arg&& arg ) const {
150  return Gaudi::invoke( std::forward<F>( f ), std::forward<Arg>( arg ) );
151  }
152  template <typename F, typename Arg, typename = require_is_optional<Arg>>
153  void operator()( F&& f, Arg&& arg ) const {
154  if ( arg ) Gaudi::invoke( std::forward<F>( f ), *std::forward<Arg>( arg ) );
155  }
156  } invoke_optionally{};
158 
159  template <typename Out1, typename Out2,
160  typename = std::enable_if_t<std::is_constructible<Out1, Out2>::value &&
162  Out1* put( DataObjectHandle<Out1>& out_handle, Out2&& out ) {
163  return out_handle.put( std::make_unique<Out1>( std::forward<Out2>( out ) ) );
164  }
165 
166  template <typename Out1, typename Out2, typename = std::enable_if_t<std::is_constructible<Out1, Out2>::value>>
167  void put( DataObjectHandle<AnyDataWrapper<Out1>>& out_handle, Out2&& out ) {
168  out_handle.put( std::forward<Out2>( out ) );
169  }
170 
171  // optional put
172  template <typename OutHandle, typename OptOut, typename = require_is_optional<OptOut>>
173  void put( OutHandle& out_handle, OptOut&& out ) {
174  if ( out ) put( out_handle, *std::forward<OptOut>( out ) );
175  }
177  // adapt to differences between eg. std::vector (which has push_back) and KeyedContainer (which has insert)
178  // adapt to getting a T, and a container wanting T* by doing new T{ std::move(out) }
179  // adapt to getting a optional<T>
180 
181  constexpr struct insert_t {
182  // for Container<T*>, return T
183  template <typename Container>
184  using c_remove_ptr_t = std::remove_pointer_t<typename Container::value_type>;
185 
186  template <typename Container, typename Value>
187  auto operator()( Container& c, Value&& v ) const -> decltype( c.push_back( v ) ) {
188  return c.push_back( std::forward<Value>( v ) );
189  }
190 
191  template <typename Container, typename Value>
192  auto operator()( Container& c, Value&& v ) const -> decltype( c.insert( v ) ) {
193  return c.insert( std::forward<Value>( v ) );
194  }
195 
196  // Container<T*> with T&& as argument
197  template <typename Container,
198  typename = std::enable_if_t<std::is_pointer<typename Container::value_type>::value>>
199  auto operator()( Container& c, c_remove_ptr_t<Container>&& v ) const {
200  return operator()( c, new c_remove_ptr_t<Container>{std::move( v )} );
201  }
202 
203  } insert{};
204 
206 
207  constexpr struct deref_t {
208  template <typename In, typename = std::enable_if_t<!std::is_pointer<In>::value>>
209  const In& operator()( const In& in ) const {
210  return in;
211  }
212 
213  template <typename In>
214  const In& operator()( const In* in ) const {
215  assert( in != nullptr );
216  return *in;
217  }
218  } deref{};
219 
221  // if Container is a pointer, then we're optional items
222  namespace details2 {
223  template <typename Container, typename Value>
224  void push_back( Container& c, const Value& v, std::true_type ) {
225  c.push_back( v );
226  }
227  template <typename Container, typename Value>
228  void push_back( Container& c, const Value& v, std::false_type ) {
229  c.push_back( &v );
230  }
231 
232  template <typename In>
234  template <template <typename> class Handle, typename I,
235  typename = std::enable_if_t<std::is_convertible<I, In>::value>>
236  auto operator()( const Handle<I>& h ) -> const In& {
237  return *h.get();
238  }
239  template <template <typename> class Handle, typename I,
240  typename = std::enable_if_t<std::is_convertible<I*, In>::value>>
241  auto operator()( const Handle<I>& h ) -> const In {
242  return h.getIfExists();
243  } // In is-a pointer
244  };
245 
246  template <typename T>
247  T* deref_if( T* const t, std::false_type ) {
248  return t;
249  }
250  template <typename T>
251  T& deref_if( T* const t, std::true_type ) {
252  return *t;
253  }
254  } // namespace details2
255 
256  template <typename Container>
258  static constexpr bool is_pointer = std::is_pointer<Container>::value;
259  using val_t = std::add_const_t<std::remove_pointer_t<Container>>;
260  using ptr_t = std::add_pointer_t<val_t>;
261  using ref_t = std::add_lvalue_reference_t<val_t>;
264 
265  public:
266  using value_type = std::conditional_t<is_pointer, ptr_t, val_t>;
267  using size_type = typename ContainerVector::size_type;
268  class iterator {
269  typename ContainerVector::const_iterator m_i;
270  friend class vector_of_const_;
271  iterator( typename ContainerVector::const_iterator iter ) : m_i( iter ) {}
272  using ret_t = std::conditional_t<is_pointer, ptr_t, ref_t>;
273 
274  public:
275  friend bool operator!=( const iterator& lhs, const iterator& rhs ) { return lhs.m_i != rhs.m_i; }
278  ++m_i;
279  return *this;
280  }
282  --m_i;
283  return *this;
284  }
285  bool is_null() const { return !*m_i; }
286  explicit operator bool() const { return !is_null(); }
287  };
288  vector_of_const_() = default;
289  void reserve( size_type size ) { m_containers.reserve( size ); }
290  template <typename T> // , typename = std::is_convertible<T,std::conditional_t<is_pointer,ptr_t,val_t>>
291  void push_back( T&& container ) {
292  details2::push_back( m_containers, std::forward<T>( container ), std::integral_constant<bool, is_pointer>{} );
293  } // note: does not copy its argument, so we're not really a container...
294  iterator begin() const { return m_containers.begin(); }
295  iterator end() const { return m_containers.end(); }
296  size_type size() const { return m_containers.size(); }
297 
298  template <typename X = Container>
299  std::enable_if_t<!std::is_pointer<X>::value, ref_t> operator[]( size_type i ) const {
300  return *m_containers[i];
301  }
302 
303  template <typename X = Container>
304  std::enable_if_t<std::is_pointer<X>::value, ptr_t> operator[]( size_type i ) const {
305  return m_containers[i];
306  }
307 
308  template <typename X = Container>
309  std::enable_if_t<!std::is_pointer<X>::value, ref_t> at( size_type i ) const {
310  return *m_containers[i];
311  }
312 
313  template <typename X = Container>
314  std::enable_if_t<std::is_pointer<X>::value, ptr_t> at( size_type i ) const {
315  return m_containers[i];
316  }
317 
318  bool is_null( size_type i ) const { return !m_containers[i]; }
319  };
320 
322  namespace detail2 { // utilities for detected_or_t{,_} usage
323  template <typename Tr>
324  using BaseClass_t = typename Tr::BaseClass;
325  template <typename Tr, typename T>
326  using OutputHandle_t = typename Tr::template OutputHandle<T>;
327  template <typename Tr, typename T>
328  using InputHandle_t = typename Tr::template InputHandle<T>;
329  } // namespace detail2
330 
331  // check whether Traits::BaseClass is a valid type,
332  // if so, define BaseClass_t<Traits> as being Traits::BaseClass
333  // else define as being GaudiAlgorithm
334  template <typename Tr>
335  using BaseClass_t = Gaudi::cpp17::detected_or_t<GaudiAlgorithm, detail2::BaseClass_t, Tr>;
336 
337  // check whether Traits::{Input,Output}Handle<T> is a valid type,
338  // if so, define {Input,Output}Handle_t<Traits,T> as being Traits::{Input,Output}Handle<T>
339  // else define as being DataObject{Read,,Write}Handle<T>
340  template <typename Tr, typename T>
341  using OutputHandle_t = Gaudi::cpp17::detected_or_t<DataObjectWriteHandle<T>, detail2::OutputHandle_t, Tr, T>;
342  template <typename Tr, typename T>
343  using InputHandle_t = Gaudi::cpp17::detected_or_t<DataObjectReadHandle<T>, detail2::InputHandle_t, Tr, T>;
344 
346 
347  template <typename Handles>
349  Handles handles;
350  handles.reserve( init.size() );
351  std::transform( init.begin(), init.end(),
352  std::back_inserter( handles ), [&]( const std::string& loc ) -> typename Handles::value_type {
353  return {loc, owner};
354  } );
355  return handles;
356  }
357 
359  // given a pack, return a corresponding tuple
360  template <typename... In>
362  using type = std::tuple<In...>;
363 
364  static_assert( !details::disjunction<std::is_same<EventContext, In>...>::value,
365  "EventContext can only appear as first argument" );
366 
367  template <typename Algorithm, typename Handles>
368  static auto apply( const Algorithm& algo, Handles& handles ) {
369  return Gaudi::apply( [&]( const auto&... handle ) { return algo( details::deref( handle.get() )... ); },
370  handles );
371  }
372  };
373 
374  // except when it starts with EventContext, then drop it
375  template <typename... In>
377  using type = std::tuple<In...>;
378 
379  static_assert( !details::disjunction<std::is_same<EventContext, In>...>::value,
380  "EventContext can only appear as first argument" );
381 
382  template <typename Algorithm, typename Handles>
383  static auto apply( const Algorithm& algo, Handles& handles ) {
384  return Gaudi::apply(
385  [&]( const auto&... handle ) {
386  return algo( Gaudi::Hive::currentContext(), details::deref( handle.get() )... );
387  },
388  handles );
389  }
390  };
391 
392  template <typename... In>
394 
395  template <typename OutputSpec, typename InputSpec, typename Traits_>
397 
398  template <typename... Out, typename... In, typename Traits_>
399  class DataHandleMixin<std::tuple<Out...>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
400  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
401  "BaseClass must inherit from Algorithm" );
402 
403  template <typename IArgs, typename OArgs, std::size_t... I, std::size_t... J>
404  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator, const IArgs& inputs,
405  std::index_sequence<I...>, const OArgs& outputs, std::index_sequence<J...> )
406  : BaseClass_t<Traits_>( name, pSvcLocator )
407  , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... )
408  , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
409  // make sure this algorithm is seen as reentrant by Gaudi
410  this->setProperty( "Cardinality", 0 );
411  }
412 
413  public:
415  constexpr static std::size_t N_in = sizeof...( In );
416  constexpr static std::size_t N_out = sizeof...( Out );
417 
418  // generic constructor: N -> M
420  const std::array<KeyValue, N_out>& outputs )
421  : DataHandleMixin( name, pSvcLocator, inputs, std::index_sequence_for<In...>{}, outputs,
422  std::index_sequence_for<Out...>{} ) {}
423 
424  // special cases: forward to the generic case...
425  // 1 -> 1
426  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input, const KeyValue& output )
427  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input}, std::array<KeyValue, 1>{output} ) {}
428  // 1 -> N
429  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input,
430  const std::array<KeyValue, N_out>& outputs )
431  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input}, outputs ) {}
432  // N -> 1
434  const KeyValue& output )
435  : DataHandleMixin( name, locator, inputs, std::array<KeyValue, 1>{output} ) {}
436 
437  template <std::size_t N = 0>
438  const std::string& inputLocation() const {
439  return std::get<N>( m_inputs ).objKey();
440  }
441  constexpr unsigned int inputLocationSize() const { return N_in; }
442 
443  template <std::size_t N = 0>
444  const std::string& outputLocation() const {
445  return std::get<N>( m_outputs ).objKey();
446  }
447  constexpr unsigned int outputLocationSize() const { return N_out; }
448 
449  protected:
450  bool isReEntrant() const override { return true; }
451 
454  };
455 
456  template <typename Traits_>
457  class DataHandleMixin<void, std::tuple<>, Traits_> : public BaseClass_t<Traits_> {
458  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
459  "BaseClass must inherit from Algorithm" );
460 
461  public:
462  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator )
463  : BaseClass_t<Traits_>( name, pSvcLocator ) {
464  // make sure this algorithm is seen as reentrant by Gaudi
465  this->setProperty( "Cardinality", 0 );
466  }
467 
468  protected:
469  bool isReEntrant() const override { return true; }
470 
472  };
473 
474  template <typename... In, typename Traits_>
475  class DataHandleMixin<void, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
476  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
477  "BaseClass must inherit from Algorithm" );
478 
479  template <typename IArgs, std::size_t... I>
480  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator, const IArgs& inputs,
481  std::index_sequence<I...> )
482  : BaseClass_t<Traits_>( name, pSvcLocator )
483  , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... ) {
484  // make sure this algorithm is seen as reentrant by Gaudi
485  this->setProperty( "Cardinality", 0 );
486  }
487 
488  public:
490  constexpr static std::size_t N_in = sizeof...( In );
491 
492  // generic constructor: N -> 0
494  : DataHandleMixin( name, pSvcLocator, inputs, std::index_sequence_for<In...>{} ) {}
495 
496  // special cases: forward to the generic case...
497  // 1 -> 0
498  DataHandleMixin( const std::string& name, ISvcLocator* locator, const KeyValue& input )
499  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{input} ) {}
500 
501  template <std::size_t N = 0>
502  const std::string& inputLocation() const {
503  return std::get<N>( m_inputs ).objKey();
504  }
505  constexpr unsigned int inputLocationSize() const { return N_in; }
506 
507  protected:
508  bool isReEntrant() const override { return true; }
509 
511  };
512 
513  template <typename... Out, typename Traits_>
514  class DataHandleMixin<std::tuple<Out...>, void, Traits_> : public BaseClass_t<Traits_> {
515  static_assert( std::is_base_of<Algorithm, BaseClass_t<Traits_>>::value,
516  "BaseClass must inherit from Algorithm" );
517 
518  template <typename OArgs, std::size_t... J>
519  DataHandleMixin( const std::string& name, ISvcLocator* pSvcLocator, const OArgs& outputs,
520  std::index_sequence<J...> )
521  : BaseClass_t<Traits_>( name, pSvcLocator )
522  , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
523  // make sure this algorithm is seen as reentrant by Gaudi
524  this->setProperty( "Cardinality", 0 );
525  }
526 
527  public:
529  constexpr static std::size_t N_out = sizeof...( Out );
530 
531  // generic constructor: 0 -> N
533  : DataHandleMixin( name, pSvcLocator, outputs, std::index_sequence_for<Out...>{} ) {}
534 
535  // 0 -> 1
537  : DataHandleMixin( name, locator, std::array<KeyValue, 1>{output} ) {}
538 
539  template <std::size_t N = 0>
540  const std::string& outputLocation() const {
541  return std::get<N>( m_outputs ).objKey();
542  }
543  constexpr unsigned int outputLocationSize() const { return N_out; }
544 
545  protected:
546  bool isReEntrant() const override { return true; }
547 
549  };
550 
552  template <typename Fun, typename Container, typename... Args>
553  constexpr void applyPostProcessing( const Fun&, Container&, Args... ) {
554  static_assert( sizeof...( Args ) == 0, "Args should not be used!" );
555  }
556 
557  template <typename Fun, typename Container>
558  auto applyPostProcessing( const Fun& fun, Container& c ) -> decltype( fun.postprocess( c ), void() ) {
559  fun.postprocess( c );
560  }
561 
563  } // namespace details
564  } // namespace Functional
565 } // namespace Gaudi
566 
567 #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)
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:1178
std::enable_if_t< std::is_pointer< X >::value, ptr_t > at(size_type i) const
#define UNLIKELY(x)
Definition: Kernel.h:89
std::enable_if_t<!std::is_pointer< X >::value, ref_t > operator[](size_type i) const
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
auto operator()(const Handle< I > &h) -> const In &
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:309
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.
std::enable_if_t<!std::is_pointer< X >::value, ref_t > at(size_type i) const
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
decltype(bool(std::declval< T >()), std::declval< T >().value()) is_optional_
typename Gaudi::cpp17::is_detected< details2::is_optional_, Arg > is_optional
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:27
typename filter_evtcontext_t< In... >::type filter_evtcontext
T end(T...args)
std::enable_if_t<!is_optional< Arg >::value > require_is_not_optional
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:31
T * deref_if(T *const t, std::false_type)
constexpr struct Gaudi::Functional::details::deref_t deref
constexpr auto size(const C &c) noexcept(noexcept(c.size())) -> decltype(c.size())
STL class.
DataObjectHandle.h GaudiKernel/DataObjectHandle.h.
Definition: AlgTool.h:26
constexpr struct Gaudi::Functional::details::invoke_optionally_t invoke_optionally
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)
class MergingTransformer< Out(const vector_of_const_< In > Traits_
static auto apply(const Algorithm &algo, Handles &handles)
typename details2::remove_optional< T >::type remove_optional_t
T * put(std::unique_ptr< T > object) const
Register object in transient store.
GAUDI_API const EventContext & currentContext()
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.
std::conditional_t< is_pointer, ptr_t, ref_t > ret_t
auto operator()(Container &c, Value &&v) const -> decltype(c.insert(v))
T move(T...args)
std::conditional_t< is_pointer, ptr_t, val_t > value_type
std::enable_if_t< std::is_pointer< X >::value, ptr_t > operator[](size_type i) const
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
std::enable_if_t< is_optional< Arg >::value > require_is_optional
T size(T...args)
std::vector< InputHandle_t< In > > m_inputs
struct GAUDI_API array
Parametrisation class for redirection array - like implementation.
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
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
auto operator()(Container &c, Value &&v) const -> decltype(c.push_back(v))
T back_inserter(T...args)
std::tuple< details::OutputHandle_t< Traits_, Out >... > m_outputs
double fun(const std::vector< double > &x)
Definition: PFuncTest.cpp:26
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:79
STL class.
constexpr static const auto FAILURE
Definition: StatusCode.h:86
DataHandleMixin(const std::string &name, ISvcLocator *locator, const KeyValue &input)
T transform(T...args)
auto invoke(F &&f, ArgTypes &&...args) noexcept(noexcept(detail2::INVOKE(std::forward< F >(f), std::forward< ArgTypes >(args)...))) -> decltype(detail2::INVOKE(std::forward< F >(f), std::forward< ArgTypes >(args)...))
Definition: invoke.h:82
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)
auto operator()(const Handle< I > &h) -> const In
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