The Gaudi Framework  master (991ff291)
Loading...
Searching...
No Matches
details.h
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2026 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#include <Gaudi/Algorithm.h>
16#include <GaudiKernel/IBinder.h>
18#include <algorithm>
19#include <array>
20#include <cassert>
21#include <functional>
22#include <iterator>
23#include <memory>
24#include <optional>
25#include <source_location>
26#include <sstream>
27#include <tuple>
28#include <type_traits>
29#include <utility>
30#include <vector>
31
32// TODO: migrate downstream users to include `zip.h` directly, instead of transitively,
33// and then drop this include here...
34#include "deprecated.h"
35#include "zip.h"
36
38
39 inline std::vector<DataObjID> to_DataObjID( const std::vector<std::string>& in ) {
40 std::vector<DataObjID> out;
41 out.reserve( in.size() );
42 std::transform( in.begin(), in.end(), std::back_inserter( out ),
43 []( const std::string& i ) { return DataObjID{ i }; } );
44 return out;
45 }
46
48 template <typename T>
49 concept is_optional = requires( T const& t ) {
50 t.has_value();
51 t.value();
52 typename T::value_type;
53 };
54
55 namespace details2 {
56
57 template <typename T>
59 using type = T;
60 };
61
62 template <is_optional T>
63 struct value_type_of<T> {
64 using type = T::value_type;
65 };
66
67 } // namespace details2
68
69 template <typename T>
71
72 constexpr struct invoke_optionally_t {
73 template <typename F, typename Arg>
74 requires( !is_optional<Arg> )
75 decltype( auto ) operator()( F&& f, Arg&& arg ) const {
76 return std::invoke( std::forward<F>( f ), std::forward<Arg>( arg ) );
77 }
78 template <typename F, is_optional Arg>
79 void operator()( F&& f, Arg&& arg ) const {
80 if ( arg ) std::invoke( std::forward<F>( f ), *std::forward<Arg>( arg ) );
81 }
82 } invoke_optionally{};
84#if 0
85 template <typename Value, auto>
86 using repeat_t = Value;
87 template <typename Value, auto N>
88 using RepeatValues_ =
89 decltype( []<std::size_t... I>( std::index_sequence<I...> ) -> std::tuple<repeat_t<Value, I>...> {
90 }( std::make_index_sequence<N>{} ) );
91#else
92 template <typename Value, std::size_t... I>
93 auto get_values_helper( std::index_sequence<I...> ) {
94 return std::make_tuple( ( (void)I, Value{} )... );
95 }
96
97 template <typename Value, auto N>
98 using RepeatValues_ = decltype( get_values_helper<Value>( std::make_index_sequence<N>() ) );
99#endif
100
102 template <std::derived_from<DataObject> Out1, std::convertible_to<Out1> Out2>
103 auto put( const DataObjectHandle<Out1>& out_handle, Out2&& out ) {
104 return out_handle.put( std::make_unique<Out1>( std::forward<Out2>( out ) ) );
105 }
106
107 template <typename Out1, std::convertible_to<Out1> Out2>
108 auto put( const DataObjectHandle<AnyDataWrapper<Out1>>& out_handle, Out2&& out ) {
109 return out_handle.put( std::forward<Out2>( out ) );
110 }
111
112 // optional put
113 template <typename OutHandle, typename OptOut>
114 requires( is_optional<OptOut> )
115 void put( const OutHandle& out_handle, OptOut&& out ) {
116 if ( out ) put( out_handle, *std::forward<OptOut>( out ) );
117 }
118
120 // adapt to differences between eg. std::vector (which has push_back) and KeyedContainer (which has insert)
121 // adapt to getting a T, and a container wanting T* by doing new T{ std::move(out) }
122 // adapt to getting a optional<T>
123
124 constexpr struct insert_t {
125 // for Container<T*>, return T
126 template <typename Container>
127 using c_remove_ptr_t = std::remove_pointer_t<typename Container::value_type>;
128
129 template <typename Container, typename Value>
130 auto operator()( Container& c, Value&& v ) const -> decltype( c.push_back( v ) ) {
131 return c.push_back( std::forward<Value>( v ) );
132 }
133
134 template <typename Container, typename Value>
135 auto operator()( Container& c, Value&& v ) const -> decltype( c.insert( v ) ) {
136 return c.insert( std::forward<Value>( v ) );
137 }
138
139 // Container<T*> with T&& as argument
140 template <typename Container, typename Value>
141 requires( std::is_pointer_v<typename Container::value_type> &&
142 std::is_convertible_v<Value, c_remove_ptr_t<Container>> )
143 auto operator()( Container& c, Value&& v ) const {
144 return operator()( c, new c_remove_ptr_t<Container>{ std::forward<Value>( v ) } );
145 }
146
147 } insert{};
148
150
151 constexpr struct deref_t {
152 template <typename In>
153 requires( !std::is_pointer_v<In> )
154 const In& operator()( const In& in ) const {
155 return in;
156 }
157
158 template <typename In>
159 requires( !std::is_pointer_v<std::decay_t<In>> )
160 In operator()( In&& in ) const {
161 return std::forward<In>( in );
162 }
163
164 template <typename In>
165 const In& operator()( const In* in ) const {
166 assert( in != nullptr );
167 return *in;
168 }
169 } deref{};
170
172 // if Container is a pointer, then we're optional items
173 namespace details2 {
174 template <typename T>
175 constexpr static bool is_gaudi_range_v = false;
176
177 template <typename T>
178 constexpr static bool is_gaudi_range_v<Gaudi::Range_<T>> = true;
179
180 template <typename T>
181 constexpr static bool is_gaudi_range_v<Gaudi::NamedRange_<T>> = true;
182
183 template <typename T>
184 constexpr static bool is_gaudi_range_v<std::optional<Gaudi::NamedRange_<T>>> = true;
185
186 template <typename In>
188 template <template <typename> class Handle, std::convertible_to<In> I>
189 auto operator()( const Handle<I>& h ) -> const In& {
190 return *h.get();
191 }
192 template <template <typename> class Handle, typename I>
193 auto operator()( const Handle<Gaudi::Range_<I>>& h ) -> In {
194 return h.get();
195 }
196 template <template <typename> class Handle, typename I>
197 auto operator()( const Handle<Gaudi::NamedRange_<I>>& h ) -> In {
198 return h.get();
199 }
200 template <template <typename> class Handle, typename I>
201 auto operator()( const Handle<std::optional<Gaudi::NamedRange_<I>>>& h ) -> In {
202 return h.get();
203 }
204 template <template <typename> class Handle, typename I>
205 requires( std::is_convertible_v<I*, In> )
206 auto operator()( const Handle<I>& h ) -> In {
207 return h.getIfExists();
208 } // In is-a pointer
209 };
210
211 template <typename Iterator>
213 using traits = std::iterator_traits<Iterator>;
215
216 public:
217 using iterator_category [[maybe_unused]] = typename traits::iterator_category;
218 using difference_type [[maybe_unused]] = typename traits::difference_type;
219 using reference = decltype( **m_iter );
220 using value_type [[maybe_unused]] = std::remove_reference_t<reference>;
221 using pointer [[maybe_unused]] = std::add_pointer_t<value_type>;
222
223 indirect_iterator() = default;
224 constexpr explicit indirect_iterator( Iterator i ) : m_iter( std::move( i ) ) {}
225
226 constexpr reference operator*() const { return **m_iter; }
227
228 constexpr bool operator==( const indirect_iterator& rhs ) const { return m_iter == rhs.m_iter; }
229
231 ++m_iter;
232 return *this;
233 }
234 constexpr indirect_iterator operator++( int ) {
235 auto i = *this;
236 ++*this;
237 return i;
238 }
239
240 // bidirectional iterator operations (if possible)
242 requires std::bidirectional_iterator<Iterator>
243 {
244 --m_iter;
245 return *this;
246 }
248 requires std::bidirectional_iterator<Iterator>
249 {
250 auto i = *this;
251 --*this;
252 return i;
253 }
254
255 // random access iterator operations (if possible)
256 constexpr indirect_iterator& operator+=( difference_type n )
257 requires std::random_access_iterator<Iterator>
258 {
259 m_iter += n;
260 return *this;
261 }
262 constexpr indirect_iterator operator+( difference_type n ) const
263 requires std::random_access_iterator<Iterator>
264 {
265 auto i = *this;
266 return i += n;
267 }
268 constexpr indirect_iterator& operator-=( difference_type n )
269 requires std::random_access_iterator<Iterator>
270 {
271 m_iter -= n;
272 return *this;
273 }
274 constexpr indirect_iterator operator-( difference_type n ) const
275 requires std::random_access_iterator<Iterator>
276 {
277 auto i = *this;
278 return i -= n;
279 }
280 constexpr difference_type operator-( const indirect_iterator& other ) const
281 requires std::random_access_iterator<Iterator>
282 {
283 return m_iter - other.m_iter;
284 }
285 constexpr reference operator[]( difference_type n ) const
286 requires std::random_access_iterator<Iterator>
287 {
288 return **( m_iter + n );
289 }
290 };
291
292 } // namespace details2
293
294 template <typename Container>
296 static constexpr bool is_pointer = std::is_pointer_v<Container>;
297 static constexpr bool is_range = details2::is_gaudi_range_v<Container>;
298 template <typename C>
299 using borrowed_value_t = std::add_const_t<std::remove_pointer_t<C>>;
300 // TODO: refuse pointer to a range... range must always be by value
302 using ptr_t = std::add_pointer_t<val_t>;
303 using ContainerVector = std::vector<std::conditional_t<is_range, std::remove_const_t<val_t>, ptr_t>>;
305
306 constexpr static decltype( auto ) wrap( ContainerVector::const_reference t ) {
307 if constexpr ( is_pointer || is_range ) {
308 return t;
309 } else {
310 return *t;
311 }
312 }
313 constexpr static auto wrap( ContainerVector::const_iterator i ) {
314 if constexpr ( is_pointer || is_range ) {
315 return i;
316 } else {
317 return details2::indirect_iterator{ i };
318 }
319 }
320
321 public:
322 using value_type = std::conditional_t<is_pointer, ptr_t, val_t>;
323 using size_type = typename ContainerVector::size_type;
324
325 vector_of_const_() = default;
326 void reserve( size_type size ) { m_containers.reserve( size ); }
327 template <typename T>
328 requires( is_pointer || is_range )
329 void push_back( T&& container ) {
330 m_containers.push_back( container );
331 }
332 template <typename C = Container>
333 requires( !std::is_pointer_v<C> && !details2::is_gaudi_range_v<C> )
334 void push_back( borrowed_value_t<C>& container ) {
335 // note: does not copy its argument, so we're not really a container...
336 m_containers.push_back( &container );
337 }
338 template <typename C = Container>
339 requires( !std::is_pointer_v<C> && !details2::is_gaudi_range_v<C> )
340 void push_back( borrowed_value_t<C>&& ) = delete;
341
342 auto begin() const { return wrap( m_containers.begin() ); }
343 auto end() const { return wrap( m_containers.end() ); }
344 decltype( auto ) front() const { return wrap( m_containers.front() ); }
345 decltype( auto ) back() const { return wrap( m_containers.back() ); }
346 decltype( auto ) operator[]( size_type i ) const { return wrap( m_containers[i] ); }
347 decltype( auto ) at( size_type i ) const { return wrap( m_containers.at( i ) ); }
348 size_type size() const { return m_containers.size(); }
349 };
350
351 template <template <typename> class Handle, typename I>
353 struct Payload {
354 std::vector<Handle<I>> handles;
356
357 template <typename Algorithm>
358 Payload( Algorithm* parent, std::pair<std::string, std::vector<std::string>> const& keys )
359 : property{ parent, keys.first, details::to_DataObjID( keys.second ),
360 [ptr = &handles, parent]( auto& self_ ) {
361 auto& self = dynamic_cast<Gaudi::Property<std::vector<DataObjID>>&>( self_ );
362 ptr->clear();
363 ptr->reserve( self.value().size() );
364 std::ranges::transform( self.value(), std::back_inserter( *ptr ),
365 [&]( const auto& location ) -> Handle<I> {
366 return { location, parent };
367 } );
368 },
370
371 Payload( Payload&& ) = delete;
372 Payload& operator=( Payload&& ) = delete;
373 Payload( Payload const& ) = delete;
374 Payload& operator=( Payload const& ) = delete;
375 };
376 std::unique_ptr<Payload> m_payload; // need a stable rendez-vous for the callback & property to work
377
378 public:
379 template <typename Algorithm>
380 HandleVector( Algorithm* parent, std::pair<std::string, std::vector<std::string>> const& keys )
381 : m_payload{ std::make_unique<Payload>( parent, keys ) } {}
382
383 // allow construction by DataHandleMixin
384 template <typename A, typename K>
385 HandleVector( std::tuple<A, K>&& tup ) : HandleVector{ std::get<0>( tup ), std::get<1>( tup ) } {}
386
389 ins.reserve( m_payload->handles.size() );
390 std::ranges::transform( m_payload->handles, std::back_inserter( ins ), details2::get_from_handle<I>{} );
391 return ins;
392 }
393 template <typename Out>
394 void put( Out&& out ) const {
395 auto const n = size();
396 if ( out.size() != n ) {
397 throw GaudiException( "Error during transform in " +
398 std::string{ std::source_location::current().function_name() } + ": expected " +
399 std::to_string( n ) + " containers, got " + std::to_string( out.size() ) + " instead",
400 "Gaudi::Functional::details::HandleVector::put", StatusCode::FAILURE );
401 }
402 for ( std::size_t i = 0; i != n; ++i ) details::put( handles()[i], std::move( out[i] ) );
403 }
404
405 std::vector<Handle<I>> const& handles() const { return m_payload->handles; }
406 std::vector<DataObjID> const& locations() const { return m_payload->property.value(); }
407 DataObjID const& at( size_t i ) const { return m_payload->property.value().at( i ); }
408 auto size() const { return m_payload->handles.size(); }
409 };
410
411 template <template <typename> class Handle, typename... I, typename Algorithm, typename InKeys>
412 auto make_HandleVectorTuple( Algorithm* parent, InKeys const& keys ) {
413 return std::apply(
414 [parent]( auto const&... key ) {
415 static_assert( sizeof...( key ) == sizeof...( I ) );
416 return std::tuple{ HandleVector<Handle, I>{ parent, key }... };
417 },
418 keys );
419 }
420
421 template <template <typename> class Handle, typename... I>
422 decltype( auto ) getLocations( std::tuple<HandleVector<Handle, I>...> const& vectors, unsigned int i ) {
423 return std::apply(
424 [i]( auto const&... elems ) -> decltype( auto ) { return *std::array{ &elems.locations()... }.at( i ); },
425 vectors );
426 }
427
428 template <typename F>
430 try {
431 return std::forward<F>( f )();
432 } catch ( GaudiException& e ) {
433 if ( e.code().isFailure() ) alg.error() << e.tag() << " : " << e.message() << endmsg;
434 return e.code();
435 }
436 }
437
439 namespace detail2 { // utilities for detected_or_t{,_} usage
440
441 // keep only for backwards compatibility... for now.
442 template <typename Tr>
443 using BaseClass_t = typename Tr::BaseClass;
444
445 template <typename Tr, typename Default>
446 struct BaseClass {
447 using type = Default;
448 };
449 template <typename Tr, typename Default>
450 requires requires { typename Tr::BaseClass; }
451 struct BaseClass<Tr, Default> {
452 using type = Tr::BaseClass;
453 };
454
455 template <typename T, typename Tr, template <typename...> typename Default>
457 using type = Default<T>;
458 };
459 template <typename T, typename Tr, template <typename...> typename Default>
460 requires requires { typename Tr::template OutputHandle<T>; }
461 struct OutputHandle<T, Tr, Default> {
462 using type = Tr::template OutputHandle<T>;
463 };
464
465 template <typename T, typename Tr, template <typename...> typename Default>
466 struct InputHandle {
467 using type = Default<T>;
468 };
469 template <typename T, typename Tr, template <typename...> typename Default>
470 requires requires { typename Tr::template InputHandle<T>; }
471 struct InputHandle<T, Tr, Default> {
472 using type = Tr::template InputHandle<T>;
473 };
474
475 template <typename T>
477 std::conditional_t<std::derived_from<std::decay_t<T>, IAlgTool>,
479 } // namespace detail2
480
481 // check whether Tr::BaseClass is a valid type,
482 // if so, define BaseClass_t<Tr> as being Tr::BaseClass
483 // else define as being Gaudi::Algorithm
484 template <typename Tr, typename Default = Gaudi::Algorithm>
486
487 // check whether Traits::{Input,Output}Handle<T> is a valid type,
488 // if so, define {Input,Output}Handle_t<Traits,T> as being Traits::{Input,Output}Handle<T>
489 // else define as being DataObject{Read,,Write}Handle<T>
490 template <typename Tr, typename T>
492
493 template <typename Tr, typename T>
495
496 template <typename Traits>
497 inline constexpr bool isLegacy =
498 std::is_base_of_v<Gaudi::details::LegacyAlgorithmAdapter, details::BaseClass_t<Traits>>;
499
501
502 template <typename Handle, typename Algo>
503 auto get( const Handle& handle, const Algo&,
504 const EventContext& ) -> decltype( details::deref( handle.get() ) ) // make it SFINAE friendly...
505 {
506 return details::deref( handle.get() );
507 }
508
509 template <typename IFace, typename Algo>
510 auto get( const ToolHandle<Gaudi::Interface::Bind::IBinder<IFace>>& handle, const Algo&, const EventContext& ctx ) {
511 return handle.bind( ctx );
512 }
513
514 template <typename Handle>
515 auto getKey( const Handle& h ) -> decltype( h.objKey() ) {
516 return h.objKey();
517 }
518
520 // given a pack, return a corresponding tuple
521 template <typename... In>
523 using type = std::tuple<In...>;
524
525 static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
526 "EventContext can only appear as first argument" );
527
528 template <typename Algorithm, typename Handles>
529 static auto apply( const Algorithm& algo, const EventContext& ctx, Handles& handles ) {
530 return std::apply( [&]( const auto&... handle ) { return algo( get( handle, algo, ctx )... ); }, handles );
531 }
532 };
533
534 // except when it starts with EventContext, then drop it
535 template <typename... In>
537 using type = std::tuple<In...>;
538
539 static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
540 "EventContext can only appear as first argument" );
541
542 template <typename Algorithm, typename Handles>
543 static auto apply( const Algorithm& algo, const EventContext& ctx, Handles& handles ) {
544 return std::apply( [&]( const auto&... handle ) { return algo( ctx, get( handle, algo, ctx )... ); }, handles );
545 }
546 };
547
548 template <typename... In>
549 using filter_evtcontext = typename filter_evtcontext_t<In...>::type;
550
551 template <typename OutputSpec, typename InputSpec, typename Traits_>
553
554 template <typename... Out, typename... In, typename Traits_>
555 requires std::derived_from<BaseClass_t<Traits_>, Algorithm>
556 class DataHandleMixin<std::tuple<Out...>, std::tuple<In...>, Traits_> : public BaseClass_t<Traits_> {
557
558 template <typename IArgs, typename OArgs, std::size_t... I, std::size_t... J>
559 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, const IArgs& inputs, std::index_sequence<I...>,
560 const OArgs& outputs, std::index_sequence<J...> )
561 : BaseClass_t<Traits_>( std::move( name ), pSvcLocator )
562 , m_inputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<I>( inputs ) )... )
563 , m_outputs( std::tuple_cat( std::forward_as_tuple( this ), std::get<J>( outputs ) )... ) {
564 // make sure this algorithm is seen as reentrant by Gaudi
565 this->setProperty( "Cardinality", 0 ).ignore();
566 }
567
568 public:
569 constexpr static std::size_t N_in = sizeof...( In );
570 constexpr static std::size_t N_out = sizeof...( Out );
571
572 using KeyValue = std::pair<std::string, std::string>;
573 using KeyValues = std::pair<std::string, std::vector<std::string>>;
574
575 // generic constructor: N -> M
576 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, RepeatValues_<KeyValue, N_in> const& inputs,
577 RepeatValues_<KeyValue, N_out> const& outputs )
578 requires( N_in != 0 && N_out != 0 )
579 : DataHandleMixin( std::move( name ), pSvcLocator, inputs, std::index_sequence_for<In...>{}, outputs,
580 std::index_sequence_for<Out...>{} ) {}
581
582 // special cases: forward to the generic case...
583 // 0 -> 0
584 DataHandleMixin( std::string name, ISvcLocator* locator, std::tuple<> = {}, std::tuple<> = {} )
585 requires( N_in == 0 && N_out == 0 )
586 : DataHandleMixin( std::move( name ), locator, std::tuple<>{}, std::index_sequence<>{}, std::tuple<>{},
587 std::index_sequence<>{} ) {}
588 // 1 -> 0
589 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& input )
590 requires( N_in == 1 && N_out == 0 )
591 : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ), std::index_sequence<0>{},
592 std::tuple<>{}, std::index_sequence<>{} ) {}
593 // 0 -> 1
594 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& output )
595 requires( N_in == 0 && N_out == 1 )
596 : DataHandleMixin( std::move( name ), locator, std::tuple<>{}, std::index_sequence<>{},
597 std::forward_as_tuple( output ), std::index_sequence<0>{} ) {}
598 // 1 -> 1
599 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& input, const KeyValue& output )
600 requires( N_in == 1 && N_out == 1 )
601 : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ),
602 std::index_sequence<size_t{ 0 }>{}, std::forward_as_tuple( output ),
603 std::index_sequence<size_t{ 0 }>{} ) {}
604 // 1 -> N
605 DataHandleMixin( std::string name, ISvcLocator* locator, const KeyValue& input,
606 RepeatValues_<KeyValue, N_out> const& outputs )
607 requires( N_in == 1 && N_out != 0 )
608 : DataHandleMixin( std::move( name ), locator, std::forward_as_tuple( input ),
609 std::index_sequence<size_t{ 0 }>{}, outputs, std::index_sequence_for<Out...>{} ) {}
610 // N -> 1
611 DataHandleMixin( std::string name, ISvcLocator* locator, RepeatValues_<KeyValue, N_in> const& inputs,
612 const KeyValue& output )
613 requires( N_in != 0 && N_out == 1 )
614 : DataHandleMixin( std::move( name ), locator, inputs, std::index_sequence_for<In...>{},
615 std::forward_as_tuple( output ), std::index_sequence<size_t{ 0 }>{} ) {}
616 // N -> 0
617 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, RepeatValues_<KeyValue, N_in> const& inputs )
618 requires( N_in != 0 && N_out == 0 )
619 : DataHandleMixin( std::move( name ), pSvcLocator, inputs, std::index_sequence_for<In...>{}, std::tuple<>{},
620 std::index_sequence<>{} ) {}
621 // 0 -> N
622 DataHandleMixin( std::string name, ISvcLocator* pSvcLocator, RepeatValues_<KeyValue, N_out> const& outputs )
623 requires( N_in == 0 && N_out != 0 )
624 : DataHandleMixin( std::move( name ), pSvcLocator, std::tuple<>{}, std::index_sequence<>{}, outputs,
625 std::index_sequence_for<Out...>{} ) {}
626
627 template <std::size_t N = 0>
628 decltype( auto ) inputLocation() const
629 requires( N_in > 0 )
630 {
631 return getKey( std::get<N>( m_inputs ) );
632 }
633 template <typename T>
634 decltype( auto ) inputLocation() const
635 requires( N_in > 0 )
636 {
637 return getKey( std::get<details::InputHandle_t<Traits_, std::decay_t<T>>>( m_inputs ) );
638 }
639 constexpr unsigned int inputLocationSize() const { return N_in; }
640
641 template <std::size_t N = 0>
642 decltype( auto ) outputLocation() const
643 requires( N_out > 0 )
644 {
645 return getKey( std::get<N>( m_outputs ) );
646 }
647 template <typename T>
648 decltype( auto ) outputLocation() const
649 requires( N_out > 0 )
650 {
651 return getKey( std::get<details::OutputHandle_t<Traits_, std::decay_t<T>>>( m_outputs ) );
652 }
653 constexpr unsigned int outputLocationSize() const { return N_out; }
654
655 protected:
656 bool isReEntrant() const override { return true; }
657
658 std::tuple<details::InputHandle_t<Traits_, In>...> m_inputs;
659 std::tuple<details::OutputHandle_t<Traits_, Out>...> m_outputs;
660 };
661
662 template <typename Traits_>
663 class DataHandleMixin<std::tuple<void>, std::tuple<>, Traits_>
664 : public DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> {
665 public:
666 using DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>::DataHandleMixin;
667 };
668
669} // namespace Gaudi::Functional::details
bool PyHelper setProperty(IInterface *p, char *name, char *value)
boost::spirit::classic::position_iterator2< ForwardIterator > Iterator
Definition Iterator.h:18
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
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 *locator, const KeyValue &output)
Definition details.h:594
DataHandleMixin(std::string name, ISvcLocator *locator, std::tuple<>={}, std::tuple<>={})
Definition details.h:584
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_in > const &inputs)
Definition details.h:617
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input, RepeatValues_< KeyValue, N_out > const &outputs)
Definition details.h:605
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_in > const &inputs, RepeatValues_< KeyValue, N_out > const &outputs)
Definition details.h:576
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input)
Definition details.h:589
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, const IArgs &inputs, std::index_sequence< I... >, const OArgs &outputs, std::index_sequence< J... >)
Definition details.h:559
DataHandleMixin(std::string name, ISvcLocator *locator, RepeatValues_< KeyValue, N_in > const &inputs, const KeyValue &output)
Definition details.h:611
DataHandleMixin(std::string name, ISvcLocator *pSvcLocator, RepeatValues_< KeyValue, N_out > const &outputs)
Definition details.h:622
DataHandleMixin(std::string name, ISvcLocator *locator, const KeyValue &input, const KeyValue &output)
Definition details.h:599
HandleVector(std::tuple< A, K > &&tup)
Definition details.h:385
std::unique_ptr< Payload > m_payload
Definition details.h:376
DataObjID const & at(size_t i) const
Definition details.h:407
HandleVector(Algorithm *parent, std::pair< std::string, std::vector< std::string > > const &keys)
Definition details.h:380
std::vector< DataObjID > const & locations() const
Definition details.h:406
vector_of_const_< I > get(EventContext const &) const
Definition details.h:387
std::vector< Handle< I > > const & handles() const
Definition details.h:405
constexpr indirect_iterator & operator+=(difference_type n)
Definition details.h:256
constexpr indirect_iterator operator--(int)
Definition details.h:247
constexpr indirect_iterator & operator-=(difference_type n)
Definition details.h:268
constexpr indirect_iterator operator+(difference_type n) const
Definition details.h:262
constexpr bool operator==(const indirect_iterator &rhs) const
Definition details.h:228
constexpr indirect_iterator operator-(difference_type n) const
Definition details.h:274
constexpr difference_type operator-(const indirect_iterator &other) const
Definition details.h:280
constexpr reference operator[](difference_type n) const
Definition details.h:285
constexpr indirect_iterator operator++(int)
Definition details.h:234
static constexpr decltype(auto) wrap(ContainerVector::const_reference t)
Definition details.h:306
static constexpr auto wrap(ContainerVector::const_iterator i)
Definition details.h:313
std::add_pointer_t< val_t > ptr_t
Definition details.h:302
void push_back(borrowed_value_t< C > &&)=delete
std::add_const_t< std::remove_pointer_t< C > > borrowed_value_t
Definition details.h:299
typename ContainerVector::size_type size_type
Definition details.h:323
std::vector< std::conditional_t< is_range, std::remove_const_t< val_t >, ptr_t > > ContainerVector
Definition details.h:303
std::conditional_t< is_pointer, ptr_t, val_t > value_type
Definition details.h:322
borrowed_value_t< Container > val_t
Definition details.h:301
decltype(auto) at(size_type i) const
Definition details.h:347
void push_back(borrowed_value_t< C > &container)
Definition details.h:334
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
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.
virtual const std::string & message() const
error message to be printed
virtual const StatusCode & code() const
StatusCode for Exception.
virtual const std::string & tag() const
name tag for the exception, or exception type
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
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isFailure() const
Definition StatusCode.h:129
constexpr static const auto FAILURE
Definition StatusCode.h:100
Handle to be used in lieu of naked pointers to tools.
Definition ToolHandle.h:132
Gaudi::tagged_bool< class ImmediatelyInvokeHandler_tag > ImmediatelyInvokeHandler
Definition Property.h:23
typename Tr::BaseClass BaseClass_t
Definition details.h:443
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:476
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
Definition details.h:503
auto getKey(const Handle &h) -> decltype(h.objKey())
Definition details.h:515
constexpr bool isLegacy
Definition details.h:497
std::vector< DataObjID > to_DataObjID(const std::vector< std::string > &in)
Definition details.h:39
typename detail2::InputHandle< T, Tr, detail2::DefaultInputHandle >::type InputHandle_t
Definition details.h:494
auto put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
Definition details.h:103
auto make_HandleVectorTuple(Algorithm *parent, InKeys const &keys)
Definition details.h:412
typename detail2::OutputHandle< T, Tr, DataObjectWriteHandle >::type OutputHandle_t
Definition details.h:491
constexpr struct Gaudi::Functional::details::deref_t deref
typename details2::value_type_of< T >::type remove_optional_t
Definition details.h:70
detail2::BaseClass< Tr, Default >::type BaseClass_t
Definition details.h:485
decltype(get_values_helper< Value >(std::make_index_sequence< N >())) RepeatValues_
Definition details.h:98
decltype(auto) getLocations(std::tuple< HandleVector< Handle, I >... > const &vectors, unsigned int i)
Definition details.h:422
auto get_values_helper(std::index_sequence< I... >)
Definition details.h:93
StatusCode execute(CommonMessagingBase const &alg, F &&f)
Definition details.h:429
typename filter_evtcontext_t< In... >::type filter_evtcontext
Definition details.h:549
STL namespace.
Payload & operator=(Payload const &)=delete
Gaudi::Property< std::vector< DataObjID > > property
Definition details.h:355
Payload(Algorithm *parent, std::pair< std::string, std::vector< std::string > > const &keys)
Definition details.h:358
const In & operator()(const In *in) const
Definition details.h:165
auto operator()(const Handle< std::optional< Gaudi::NamedRange_< I > > > &h) -> In
Definition details.h:201
auto operator()(const Handle< I > &h) -> const In &
Definition details.h:189
auto operator()(const Handle< Gaudi::NamedRange_< I > > &h) -> In
Definition details.h:197
auto operator()(const Handle< Gaudi::Range_< I > > &h) -> In
Definition details.h:193
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
Definition details.h:543
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
Definition details.h:529
std::remove_pointer_t< typename Container::value_type > c_remove_ptr_t
Definition details.h:127
auto operator()(Container &c, Value &&v) const -> decltype(c.push_back(v))
Definition details.h:130
auto operator()(Container &c, Value &&v) const -> decltype(c.insert(v))
Definition details.h:135
decltype(auto) operator()(F &&f, Arg &&arg) const
Definition details.h:75
void operator()(F &&f, Arg &&arg) const
Definition details.h:79