The Gaudi Framework  master (181af51f)
Loading...
Searching...
No Matches
details.h
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 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#pragma once
12
13#include <Gaudi/Algorithm.h>
17#include <GaudiKernel/IBinder.h>
19#include <cassert>
20#include <sstream>
21#include <type_traits>
22
23#if defined( __cpp_lib_ranges_zip ) && defined( __cpp_lib_ranges_as_const )
24# define GAUDI_FUNCTIONAL_USES_STD_RANGES 1
25# include <ranges>
26#else
27# include <range/v3/view/const.hpp>
28# include <range/v3/view/zip.hpp>
29#endif
30
32
33 // CRJ : Stuff for zipping
34 namespace zip {
35
37 template <typename OS, typename Arg>
38 void printSizes( OS& out, Arg&& arg ) {
39 out << "SizeOf'" << System::typeinfoName( typeid( Arg ) ) << "'=" << std::forward<Arg>( arg ).size();
40 }
41
43 template <typename OS, typename Arg, typename... Args>
44 void printSizes( OS& out, Arg&& arg, Args&&... args ) {
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 return true;
54 }
55
57 template <typename A, typename B>
58 inline bool check_sizes( const A& a, const B& b ) noexcept {
59 return a.size() == b.size();
60 }
61
63 template <typename A, typename B, typename... C>
64 inline bool check_sizes( const A& a, const B& b, const C&... c ) noexcept {
65 return ( check_sizes( a, b ) && check_sizes( b, c... ) );
66 }
67
69 template <typename... Args>
70 inline decltype( auto ) verifySizes( Args&... args ) {
71 if ( !check_sizes( args... ) ) {
72 std::ostringstream mess;
73 mess << "Zipped containers have different sizes : ";
74 printSizes( mess, args... );
75 throw GaudiException( mess.str(), "Gaudi::Functional::details::zip::verifySizes", StatusCode::FAILURE );
76 }
77 }
78
80 template <typename... Args>
81 inline decltype( auto ) range( Args&&... args ) {
82#ifndef NDEBUG
83 verifySizes( args... );
84#endif
85#if defined( GAUDI_FUNCTIONAL_USES_STD_RANGES )
86 return std::ranges::zip_view( std::forward<Args>( args )... );
87#else
88 return ranges::views::zip( std::forward<Args>( args )... );
89#endif
90 }
91
93 template <typename... Args>
94 inline decltype( auto ) const_range( Args&&... args ) {
95#ifndef NDEBUG
96 verifySizes( args... );
97#endif
98#if defined( GAUDI_FUNCTIONAL_USES_STD_RANGES )
99 return std::ranges::as_const_view( std::ranges::zip_view( std::forward<Args>( args )... ) );
100#else
101 return ranges::views::const_( ranges::views::zip( std::forward<Args>( args )... ) );
102#endif
103 }
104 } // namespace zip
105
106 inline std::vector<DataObjID> to_DataObjID( const std::vector<std::string>& in ) {
107 std::vector<DataObjID> out;
108 out.reserve( in.size() );
109 std::transform( in.begin(), in.end(), std::back_inserter( out ),
110 []( const std::string& i ) { return DataObjID{ i }; } );
111 return out;
112 }
113
115 template <typename T>
116 concept is_optional = requires( T const& t ) {
117 t.has_value();
118 t.value();
119 typename T::value_type;
120 };
121
122 namespace details2 {
123
124 template <typename T>
126 using type = T;
127 };
128
129 template <is_optional T>
130 struct value_type_of<T> {
131 using type = T::value_type;
132 };
133
134 } // namespace details2
135
136 template <typename T>
138
139 constexpr struct invoke_optionally_t {
140 template <typename F, typename Arg>
141 requires( !is_optional<Arg> )
142 decltype( auto ) operator()( F&& f, Arg&& arg ) const {
143 return std::invoke( std::forward<F>( f ), std::forward<Arg>( arg ) );
144 }
145 template <typename F, is_optional Arg>
146 void operator()( F&& f, Arg&& arg ) const {
147 if ( arg ) std::invoke( std::forward<F>( f ), *std::forward<Arg>( arg ) );
148 }
149 } invoke_optionally{};
151
152 template <typename Value, std::size_t... I>
153 auto get_values_helper( std::index_sequence<I...> ) {
154 return std::make_tuple( ( (void)I, Value{} )... );
155 }
156
157 template <typename Value, auto N>
158 using RepeatValues_ = decltype( get_values_helper<Value>( std::make_index_sequence<N>() ) );
159
161 template <std::derived_from<DataObject> Out1, std::convertible_to<Out1> Out2>
162 auto put( const 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, std::convertible_to<Out1> Out2>
167 auto put( const DataObjectHandle<AnyDataWrapper<Out1>>& out_handle, Out2&& out ) {
168 return out_handle.put( std::forward<Out2>( out ) );
169 }
170
171 // optional put
172 template <typename OutHandle, typename OptOut>
173 requires( is_optional<OptOut> )
174 void put( const OutHandle& out_handle, OptOut&& out ) {
175 if ( out ) put( out_handle, *std::forward<OptOut>( out ) );
176 }
177
179 // adapt to differences between eg. std::vector (which has push_back) and KeyedContainer (which has insert)
180 // adapt to getting a T, and a container wanting T* by doing new T{ std::move(out) }
181 // adapt to getting a optional<T>
182
183 constexpr struct insert_t {
184 // for Container<T*>, return T
185 template <typename Container>
186 using c_remove_ptr_t = std::remove_pointer_t<typename Container::value_type>;
187
188 template <typename Container, typename Value>
189 auto operator()( Container& c, Value&& v ) const -> decltype( c.push_back( v ) ) {
190 return c.push_back( std::forward<Value>( v ) );
191 }
192
193 template <typename Container, typename Value>
194 auto operator()( Container& c, Value&& v ) const -> decltype( c.insert( v ) ) {
195 return c.insert( std::forward<Value>( v ) );
196 }
197
198 // Container<T*> with T&& as argument
199 template <typename Container, typename Value>
200 requires( std::is_pointer_v<typename Container::value_type> &&
201 std::is_convertible_v<Value, c_remove_ptr_t<Container>> )
202 auto operator()( Container& c, Value&& v ) const {
203 return operator()( c, new c_remove_ptr_t<Container>{ std::forward<Value>( v ) } );
204 }
205
206 } insert{};
207
209
210 constexpr struct deref_t {
211 template <typename In>
212 requires( !std::is_pointer_v<In> )
213 const In& operator()( const In& in ) const {
214 return in;
215 }
216
217 template <typename In>
218 requires( !std::is_pointer_v<std::decay_t<In>> )
219 In operator()( In&& in ) const {
220 return std::forward<In>( in );
221 }
222
223 template <typename In>
224 const In& operator()( const In* in ) const {
225 assert( in != nullptr );
226 return *in;
227 }
228 } deref{};
229
231 // if Container is a pointer, then we're optional items
232 namespace details2 {
233 template <typename T>
234 constexpr static bool is_gaudi_range_v = false;
235
236 template <typename T>
237 constexpr static bool is_gaudi_range_v<Gaudi::Range_<T>> = true;
238
239 template <typename T>
240 constexpr static bool is_gaudi_range_v<Gaudi::NamedRange_<T>> = true;
241
242 template <typename T>
243 constexpr static bool is_gaudi_range_v<std::optional<Gaudi::NamedRange_<T>>> = true;
244
245 template <typename In>
247 template <template <typename> class Handle, std::convertible_to<In> I>
248 auto operator()( const Handle<I>& h ) -> const In& {
249 return *h.get();
250 }
251 template <template <typename> class Handle, typename I>
252 auto operator()( const Handle<Gaudi::Range_<I>>& h ) -> const In {
253 return h.get();
254 }
255 template <template <typename> class Handle, typename I>
256 auto operator()( const Handle<Gaudi::NamedRange_<I>>& h ) -> const In {
257 return h.get();
258 }
259 template <template <typename> class Handle, typename I>
260 auto operator()( const Handle<std::optional<Gaudi::NamedRange_<I>>>& h ) -> const In {
261 return h.get();
262 }
263 template <template <typename> class Handle, typename I>
264 requires( 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 Iterator>
272 using traits = std::iterator_traits<Iterator>;
274
275 public:
276 using iterator_category [[maybe_unused]] = typename traits::iterator_category;
277 using difference_type [[maybe_unused]] = typename traits::difference_type;
278 using reference = decltype( **m_iter );
279 using value_type [[maybe_unused]] = std::remove_reference_t<reference>;
280 using pointer [[maybe_unused]] = std::add_pointer_t<value_type>;
281
282 indirect_iterator() = default;
283 constexpr explicit indirect_iterator( Iterator i ) : m_iter( std::move( i ) ) {}
284
285 constexpr reference operator*() const { return **m_iter; }
286
287 constexpr bool operator==( const indirect_iterator& rhs ) const { return m_iter == rhs.m_iter; }
288
290 ++m_iter;
291 return *this;
292 }
293 constexpr indirect_iterator operator++( int ) {
294 auto i = *this;
295 ++*this;
296 return i;
297 }
298
299 // bidirectional iterator operations (if possible)
301 requires std::bidirectional_iterator<Iterator>
302 {
303 --m_iter;
304 return *this;
305 }
307 requires std::bidirectional_iterator<Iterator>
308 {
309 auto i = *this;
310 --*this;
311 return i;
312 }
313
314 // random access iterator operations (if possible)
315 constexpr indirect_iterator& operator+=( difference_type n )
316 requires std::random_access_iterator<Iterator>
317 {
318 m_iter += n;
319 return *this;
320 }
321 constexpr indirect_iterator operator+( difference_type n ) const
322 requires std::random_access_iterator<Iterator>
323 {
324 auto i = *this;
325 return i += n;
326 }
327 constexpr indirect_iterator& operator-=( difference_type n )
328 requires std::random_access_iterator<Iterator>
329 {
330 m_iter -= n;
331 return *this;
332 }
333 constexpr indirect_iterator operator-( difference_type n ) const
334 requires std::random_access_iterator<Iterator>
335 {
336 auto i = *this;
337 return i -= n;
338 }
339 constexpr difference_type operator-( const indirect_iterator& other ) const
340 requires std::random_access_iterator<Iterator>
341 {
342 return m_iter - other.m_iter;
343 }
344 constexpr reference operator[]( difference_type n ) const
345 requires std::random_access_iterator<Iterator>
346 {
347 return **( m_iter + n );
348 }
349 };
350
351 } // namespace details2
352
353 template <typename Container>
355 static constexpr bool is_pointer = std::is_pointer_v<Container>;
356 static constexpr bool is_range = details2::is_gaudi_range_v<Container>;
357 // TODO: refuse pointer to a range... range must always be by value
358 using val_t = std::add_const_t<std::remove_pointer_t<Container>>;
359 using ptr_t = std::add_pointer_t<val_t>;
360 using ContainerVector = std::vector<std::conditional_t<is_range, std::remove_const_t<val_t>, ptr_t>>;
362
363 constexpr static decltype( auto ) wrap( ContainerVector::const_reference t ) {
364 if constexpr ( is_pointer || is_range ) {
365 return t;
366 } else {
367 return *t;
368 }
369 }
370 constexpr static auto wrap( ContainerVector::const_iterator i ) {
371 if constexpr ( is_pointer || is_range ) {
372 return i;
373 } else {
374 return details2::indirect_iterator{ i };
375 }
376 }
377
378 public:
379 using value_type = std::conditional_t<is_pointer, ptr_t, val_t>;
380 using size_type = typename ContainerVector::size_type;
381
382 vector_of_const_() = default;
383 void reserve( size_type size ) { m_containers.reserve( size ); }
384 template <typename T>
385 void push_back( T&& container ) {
386 if constexpr ( is_pointer || is_range ) {
387 m_containers.push_back( container );
388 } else {
389 // note: does not copy its argument, so we're not really a container...
390 m_containers.push_back( &container );
391 }
392 }
393 auto begin() const { return wrap( m_containers.begin() ); }
394 auto end() const { return wrap( m_containers.end() ); }
395 decltype( auto ) front() const { return wrap( m_containers.front() ); }
396 decltype( auto ) back() const { return wrap( m_containers.back() ); }
397 decltype( auto ) operator[]( size_type i ) const { return wrap( m_containers[i] ); }
398 decltype( auto ) at( size_type i ) const { return wrap( m_containers.at( i ) ); }
399 size_type size() const { return m_containers.size(); }
400 };
401
403 namespace detail2 { // utilities for detected_or_t{,_} usage
404
405 // keep only for backwards compatibility... for now.
406 template <typename Tr>
407 using BaseClass_t = typename Tr::BaseClass;
408
409 template <typename Tr, typename Default>
410 struct BaseClass {
411 using type = Default;
412 };
413 template <typename Tr, typename Default>
414 requires requires { typename Tr::BaseClass; }
415 struct BaseClass<Tr, Default> {
416 using type = Tr::BaseClass;
417 };
418
419 template <typename T, typename Tr, template <typename...> typename Default>
421 using type = Default<T>;
422 };
423 template <typename T, typename Tr, template <typename...> typename Default>
424 requires requires { typename Tr::template OutputHandle<T>; }
425 struct OutputHandle<T, Tr, Default> {
426 using type = Tr::template OutputHandle<T>;
427 };
428
429 template <typename T, typename Tr, template <typename...> typename Default>
430 struct InputHandle {
431 using type = Default<T>;
432 };
433 template <typename T, typename Tr, template <typename...> typename Default>
434 requires requires { typename Tr::template InputHandle<T>; }
435 struct InputHandle<T, Tr, Default> {
436 using type = Tr::template InputHandle<T>;
437 };
438
439 template <typename T>
441 std::conditional_t<std::derived_from<std::decay_t<T>, IAlgTool>,
443 } // namespace detail2
444
445 // check whether Tr::BaseClass is a valid type,
446 // if so, define BaseClass_t<Tr> as being Tr::BaseClass
447 // else define as being Gaudi::Algorithm
448 template <typename Tr, typename Default = Gaudi::Algorithm>
450
451 // check whether Traits::{Input,Output}Handle<T> is a valid type,
452 // if so, define {Input,Output}Handle_t<Traits,T> as being Traits::{Input,Output}Handle<T>
453 // else define as being DataObject{Read,,Write}Handle<T>
454 template <typename Tr, typename T>
456
457 template <typename Tr, typename T>
459
460 template <typename Traits>
461 inline constexpr bool isLegacy =
462 std::is_base_of_v<Gaudi::details::LegacyAlgorithmAdapter, details::BaseClass_t<Traits>>;
463
465
466 template <typename Handles>
467 Handles make_vector_of_handles( IDataHandleHolder* owner, const std::vector<DataObjID>& init ) {
468 Handles handles;
469 handles.reserve( init.size() );
470 std::transform( init.begin(), init.end(), std::back_inserter( handles ),
471 [&]( const auto& loc ) -> typename Handles::value_type {
472 return { loc, owner };
473 } );
474 return handles;
475 }
476
477 template <typename Handle, typename Algo>
478 auto get( const Handle& handle, const Algo&,
479 const EventContext& ) -> decltype( details::deref( handle.get() ) ) // make it SFINAE friendly...
480 {
481 return details::deref( handle.get() );
482 }
483
484 template <typename IFace, typename Algo>
485 auto get( const ToolHandle<Gaudi::Interface::Bind::IBinder<IFace>>& handle, const Algo&, const EventContext& ctx ) {
486 return handle.bind( ctx );
487 }
488
489 template <typename Handle>
490 auto getKey( const Handle& h ) -> decltype( h.objKey() ) {
491 return h.objKey();
492 }
493
495 // given a pack, return a corresponding tuple
496 template <typename... In>
498 using type = std::tuple<In...>;
499
500 static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
501 "EventContext can only appear as first argument" );
502
503 template <typename Algorithm, typename Handles>
504 static auto apply( const Algorithm& algo, const EventContext& ctx, Handles& handles ) {
505 return std::apply( [&]( const auto&... handle ) { return algo( get( handle, algo, ctx )... ); }, handles );
506 }
507
508 template <typename Algorithm, typename Handles>
509 static auto apply( const Algorithm& algo, Handles& handles ) {
510 return apply( algo, Gaudi::Hive::currentContext(), handles );
511 }
512 };
513
514 // except when it starts with EventContext, then drop it
515 template <typename... In>
517 using type = std::tuple<In...>;
518
519 static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
520 "EventContext can only appear as first argument" );
521
522 template <typename Algorithm, typename Handles>
523 static auto apply( const Algorithm& algo, const EventContext& ctx, Handles& handles ) {
524 return std::apply( [&]( const auto&... handle ) { return algo( ctx, get( handle, algo, ctx )... ); }, handles );
525 }
526
527 template <typename Algorithm, typename Handles>
528 static auto apply( const Algorithm& algo, Handles& handles ) {
529 return apply( algo, Gaudi::Hive::currentContext(), handles );
530 }
531 };
532
533 template <typename... In>
534 using filter_evtcontext = typename filter_evtcontext_t<In...>::type;
535
536 template <typename OutputSpec, typename InputSpec, typename Traits_>
538
539 template <typename Out, typename In, typename Tr>
540 void updateHandleLocation( DataHandleMixin<Out, In, Tr>& parent, const std::string& prop,
541 const std::string& newLoc ) {
542 auto sc = parent.setProperty( prop, newLoc );
543 if ( sc.isFailure() ) throw GaudiException( "Could not set Property", prop + " -> " + newLoc, sc );
544 }
545
546 template <typename Out, typename In, typename Tr>
547 void updateHandleLocations( DataHandleMixin<Out, In, Tr>& parent, const std::string& prop,
548 const std::vector<std::string>& newLocs ) {
549 std::ostringstream ss;
550 GaudiUtils::details::ostream_joiner( ss << '[', newLocs, ", ", []( std::ostream& os, const auto& i ) -> auto& {
551 return os << "'" << i << "'";
552 } ) << ']';
553 auto sc = parent.setProperty( prop, ss.str() );
554 if ( sc.isFailure() ) throw GaudiException( "Could not set Property", prop + " -> " + ss.str(), sc );
555 }
556
557 template <typename... Out, typename... In, typename Traits_>
558 class DataHandleMixin<std::tuple<Out...>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
559 static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
560
561 template <typename IArgs, typename OArgs, std::size_t... I, std::size_t... J>
562 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const IArgs& inputs, std::index_sequence<I...>,
563 const OArgs& outputs, std::index_sequence<J...> )
564 : BaseClass_t<Traits_>( std::move( name ), pSvcLocator )
565 , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... )
566 , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
567 // make sure this algorithm is seen as reentrant by Gaudi
568 this->setProperty( "Cardinality", 0 ).ignore();
569 }
570
571 public:
572 constexpr static std::size_t N_in = sizeof...( In );
573 constexpr static std::size_t N_out = sizeof...( Out );
574
575 using KeyValue = std::pair<std::string, std::string>;
576 using KeyValues = std::pair<std::string, std::vector<std::string>>;
577
578 // generic constructor: N -> M
579 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, RepeatValues_<KeyValue, N_in> const& inputs,
580 RepeatValues_<KeyValue, N_out> const& outputs )
581 : DataHandleMixin( std::move( name ), pSvcLocator, inputs, std::index_sequence_for<In...>{}, outputs,
582 std::index_sequence_for<Out...>{} ) {}
583
584 // special cases: forward to the generic case...
585 // 1 -> 1
586 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& input, const KeyValue& output )
587 : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ),
588 std::forward_as_tuple( output ) ) {}
589 // 1 -> N
590 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& input,
591 RepeatValues_<KeyValue, N_out> const& outputs )
592 : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ), outputs ) {}
593 // N -> 1
594 DataHandleMixin( std::string name, ISvcLocator* locator, RepeatValues_<KeyValue, N_in> const& inputs,
595 const KeyValue& output )
596 : DataHandleMixin( std::move( name ), locator, inputs, std::forward_as_tuple( output ) ) {}
597
598 template <std::size_t N = 0>
599 decltype( auto ) inputLocation() const {
600 return getKey( std::get<N>( m_inputs ) );
601 }
602 template <typename T>
603 decltype( auto ) inputLocation() const {
604 return getKey( std::get<details::InputHandle_t<Traits_, std::decay_t<T>>>( m_inputs ) );
605 }
606 constexpr unsigned int inputLocationSize() const { return N_in; }
607
608 template <std::size_t N = 0>
609 decltype( auto ) outputLocation() const {
610 return getKey( std::get<N>( m_outputs ) );
611 }
612 template <typename T>
613 decltype( auto ) outputLocation() const {
614 return getKey( std::get<details::OutputHandle_t<Traits_, std::decay_t<T>>>( m_outputs ) );
615 }
616 constexpr unsigned int outputLocationSize() const { return N_out; }
617
618 protected:
619 bool isReEntrant() const override { return true; }
620
621 std::tuple<details::InputHandle_t<Traits_, In>...> m_inputs;
622 std::tuple<details::OutputHandle_t<Traits_, Out>...> m_outputs;
623 };
624
625 template <typename Traits_>
626 class DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> : public BaseClass_t<Traits_> {
627 static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
628
629 public:
630 using KeyValue = std::pair<std::string, std::string>;
631 using KeyValues = std::pair<std::string, std::vector<std::string>>;
632 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, std::tuple<> = {}, std::tuple<> = {} )
633 : BaseClass_t<Traits_>( std::move( name ), pSvcLocator ) {
634 // make sure this algorithm is seen as reentrant by Gaudi
635 this->setProperty( "Cardinality", 0 ).ignore();
636 }
637
638 protected:
639 bool isReEntrant() const override { return true; }
640
641 std::tuple<> m_inputs;
642 };
643
644 template <typename... In, typename Traits_>
645 class DataHandleMixin<std::tuple<>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
646 static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
647
648 template <typename IArgs, std::size_t... I>
649 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const IArgs& inputs, std::index_sequence<I...> )
650 : BaseClass_t<Traits_>( std::move( name ), pSvcLocator )
651 , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... ) {
652 // make sure this algorithm is seen as reentrant by Gaudi
653 this->setProperty( "Cardinality", 0 ).ignore();
654 }
655
656 public:
657 using KeyValue = std::pair<std::string, std::string>;
658 using KeyValues = std::pair<std::string, std::vector<std::string>>;
659 constexpr static std::size_t N_in = sizeof...( In );
660
661 // generic constructor: N -> 0
662 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, RepeatValues_<KeyValue, N_in> const& inputs )
663 : DataHandleMixin( std::move( name ), pSvcLocator, inputs, std::index_sequence_for<In...>{} ) {}
664
665 // special cases: forward to the generic case...
666 // 1 -> 0
667 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& input )
668 : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ) ) {}
669
670 template <std::size_t N = 0>
671 decltype( auto ) inputLocation() const {
672 return getKey( std::get<N>( m_inputs ) );
673 }
674 template <typename T>
675 decltype( auto ) inputLocation() const {
676 return getKey( std::get<details::InputHandle_t<Traits_, std::decay_t<T>>>( m_inputs ) );
677 }
678 constexpr unsigned int inputLocationSize() const { return N_in; }
679
680 protected:
681 bool isReEntrant() const override { return true; }
682
683 std::tuple<details::InputHandle_t<Traits_, In>...> m_inputs;
684 };
685
686 template <typename Traits_>
687 class DataHandleMixin<std::tuple<void>, std::tuple<>, Traits_>
688 : public DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> {
689 public:
690 using DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>::DataHandleMixin;
691 };
692
693 template <typename... Out, typename Traits_>
694 class DataHandleMixin<std::tuple<Out...>, std::tuple<>, Traits_> : public BaseClass_t<Traits_> {
695 static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
696
697 template <typename OArgs, std::size_t... J>
698 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const OArgs& outputs, std::index_sequence<J...> )
699 : BaseClass_t<Traits_>( std::move( name ), pSvcLocator )
700 , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
701 // make sure this algorithm is seen as reentrant by Gaudi
702 this->setProperty( "Cardinality", 0 ).ignore();
703 }
704
705 public:
706 constexpr static std::size_t N_out = sizeof...( Out );
707 using KeyValue = std::pair<std::string, std::string>;
708 using KeyValues = std::pair<std::string, std::vector<std::string>>;
709
710 // generic constructor: 0 -> N
711 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, RepeatValues_<KeyValue, N_out> const& outputs )
712 : DataHandleMixin( std::move( name ), pSvcLocator, outputs, std::index_sequence_for<Out...>{} ) {}
713
714 // 0 -> 1
715 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& output )
716 : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( output ) ) {}
717
718 template <std::size_t N = 0>
719 decltype( auto ) outputLocation() const {
720 return getKey( std::get<N>( m_outputs ) );
721 }
722 constexpr unsigned int outputLocationSize() const { return N_out; }
723
724 protected:
725 bool isReEntrant() const override { return true; }
726
727 std::tuple<details::OutputHandle_t<Traits_, Out>...> m_outputs;
728 };
729
731 template <typename Fun, typename Container, typename... Args>
732 constexpr void applyPostProcessing( const Fun&, Container&, Args... ) {
733 static_assert( sizeof...( Args ) == 0, "Args should not be used!" );
734 }
735
736 template <typename Fun, typename Container>
737 auto applyPostProcessing( const Fun& fun, Container& c ) -> decltype( fun.postprocess( c ), void() ) {
738 fun.postprocess( c );
739 }
740
741} // namespace Gaudi::Functional::details
Gaudi::Functional::Traits::BaseClass_t< Gaudi::Algorithm > BaseClass_t
bool PyHelper setProperty(IInterface *p, char *name, char *value)
boost::spirit::classic::position_iterator2< ForwardIterator > Iterator
Definition Iterator.h:18
DataObjectHandle.h GaudiKernel/DataObjectHandle.h.
T * put(std::unique_ptr< T > object) const
Register object in transient store.
This class represents an entry point to all the event specific data.
Base class from which all concrete algorithm classes should be derived.
Definition Algorithm.h:87
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >)
Definition details.h:649
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input, RepeatValues_< KeyValue, N_out > const &outputs)
Definition details.h:590
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >, const OArgs &outputs, std::index_sequence< J... >)
Definition details.h:562
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const OArgs &outputs, std::index_sequence< J... >)
Definition details.h:698
DataHandleMixin(std::string name, ISvcLocator *locator, RepeatValues_< KeyValue, N_in > const &inputs, const KeyValue &output)
Definition details.h:594
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_in > const &inputs, RepeatValues_< KeyValue, N_out > const &outputs)
Definition details.h:579
std::pair< std::string, std::vector< std::string > > KeyValues
Definition details.h:631
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, std::tuple<>={}, std::tuple<>={})
Definition details.h:632
std::tuple< details::OutputHandle_t< Traits_, Out >... > m_outputs
Definition details.h:727
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_out > const &outputs)
Definition details.h:711
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input)
Definition details.h:667
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_in > const &inputs)
Definition details.h:662
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &output)
Definition details.h:715
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input, const KeyValue &output)
Definition details.h:586
constexpr indirect_iterator & operator+=(difference_type n)
Definition details.h:315
constexpr indirect_iterator operator--(int)
Definition details.h:306
constexpr indirect_iterator & operator-=(difference_type n)
Definition details.h:327
constexpr indirect_iterator operator+(difference_type n) const
Definition details.h:321
constexpr bool operator==(const indirect_iterator &rhs) const
Definition details.h:287
constexpr indirect_iterator operator-(difference_type n) const
Definition details.h:333
constexpr difference_type operator-(const indirect_iterator &other) const
Definition details.h:339
constexpr reference operator[](difference_type n) const
Definition details.h:344
constexpr indirect_iterator operator++(int)
Definition details.h:293
static constexpr decltype(auto) wrap(ContainerVector::const_reference t)
Definition details.h:363
static constexpr auto wrap(ContainerVector::const_iterator i)
Definition details.h:370
std::add_pointer_t< val_t > ptr_t
Definition details.h:359
std::add_const_t< std::remove_pointer_t< Container > > val_t
Definition details.h:358
typename ContainerVector::size_type size_type
Definition details.h:380
std::vector< std::conditional_t< is_range, std::remove_const_t< val_t >, ptr_t > > ContainerVector
Definition details.h:360
std::conditional_t< is_pointer, ptr_t, val_t > value_type
Definition details.h:379
decltype(auto) at(size_type i) const
Definition details.h:398
Useful class for representation of "sequence" of the objects through the range of valid iterators.
Definition Range.h:81
Define general base for Gaudi exception.
The interface implemented by the AlgTool base class.
Definition IAlgTool.h:29
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition ISvcLocator.h:42
constexpr static const auto FAILURE
Definition StatusCode.h:100
Handle to be used in lieu of naked pointers to tools.
Definition ToolHandle.h:132
typename Tr::BaseClass BaseClass_t
Definition details.h:407
std::conditional_t< std::derived_from< std::decay_t< T >, IAlgTool >, ToolHandle< Gaudi::Interface::Bind::IBinder< std::decay_t< T > > >, DataObjectReadHandle< T > > DefaultInputHandle
Definition details.h:440
decltype(auto) verifySizes(Args &... args)
Verify the data container sizes have the same sizes.
Definition details.h:70
decltype(auto) const_range(Args &&... args)
Zips multiple containers together to form a single const range.
Definition details.h:94
bool check_sizes(const A &) noexcept
Resolve case there is only one container in the range.
Definition details.h:52
decltype(auto) range(Args &&... args)
Zips multiple containers together to form a single range.
Definition details.h:81
void printSizes(OS &out, Arg &&arg)
Print the parameter.
Definition details.h:38
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
Definition details.h:478
auto getKey(const Handle &h) -> decltype(h.objKey())
Definition details.h:490
constexpr void applyPostProcessing(const Fun &, Container &, Args...)
Definition details.h:732
constexpr bool isLegacy
Definition details.h:461
std::vector< DataObjID > to_DataObjID(const std::vector< std::string > &in)
Definition details.h:106
typename detail2::InputHandle< T, Tr, detail2::DefaultInputHandle >::type InputHandle_t
Definition details.h:458
auto put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
Definition details.h:162
Handles make_vector_of_handles(IDataHandleHolder *owner, const std::vector< DataObjID > &init)
Definition details.h:467
typename detail2::OutputHandle< T, Tr, DataObjectWriteHandle >::type OutputHandle_t
Definition details.h:455
void updateHandleLocation(DataHandleMixin< Out, In, Tr > &parent, const std::string &prop, const std::string &newLoc)
Definition details.h:540
constexpr struct Gaudi::Functional::details::deref_t deref
void updateHandleLocations(DataHandleMixin< Out, In, Tr > &parent, const std::string &prop, const std::vector< std::string > &newLocs)
Definition details.h:547
typename details2::value_type_of< T >::type remove_optional_t
Definition details.h:137
detail2::BaseClass< Tr, Default >::type BaseClass_t
Definition details.h:449
decltype(get_values_helper< Value >(std::make_index_sequence< N >())) RepeatValues_
Definition details.h:158
auto get_values_helper(std::index_sequence< I... >)
Definition details.h:153
typename filter_evtcontext_t< In... >::type filter_evtcontext
Definition details.h:534
GAUDI_API const EventContext & currentContext()
Stream & ostream_joiner(Stream &os, Iterator first, Iterator last, Separator sep, OutputElement output=OutputElement{})
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition System.cpp:260
STL namespace.
const In & operator()(const In *in) const
Definition details.h:224
auto operator()(const Handle< Gaudi::NamedRange_< I > > &h) -> const In
Definition details.h:256
auto operator()(const Handle< I > &h) -> const In &
Definition details.h:248
auto operator()(const Handle< Gaudi::Range_< I > > &h) -> const In
Definition details.h:252
auto operator()(const Handle< std::optional< Gaudi::NamedRange_< I > > > &h) -> const In
Definition details.h:260
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
Definition details.h:523
static auto apply(const Algorithm &algo, Handles &handles)
Definition details.h:509
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
Definition details.h:504
static auto apply(const Algorithm &algo, Handles &handles)
Definition details.h:528
std::remove_pointer_t< typename Container::value_type > c_remove_ptr_t
Definition details.h:186
auto operator()(Container &c, Value &&v) const -> decltype(c.push_back(v))
Definition details.h:189
auto operator()(Container &c, Value &&v) const -> decltype(c.insert(v))
Definition details.h:194
decltype(auto) operator()(F &&f, Arg &&arg) const
Definition details.h:142
void operator()(F &&f, Arg &&arg) const
Definition details.h:146