21 #include <type_traits>
23 #if defined( __cpp_lib_ranges_zip ) && defined( __cpp_lib_ranges_as_const )
24 # define GAUDI_FUNCTIONAL_USES_STD_RANGES 1
27 # include <range/v3/version.hpp>
28 # include <range/v3/view/const.hpp>
29 # include <range/v3/view/zip.hpp>
34 #define GAUDI_FUNCTIONAL_CONSTRUCTOR_USES_TUPLE
42 template <
typename OS,
typename Arg>
48 template <
typename OS,
typename Arg,
typename... Args>
62 template <
typename A,
typename B>
64 return a.size() == b.size();
68 template <
typename A,
typename B,
typename... C>
69 inline bool check_sizes(
const A& a,
const B& b,
const C&...
c ) noexcept {
74 template <
typename... Args>
77 std::ostringstream mess;
78 mess <<
"Zipped containers have different sizes : ";
85 template <
typename... Args>
90 #if defined( GAUDI_FUNCTIONAL_USES_STD_RANGES )
91 return std::ranges::zip_view( std::forward<Args>(
args )... );
93 return ranges::views::zip( std::forward<Args>(
args )... );
98 template <
typename... Args>
103 #if defined( GAUDI_FUNCTIONAL_USES_STD_RANGES )
104 return std::ranges::as_const_view( std::ranges::zip_view( std::forward<Args>(
args )... ) );
106 return ranges::views::const_( ranges::views::zip( std::forward<Args>(
args )... ) );
111 inline std::vector<DataObjID>
to_DataObjID(
const std::vector<std::string>& in ) {
112 std::vector<DataObjID>
out;
113 out.reserve( in.size() );
114 std::transform( in.begin(), in.end(), std::back_inserter(
out ),
115 [](
const std::string& i ) { return DataObjID{ i }; } );
120 template <
typename T>
124 typename T::value_type;
129 template <
typename T>
134 template <is_optional T>
141 template <
typename T>
145 template <
typename F,
typename Arg>
147 decltype( auto ) operator()( F&& f, Arg&& arg )
const {
148 return std::invoke( std::forward<F>( f ), std::forward<Arg>( arg ) );
150 template <
typename F, is_optional Arg>
152 if ( arg ) std::invoke( std::forward<F>( f ), *std::forward<Arg>( arg ) );
157 template <
typename Value, std::size_t... I>
159 return std::make_tuple( ( (
void)I,
Value{} )... );
162 template <
typename Value, auto N>
163 using RepeatValues_ = decltype( get_values_helper<Value>( std::make_index_sequence<N>() ) );
166 template <std::derived_from<DataObject> Out1, std::convertible_to<Out1> Out2>
168 return out_handle.
put( std::make_unique<Out1>( std::forward<Out2>(
out ) ) );
171 template <
typename Out1, std::convertible_to<Out1> Out2>
173 return out_handle.put( std::forward<Out2>(
out ) );
177 template <
typename OutHandle,
typename OptOut>
179 void
put( const OutHandle& out_handle, OptOut&&
out ) {
180 if (
out )
put( out_handle, *std::forward<OptOut>(
out ) );
190 template <
typename Container>
193 template <
typename Container,
typename Value>
195 return c.push_back( std::forward<Value>(
v ) );
198 template <
typename Container,
typename Value>
200 return c.insert( std::forward<Value>(
v ) );
204 template <
typename Container,
typename Value>
205 requires( std::is_pointer_v<typename Container::value_type> &&
207 auto operator()( Container&
c,
Value&&
v )
const {
216 template <
typename In>
218 const In& operator()(
const In& in )
const {
222 template <
typename In>
224 In operator()( In&& in )
const {
225 return std::forward<In>( in );
228 template <
typename In>
230 assert( in !=
nullptr );
238 template <
typename T>
239 constexpr
static bool is_gaudi_range_v =
false;
241 template <
typename T>
242 constexpr
static bool is_gaudi_range_v<Gaudi::Range_<T>> =
true;
244 template <
typename T>
245 constexpr
static bool is_gaudi_range_v<Gaudi::NamedRange_<T>> =
true;
247 template <
typename T>
248 constexpr
static bool is_gaudi_range_v<std::optional<Gaudi::NamedRange_<T>>> =
true;
250 template <
typename In>
252 template <
template <
typename>
class Handle, std::convertible_to<In> I>
256 template <
template <
typename>
class Handle,
typename I>
260 template <
template <
typename>
class Handle,
typename I>
264 template <
template <
typename>
class Handle,
typename I>
268 template <
template <
typename>
class Handle,
typename I>
270 auto operator()(
const Handle<I>&
h ) ->
const In {
271 return h.getIfExists();
275 template <
typename Iterator>
277 using traits = std::iterator_traits<Iterator>;
284 using value_type [[maybe_unused]] = std::remove_reference_t<reference>;
285 using pointer [[maybe_unused]] = std::add_pointer_t<value_type>;
311 constexpr indirect_iterator operator--(
int )
312 requires std::bidirectional_iterator<Iterator>
320 constexpr indirect_iterator& operator+=( difference_type
n )
321 requires std::random_access_iterator<Iterator>
326 constexpr indirect_iterator
operator+( difference_type
n )
const
327 requires std::random_access_iterator<Iterator>
332 constexpr indirect_iterator& operator-=( difference_type
n )
333 requires std::random_access_iterator<Iterator>
338 constexpr indirect_iterator
operator-( difference_type
n )
const
339 requires std::random_access_iterator<Iterator>
344 constexpr difference_type
operator-(
const indirect_iterator& other )
const
345 requires std::random_access_iterator<Iterator>
347 return m_iter - other.m_iter;
349 constexpr
reference operator[]( difference_type
n )
const
350 requires std::random_access_iterator<Iterator>
352 return **( m_iter +
n );
358 template <
typename Container>
360 static constexpr
bool is_pointer = std::is_pointer_v<Container>;
361 static constexpr
bool is_range = details2::is_gaudi_range_v<Container>;
363 using val_t = std::add_const_t<std::remove_pointer_t<Container>>;
364 using ptr_t = std::add_pointer_t<val_t>;
368 constexpr
static decltype(
auto ) wrap(
ContainerVector::const_reference
t ) {
369 if constexpr ( is_pointer || is_range ) {
375 constexpr
static auto wrap( ContainerVector::const_iterator i ) {
376 if constexpr ( is_pointer || is_range ) {
384 using value_type = std::conditional_t<is_pointer, ptr_t, val_t>;
389 template <
typename T>
391 if constexpr ( is_pointer || is_range ) {
392 m_containers.push_back( container );
395 m_containers.push_back( &container );
398 auto begin()
const {
return wrap( m_containers.begin() ); }
399 auto end()
const {
return wrap( m_containers.end() ); }
400 decltype(
auto ) front()
const {
return wrap( m_containers.front() ); }
401 decltype(
auto ) back()
const {
return wrap( m_containers.back() ); }
402 decltype(
auto ) operator[]( size_type i )
const {
return wrap( m_containers[i] ); }
403 decltype(
auto ) at( size_type i )
const {
return wrap( m_containers.at( i ) ); }
411 template <
typename Tr>
414 template <
typename Tr,
typename Default>
418 template <
typename Tr,
typename Default>
424 template <
typename T,
typename Tr,
template <
typename...>
typename Default>
428 template <
typename T,
typename Tr,
template <
typename...>
typename Default>
434 template <
typename T,
typename Tr,
template <
typename...>
typename Default>
438 template <
typename T,
typename Tr,
template <
typename...>
typename Default>
444 template <
typename T>
446 std::conditional_t<std::derived_from<std::decay_t<T>,
IAlgTool>,
453 template <
typename Tr,
typename Default = Gaudi::Algorithm>
459 template <
typename Tr,
typename T>
462 template <
typename Tr,
typename T>
465 template <
typename Traits>
467 std::is_base_of_v<Gaudi::details::LegacyAlgorithmAdapter, details::BaseClass_t<Traits>>;
470 #define GAUDI_FUNCTIONAL_MAKE_VECTOR_OF_HANDLES_USES_DATAOBJID
472 template <
typename Handles>
475 handles.reserve( init.size() );
476 std::transform( init.begin(), init.end(), std::back_inserter( handles ),
477 [&](
const auto& loc ) ->
typename Handles::value_type {
478 return { loc, owner };
483 template <
typename Handle,
typename Algo>
484 auto get(
const Handle& handle,
const Algo&,
490 template <
typename IFace,
typename Algo>
492 return handle.bind(
ctx );
495 template <
typename Handle>
496 auto getKey(
const Handle&
h ) -> decltype(
h.objKey() ) {
502 template <
typename... In>
504 using type = std::tuple<In...>;
506 static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
507 "EventContext can only appear as first argument" );
509 template <
typename Algorithm,
typename Handles>
515 template <
typename Algorithm,
typename Handles>
517 return std::apply( [&](
const auto&... handle ) {
return algo(
get( handle, algo,
ctx )... ); }, handles );
522 template <
typename... In>
524 using type = std::tuple<In...>;
526 static_assert( !std::disjunction_v<std::is_same<EventContext, In>...>,
527 "EventContext can only appear as first argument" );
529 template <
typename Algorithm,
typename Handles>
531 return std::apply( [&](
const auto&... handle ) {
return algo(
ctx,
get( handle, algo,
ctx )... ); }, handles );
534 template <
typename Algorithm,
typename Handles>
540 template <
typename... In>
543 template <
typename OutputSpec,
typename InputSpec,
typename Traits_>
546 template <
typename Out,
typename In,
typename Tr>
548 const std::string& newLoc ) {
549 auto sc = parent.setProperty( prop, newLoc );
550 if ( sc.isFailure() )
throw GaudiException(
"Could not set Property", prop +
" -> " + newLoc, sc );
553 template <
typename Out,
typename In,
typename Tr>
555 const std::vector<std::string>& newLocs ) {
556 std::ostringstream ss;
558 return os <<
"'" << i <<
"'";
560 auto sc = parent.setProperty( prop, ss.str() );
561 if ( sc.isFailure() )
throw GaudiException(
"Could not set Property", prop +
" -> " + ss.str(), sc );
564 template <
typename... Out,
typename... In,
typename Traits_>
568 template <
typename IArgs,
typename OArgs, std::size_t... I, std::size_t... J>
570 const OArgs& outputs, std::index_sequence<J...> )
572 , m_inputs(
std::tuple_cat(
std::forward_as_tuple( this ),
std::
get<I>( inputs ) )... )
573 , m_outputs(
std::tuple_cat(
std::forward_as_tuple( this ),
std::
get<J>( outputs ) )... ) {
579 constexpr
static std::size_t N_in =
sizeof...( In );
580 constexpr
static std::size_t N_out =
sizeof...( Out );
582 using KeyValue = std::pair<std::string, std::string>;
583 using KeyValues = std::pair<std::string, std::vector<std::string>>;
589 std::index_sequence_for<Out...>{} ) {}
605 template <std::
size_t N = 0>
606 decltype(
auto ) inputLocation()
const {
607 return getKey( std::get<N>( m_inputs ) );
609 template <
typename T>
610 decltype(
auto ) inputLocation()
const {
615 template <std::
size_t N = 0>
616 decltype(
auto ) outputLocation()
const {
617 return getKey( std::get<N>( m_outputs ) );
619 template <
typename T>
620 decltype(
auto ) outputLocation()
const {
628 std::tuple<details::InputHandle_t<Traits_, In>...>
m_inputs;
629 std::tuple<details::OutputHandle_t<Traits_, Out>...>
m_outputs;
632 template <
typename Traits_>
637 using KeyValue = std::pair<std::string, std::string>;
638 using KeyValues = std::pair<std::string, std::vector<std::string>>;
651 template <
typename... In,
typename Traits_>
655 template <
typename IArgs, std::size_t... I>
658 , m_inputs(
std::tuple_cat(
std::forward_as_tuple( this ),
std::
get<I>( inputs ) )... ) {
664 using KeyValue = std::pair<std::string, std::string>;
665 using KeyValues = std::pair<std::string, std::vector<std::string>>;
666 constexpr
static std::size_t N_in =
sizeof...( In );
677 template <std::
size_t N = 0>
678 decltype(
auto ) inputLocation()
const {
679 return getKey( std::get<N>( m_inputs ) );
681 template <
typename T>
682 decltype(
auto ) inputLocation()
const {
690 std::tuple<details::InputHandle_t<Traits_, In>...>
m_inputs;
693 template <
typename Traits_>
700 template <
typename... Out,
typename Traits_>
704 template <
typename OArgs, std::size_t... J>
707 , m_outputs(
std::tuple_cat(
std::forward_as_tuple( this ),
std::
get<J>( outputs ) )... ) {
713 constexpr
static std::size_t N_out =
sizeof...( Out );
714 using KeyValue = std::pair<std::string, std::string>;
715 using KeyValues = std::pair<std::string, std::vector<std::string>>;
725 template <std::
size_t N = 0>
726 decltype(
auto ) outputLocation()
const {
727 return getKey( std::get<N>( m_outputs ) );
734 std::tuple<details::OutputHandle_t<Traits_, Out>...>
m_outputs;
738 template <
typename Fun,
typename Container,
typename... Args>
740 static_assert(
sizeof...( Args ) == 0,
"Args should not be used!" );
743 template <
typename Fun,
typename Container>
745 fun.postprocess(
c );