@@ -75,6 +75,17 @@ concept is_table_iterator_or_enumeration = soa::is_table_or_iterator<T> || is_en
7575// the contents of an AnalysisTask...
7676namespace
7777{
78+ // One closure type for every argument index. Written inline inside the pack
79+ // expansion in bindAssociatedTables() below, the predicate lambda would get a
80+ // fresh closure type per Args, and with it its own std::ranges::filter_view,
81+ // __bind_back and __perfect_forward_impl instantiation -- paid once per
82+ // associated table per process function. Taking the index as a runtime capture
83+ // instead lets every call site share a single filter_view specialisation.
84+ inline auto matchersForArgument (int argumentIndex)
85+ {
86+ return std::views::filter ([argumentIndex](auto const & pair) { return pair.first == argumentIndex; });
87+ }
88+
7889struct AnalysisDataProcessorBuilder {
7990 template <soa::is_iterator G, soa::is_table... Args>
8091 static void addGroupingCandidates (Cache& bk, Cache& bku, bool enabled)
@@ -286,15 +297,15 @@ struct AnalysisDataProcessorBuilder {
286297 requires(!std::same_as<Grouping, void >)
287298 {
288299 constexpr auto hash = o2::framework::TypeIdHelpers::uniqueId<void (C::*)(Grouping, Args...)>();
289- return extract<std::decay_t <Grouping>, 0 >(record, matchers | std::views::filter ([]( auto const & pair) { return pair. first == 0 ; } ), infos, hash);
300+ return extract<std::decay_t <Grouping>, 0 >(record, matchers | matchersForArgument ( 0 ), infos, hash);
290301 }
291302
292303 template <std::ranges::input_range R, typename C, is_table_iterator_or_enumeration Grouping, soa::is_table... Args>
293304 static auto bindAssociatedTables (InputRecord& record, R matchers, void (C::*)(Grouping, Args...), std::vector<ExpressionInfo>& infos)
294305 requires(!std::same_as<Grouping, void > && sizeof ...(Args) > 0)
295306 {
296307 constexpr auto hash = o2::framework::TypeIdHelpers::uniqueId<void (C::*)(Grouping, Args...)>();
297- return std::make_tuple (extract<std::decay_t <Args>, has_type_at_v<Args>(pack<Args...>{}) + 1 >(record, matchers | std::views::filter ([]( auto const & pair) { return pair. first == has_type_at_v<Args>(pack<Args...>{}) + 1 ; } ), infos, hash)...);
308+ return std::make_tuple (extract<std::decay_t <Args>, has_type_at_v<Args>(pack<Args...>{}) + 1 >(record, matchers | matchersForArgument ( has_type_at_v<Args>(pack<Args...>{}) + 1 ), infos, hash)...);
298309 }
299310
300311 template <soa::is_table... As>
@@ -595,8 +606,7 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args)
595606 // replace origins in Preslice declarations
596607 homogeneous_apply_refs_sized<numElements>([&newOrigin](auto & element) { return analysis_task_parsers::replaceOrigin (element, newOrigin); }, *task.get ());
597608
598- auto algo = AlgorithmSpec::InitCallback
599- {
609+ auto algo = AlgorithmSpec::InitCallback{
600610 [task = task, expressionInfos, inputInfos, newOrigin, newOriginStr](InitContext& ic) mutable {
601611 Cache bindingsKeys;
602612 Cache bindingsKeysUnsorted;
@@ -715,8 +725,7 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args)
715725 // finalize outputs
716726 homogeneous_apply_refs_sized<numElements>([&pc](auto & element) { return analysis_task_parsers::finalizeOutput (pc, element); }, *task.get ());
717727 };
718- }
719- };
728+ }};
720729
721730 return {
722731 name,
0 commit comments