Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-17 07:49: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 
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 concrete navigation policy by
0037 /// value.
0038 /// @tparam F The factory function type
0039 /// @tparam Args The argument types for the factory function
0040 template <typename F, typename... Args>
0041 concept NavigationPolicyValueFactoryConcept = requires(
0042     F f, const GeometryContext& gctx, const TrackingVolume& volume,
0043     const Logger& logger, Args&&... args) {
0044   { f(gctx, volume, logger, args...) } -> std::derived_from<INavigationPolicy>;
0045 
0046   requires NavigationPolicyConcept<decltype(f(gctx, volume, logger, args...))>;
0047 };
0048 
0049 /// Concept for factory functions that return a `std::unique_ptr` to a
0050 /// navigation policy. This allows the factory function to select between
0051 /// different concrete policy types at runtime (e.g. based on the volume
0052 /// geometry).
0053 /// @tparam F The factory function type
0054 /// @tparam Args The argument types for the factory function
0055 template <typename F, typename... Args>
0056 concept NavigationPolicyPointerFactoryConcept = requires(
0057     F f, const GeometryContext& gctx, const TrackingVolume& volume,
0058     const Logger& logger, Args&&... args) {
0059   requires IsNavigationPolicyPtr<
0060       std::remove_cvref_t<decltype(f(gctx, volume, logger, args...))>>::value;
0061 };
0062 }  // namespace detail
0063 
0064 /// Base class for navigation policy factories. The factory can be assembled
0065 /// iteratively by using `make` followed by a number of calls to the `add`
0066 /// function of the helper type. Example:
0067 ///
0068 /// ```cpp
0069 /// auto factory = NavigationPolicyFactory{}
0070 ///  .add<NavigationPolicy1>(arg1, arg2)
0071 ///  .add<NavigationPolicy2>(/*no args*/)
0072 ///  .asUniquePtr();
0073 /// ```
0074 class NavigationPolicyFactory {
0075  private:
0076   /// Type alias for factory functions that create navigation policies
0077   using factory_type = std::function<std::unique_ptr<INavigationPolicy>(
0078       const GeometryContext&, const TrackingVolume&, const Logger&)>;
0079 
0080   /// Private constructor for internal use
0081   /// @param factories Vector of factory functions
0082   explicit NavigationPolicyFactory(std::vector<factory_type>&& factories)
0083       : m_factories(std::move(factories)) {}
0084 
0085  public:
0086   /// Default constructor
0087   NavigationPolicyFactory() = default;
0088 
0089   /// Add a navigation policy to the factory
0090   /// @tparam P The policy type to add
0091   /// @param args The arguments to pass to the policy constructor
0092   /// @note Arguments need to be copy constructible because the factory must be
0093   ///       able to execute multiple times.
0094   /// @return New instance of this object with the added factory for method
0095   ///         chaining
0096   template <NavigationPolicyConcept P, typename... Args>
0097     requires(std::is_constructible_v<P, const GeometryContext&,
0098                                      const TrackingVolume&, const Logger&,
0099                                      Args...> &&
0100              (std::is_copy_constructible_v<Args> && ...))
0101   constexpr NavigationPolicyFactory add(Args&&... args) && {
0102     auto factory = [=](const GeometryContext& gctx,
0103                        const TrackingVolume& volume, const Logger& logger) {
0104       return std::make_unique<P>(gctx, volume, logger, args...);
0105     };
0106 
0107     m_factories.push_back(std::move(factory));
0108     return std::move(*this);
0109   }
0110 
0111   /// Add a policy created by a factory function that returns a
0112   /// `std::unique_ptr` to a navigation policy. Returning a pointer allows the
0113   /// factory function to select between different concrete policy types at
0114   /// runtime (e.g. based on the volume geometry).
0115   /// @tparam Fn The type of the function to construct the policy
0116   /// @param fn The factory function
0117   /// @param args The arguments to pass to the policy factory
0118   /// @note Arguments need to be copy constructible because the factory must be
0119   ///       able to execute multiple times.
0120   /// @return New instance of this object with the added factory for method
0121   ///         chaining
0122   template <typename Fn, typename... Args>
0123     requires(detail::NavigationPolicyPointerFactoryConcept<Fn, Args...> &&
0124              (std::is_copy_constructible_v<Args> && ...))
0125   constexpr NavigationPolicyFactory add(Fn&& fn, Args&&... args) && {
0126     auto factory = [=](const GeometryContext& gctx,
0127                        const TrackingVolume& volume,
0128                        const Logger& logger) -> factory_type::result_type {
0129       return fn(gctx, volume, logger, args...);
0130     };
0131 
0132     m_factories.push_back(std::move(factory));
0133     return std::move(*this);
0134   }
0135 
0136   /// Add a policy created by a factory function that returns a concrete policy
0137   /// by value.
0138   /// @tparam Fn The type of the function to construct the policy
0139   /// @param fn The factory function
0140   /// @param args The arguments to pass to the policy factory
0141   /// @note Arguments need to be copy constructible because the factory must be
0142   ///       able to execute multiple times.
0143   /// @return New instance of this object with the added factory for method
0144   ///         chaining
0145   /// @deprecated Return a `std::unique_ptr<INavigationPolicy>` from the factory
0146   ///             function instead. This also lets the function select the
0147   ///             concrete policy type at runtime.
0148   template <typename Fn, typename... Args>
0149     requires(detail::NavigationPolicyValueFactoryConcept<Fn, Args...> &&
0150              !detail::NavigationPolicyPointerFactoryConcept<Fn, Args...> &&
0151              (std::is_copy_constructible_v<Args> && ...))
0152   [[deprecated(
0153       "Return a std::unique_ptr<INavigationPolicy> from the factory function "
0154       "instead of a policy by value.")]]
0155   constexpr NavigationPolicyFactory add(Fn&& fn, Args&&... args) && {
0156     auto factory = [=](const GeometryContext& gctx,
0157                        const TrackingVolume& volume,
0158                        const Logger& logger) -> factory_type::result_type {
0159       using policy_type = decltype(fn(gctx, volume, logger, args...));
0160       return std::make_unique<policy_type>(fn(gctx, volume, logger, args...));
0161     };
0162 
0163     m_factories.push_back(std::move(factory));
0164     return std::move(*this);
0165   }
0166 
0167   /// Move the factory into a unique pointer
0168   /// @return A unique pointer to the factory
0169   std::unique_ptr<NavigationPolicyFactory> asUniquePtr() && {
0170     return std::make_unique<NavigationPolicyFactory>(std::move(*this));
0171   }
0172 
0173   /// Construct a multi-navigation policy using the registered factories
0174   /// @param gctx The geometry context
0175   /// @param volume The tracking volume
0176   /// @param logger The logger
0177   /// @return A unique pointer to the constructed MultiNavigationPolicy
0178   /// @throws std::runtime_error if no factories are registered
0179   std::unique_ptr<MultiNavigationPolicy> operator()(
0180       const GeometryContext& gctx, const TrackingVolume& volume,
0181       const Logger& logger) const {
0182     if (m_factories.empty()) {
0183       throw std::runtime_error(
0184           "No factories registered in the navigation policy factory");
0185     }
0186 
0187     std::vector<std::unique_ptr<INavigationPolicy>> policies;
0188     policies.reserve(m_factories.size());
0189     for (auto& factory : m_factories) {
0190       policies.push_back(factory(gctx, volume, logger));
0191     }
0192 
0193     return std::make_unique<MultiNavigationPolicy>(std::move(policies));
0194   }
0195 
0196   /// Construct a navigation policy using the factories (alias for operator())
0197   /// @param gctx The geometry context
0198   /// @param volume The tracking volume
0199   /// @param logger The logger
0200   /// @return A unique pointer to the constructed navigation policy
0201   std::unique_ptr<INavigationPolicy> build(const GeometryContext& gctx,
0202                                            const TrackingVolume& volume,
0203                                            const Logger& logger) const {
0204     return operator()(gctx, volume, logger);
0205   }
0206 
0207  private:
0208   /// Vector of factory functions to create navigation policies
0209   std::vector<factory_type> m_factories;
0210 };
0211 
0212 }  // namespace Acts