Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-15 09:14:34

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 namespace Acts {
0017 
0018 class TrackingVolume;
0019 class GeometryContext;
0020 class Logger;
0021 class INavigationPolicy;
0022 
0023 namespace detail {
0024 
0025 /// Concept for factory functions that create navigation policies
0026 /// @tparam F The factory function type
0027 /// @tparam Args The argument types for the factory function
0028 template <typename F, typename... Args>
0029 concept NavigationPolicyIsolatedFactoryConcept = requires(
0030     F f, const GeometryContext& gctx, const TrackingVolume& volume,
0031     const Logger& logger, Args&&... args) {
0032   { f(gctx, volume, logger, args...) } -> std::derived_from<INavigationPolicy>;
0033 
0034   requires NavigationPolicyConcept<decltype(f(gctx, volume, logger, args...))>;
0035 
0036   requires(std::is_copy_constructible_v<Args> && ...);
0037 };
0038 }  // namespace detail
0039 
0040 /// Base class for navigation policy factories. The factory can be assembled
0041 /// iteratively by using `make` followed by a number of calls to the `add`
0042 /// function of the helper type. Example:
0043 ///
0044 /// ```cpp
0045 /// auto factory = NavigationPolicyFactory{}
0046 ///  .add<NavigationPolicy1>(arg1, arg2)
0047 ///  .add<NavigationPolicy2>(/*no args*/)
0048 ///  .asUniquePtr();
0049 /// ```
0050 class NavigationPolicyFactory {
0051  private:
0052   /// Type alias for factory functions that create navigation policies
0053   using factory_type = std::function<std::unique_ptr<INavigationPolicy>(
0054       const GeometryContext&, const TrackingVolume&, const Logger&)>;
0055 
0056   /// Private constructor for internal use
0057   /// @param factories Vector of factory functions
0058   explicit NavigationPolicyFactory(std::vector<factory_type>&& factories)
0059       : m_factories(std::move(factories)) {}
0060 
0061  public:
0062   /// Default constructor
0063   NavigationPolicyFactory() = default;
0064 
0065   /// Create a new navigation policy factory
0066   /// @deprecated Use the default constructor instead
0067   /// @return A new NavigationPolicyFactory instance
0068   [[deprecated("Use the default constructor")]]
0069   static auto make() {
0070     return NavigationPolicyFactory{};
0071   }
0072 
0073   /// Add a navigation policy to the factory
0074   /// @tparam P The policy type to add
0075   /// @param args The arguments to pass to the policy constructor
0076   /// @note Arguments need to be copy constructible because the factory must be
0077   ///       able to execute multiple times.
0078   /// @return New instance of this object with the added factory for method
0079   ///         chaining
0080   template <NavigationPolicyConcept P, typename... Args>
0081     requires(std::is_constructible_v<P, const GeometryContext&,
0082                                      const TrackingVolume&, const Logger&,
0083                                      Args...> &&
0084              (std::is_copy_constructible_v<Args> && ...))
0085   constexpr NavigationPolicyFactory add(Args&&... args) && {
0086     auto factory = [=](const GeometryContext& gctx,
0087                        const TrackingVolume& volume, const Logger& logger) {
0088       return std::make_unique<P>(gctx, volume, logger, args...);
0089     };
0090 
0091     m_factories.push_back(std::move(factory));
0092     return std::move(*this);
0093   }
0094 
0095   /// Add a policy created by a factory function
0096   /// @tparam Fn The type of the function to construct the policy
0097   /// @param fn The factory function
0098   /// @param args The arguments to pass to the policy factory
0099   /// @note Arguments need to be copy constructible because the factory must be
0100   ///       able to execute multiple times.
0101   /// @return New instance of this object with the added factory for method
0102   ///         chaining
0103   template <typename Fn, typename... Args>
0104     requires(detail::NavigationPolicyIsolatedFactoryConcept<Fn, Args...>)
0105   constexpr NavigationPolicyFactory add(Fn&& fn, Args&&... args) && {
0106     auto factory = [=](const GeometryContext& gctx,
0107                        const TrackingVolume& volume, const Logger& logger) {
0108       using policy_type = decltype(fn(gctx, volume, logger, args...));
0109       return std::make_unique<policy_type>(fn(gctx, volume, logger, args...));
0110     };
0111 
0112     m_factories.push_back(std::move(factory));
0113     return std::move(*this);
0114   }
0115 
0116   /// Move the factory into a unique pointer
0117   /// @return A unique pointer to the factory
0118   std::unique_ptr<NavigationPolicyFactory> asUniquePtr() && {
0119     return std::make_unique<NavigationPolicyFactory>(std::move(*this));
0120   }
0121 
0122   /// Construct a multi-navigation policy using the registered factories
0123   /// @param gctx The geometry context
0124   /// @param volume The tracking volume
0125   /// @param logger The logger
0126   /// @return A unique pointer to the constructed MultiNavigationPolicy
0127   /// @throws std::runtime_error if no factories are registered
0128   std::unique_ptr<MultiNavigationPolicy> operator()(
0129       const GeometryContext& gctx, const TrackingVolume& volume,
0130       const Logger& logger) const {
0131     if (m_factories.empty()) {
0132       throw std::runtime_error(
0133           "No factories registered in the navigation policy factory");
0134     }
0135 
0136     std::vector<std::unique_ptr<INavigationPolicy>> policies;
0137     policies.reserve(m_factories.size());
0138     for (auto& factory : m_factories) {
0139       policies.push_back(factory(gctx, volume, logger));
0140     }
0141 
0142     return std::make_unique<MultiNavigationPolicy>(std::move(policies));
0143   }
0144 
0145   /// Construct a navigation policy using the factories (alias for operator())
0146   /// @param gctx The geometry context
0147   /// @param volume The tracking volume
0148   /// @param logger The logger
0149   /// @return A unique pointer to the constructed navigation policy
0150   std::unique_ptr<INavigationPolicy> build(const GeometryContext& gctx,
0151                                            const TrackingVolume& volume,
0152                                            const Logger& logger) const {
0153     return operator()(gctx, volume, logger);
0154   }
0155 
0156  private:
0157   /// Vector of factory functions to create navigation policies
0158   std::vector<factory_type> m_factories;
0159 };
0160 
0161 }  // namespace Acts