Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-14 09:30:32

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Navigation/INavigationPolicy.hpp"
0012 #include "Acts/Navigation/MultiNavigationPolicy.hpp"
0013 
0014 #include <concepts>
0015 #include <memory>
0016 
0017 namespace Acts {
0018 
0019 class TrackingVolume;
0020 class GeometryContext;
0021 class Logger;
0022 class INavigationPolicy;
0023 
0024 namespace detail {
0025 
0026 /// Trait detecting a `std::unique_ptr<T>` where `T` derives from
0027 /// @ref INavigationPolicy.
0028 /// @tparam T The type to inspect
0029 template <typename T>
0030 struct IsNavigationPolicyPtr : std::false_type {};
0031 
0032 template <typename T>
0033   requires(std::derived_from<T, INavigationPolicy>)
0034 struct IsNavigationPolicyPtr<std::unique_ptr<T>> : std::true_type {};
0035 
0036 /// Concept for factory functions that return a `std::unique_ptr` to a
0037 /// navigation policy. This allows the factory function to select between
0038 /// different concrete policy types at runtime (e.g. based on the volume
0039 /// geometry).
0040 /// @tparam F The factory function type
0041 /// @tparam Args The argument types for the factory function
0042 template <typename F, typename... Args>
0043 concept NavigationPolicyPointerFactoryConcept = requires(
0044     F f, const GeometryContext& gctx, const TrackingVolume& volume,
0045     const Logger& logger, Args&&... args) {
0046   requires IsNavigationPolicyPtr<
0047       std::remove_cvref_t<decltype(f(gctx, volume, logger, args...))>>::value;
0048 };
0049 }  // namespace detail
0050 
0051 /// Base class for navigation policy factories. The factory can be assembled
0052 /// iteratively by using `make` followed by a number of calls to the `add`
0053 /// function of the helper type. Example:
0054 ///
0055 /// ```cpp
0056 /// auto factory = NavigationPolicyFactory{}
0057 ///  .add<NavigationPolicy1>(arg1, arg2)
0058 ///  .add<NavigationPolicy2>(/*no args*/)
0059 ///  .asUniquePtr();
0060 /// ```
0061 class NavigationPolicyFactory {
0062  private:
0063   /// Type alias for factory functions that create navigation policies
0064   using factory_type = std::function<std::unique_ptr<INavigationPolicy>(
0065       const GeometryContext&, const TrackingVolume&, const Logger&)>;
0066 
0067   /// Private constructor for internal use
0068   /// @param factories Vector of factory functions
0069   explicit NavigationPolicyFactory(std::vector<factory_type>&& factories)
0070       : m_factories(std::move(factories)) {}
0071 
0072  public:
0073   /// Default constructor
0074   NavigationPolicyFactory() = default;
0075 
0076   /// Add a navigation policy to the factory
0077   /// @tparam P The policy type to add
0078   /// @param args The arguments to pass to the policy constructor
0079   /// @note Arguments need to be copy constructible because the factory must be
0080   ///       able to execute multiple times.
0081   /// @return New instance of this object with the added factory for method
0082   ///         chaining
0083   template <NavigationPolicyConcept P, typename... Args>
0084     requires(std::is_constructible_v<P, const GeometryContext&,
0085                                      const TrackingVolume&, const Logger&,
0086                                      Args...> &&
0087              (std::is_copy_constructible_v<Args> && ...))
0088   constexpr NavigationPolicyFactory add(Args&&... args) && {
0089     auto factory = [=](const GeometryContext& gctx,
0090                        const TrackingVolume& volume, const Logger& logger) {
0091       return std::make_unique<P>(gctx, volume, logger, args...);
0092     };
0093 
0094     m_factories.push_back(std::move(factory));
0095     return std::move(*this);
0096   }
0097 
0098   /// Add a policy created by a factory function that returns a
0099   /// `std::unique_ptr` to a navigation policy. Returning a pointer allows the
0100   /// factory function to select between different concrete policy types at
0101   /// runtime (e.g. based on the volume geometry).
0102   /// @tparam Fn The type of the function to construct the policy
0103   /// @param fn The factory function
0104   /// @param args The arguments to pass to the policy factory
0105   /// @note Arguments need to be copy constructible because the factory must be
0106   ///       able to execute multiple times.
0107   /// @return New instance of this object with the added factory for method
0108   ///         chaining
0109   template <typename Fn, typename... Args>
0110     requires(detail::NavigationPolicyPointerFactoryConcept<Fn, Args...> &&
0111              (std::is_copy_constructible_v<Args> && ...))
0112   constexpr NavigationPolicyFactory add(Fn&& fn, Args&&... args) && {
0113     auto factory = [=](const GeometryContext& gctx,
0114                        const TrackingVolume& volume,
0115                        const Logger& logger) -> factory_type::result_type {
0116       return fn(gctx, volume, logger, args...);
0117     };
0118 
0119     m_factories.push_back(std::move(factory));
0120     return std::move(*this);
0121   }
0122 
0123   /// Move the factory into a unique pointer
0124   /// @return A unique pointer to the factory
0125   std::unique_ptr<NavigationPolicyFactory> asUniquePtr() && {
0126     return std::make_unique<NavigationPolicyFactory>(std::move(*this));
0127   }
0128 
0129   /// Construct a multi-navigation policy using the registered factories
0130   /// @param gctx The geometry context
0131   /// @param volume The tracking volume
0132   /// @param logger The logger
0133   /// @return A unique pointer to the constructed MultiNavigationPolicy
0134   /// @throws std::runtime_error if no factories are registered
0135   std::unique_ptr<MultiNavigationPolicy> operator()(
0136       const GeometryContext& gctx, const TrackingVolume& volume,
0137       const Logger& logger) const {
0138     if (m_factories.empty()) {
0139       throw std::runtime_error(
0140           "No factories registered in the navigation policy factory");
0141     }
0142 
0143     std::vector<std::unique_ptr<INavigationPolicy>> policies;
0144     policies.reserve(m_factories.size());
0145     for (auto& factory : m_factories) {
0146       policies.push_back(factory(gctx, volume, logger));
0147     }
0148 
0149     return std::make_unique<MultiNavigationPolicy>(std::move(policies));
0150   }
0151 
0152   /// Construct a navigation policy using the factories (alias for operator())
0153   /// @param gctx The geometry context
0154   /// @param volume The tracking volume
0155   /// @param logger The logger
0156   /// @return A unique pointer to the constructed navigation policy
0157   std::unique_ptr<INavigationPolicy> build(const GeometryContext& gctx,
0158                                            const TrackingVolume& volume,
0159                                            const Logger& logger) const {
0160     return operator()(gctx, volume, logger);
0161   }
0162 
0163  private:
0164   /// Vector of factory functions to create navigation policies
0165   std::vector<factory_type> m_factories;
0166 };
0167 
0168 }  // namespace Acts