Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:10:52

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 template <typename... Factories>
0025 class NavigationPolicyFactoryImpl;
0026 }
0027 
0028 /// Base class for navigation policy factories. The factory can be assembled
0029 /// iteratively by using `make` followed by a number of calls to the `add`
0030 /// function of the helper type. Example:
0031 ///
0032 /// ```cpp
0033 /// auto factory = NavigationPolicyFactory::make()
0034 ///  .add<NavigationPolicy1>(arg1, arg2)
0035 ///  .add<NavigationPolicy2>(/*no args*/)
0036 ///  .asUniquePtr();
0037 /// ```
0038 class NavigationPolicyFactory {
0039  public:
0040   virtual ~NavigationPolicyFactory() = default;
0041 
0042   // This needs to be listed here, but the return type cannot be spelled out
0043   // yet.
0044   static auto make();
0045 
0046   // This will potentially get serialization interface and deserialization
0047   // functionality
0048 
0049   virtual std::unique_ptr<INavigationPolicy> build(
0050       const GeometryContext& gctx, const TrackingVolume& volume,
0051       const Logger& logger) const = 0;
0052 };
0053 
0054 namespace detail {
0055 
0056 template <typename F, typename... Args>
0057 concept NavigationPolicyIsolatedFactoryConcept = requires(
0058     F f, const GeometryContext& gctx, const TrackingVolume& volume,
0059     const Logger& logger, Args&&... args) {
0060   { f(gctx, volume, logger, args...) } -> std::derived_from<INavigationPolicy>;
0061 
0062   requires NavigationPolicyConcept<decltype(f(gctx, volume, logger, args...))>;
0063 
0064   requires(std::is_copy_constructible_v<Args> && ...);
0065 };
0066 
0067 template <>
0068 class NavigationPolicyFactoryImpl<> {
0069  public:
0070   template <typename...>
0071   friend class NavigationPolicyFactoryImpl;
0072   NavigationPolicyFactoryImpl() = default;
0073 
0074   /// Create a factory with the specified policy added
0075   /// @tparam P The policy type to add
0076   /// @param args The arguments to pass to the policy constructor
0077   /// @note Arguments need to be copy constructible because the factory must be
0078   ///       able to execute multiple times.
0079   /// @return A new policy factory including the @c P policy.
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 auto add(Args&&... args) && {
0086     auto factory = [=](const GeometryContext& gctx,
0087                        const TrackingVolume& volume, const Logger& logger) {
0088       return P{gctx, volume, logger, args...};
0089     };
0090 
0091     return NavigationPolicyFactoryImpl<decltype(factory)>{
0092         std::make_tuple(std::move(factory))};
0093   }
0094 
0095   /// Create a factory with a policy returned by a factory function
0096   /// @tparam Fn The type of the function to construct the policy
0097   /// @param args The arguments to pass to the policy factory
0098   /// @note Arguments need to be copy constructible because the factory must be
0099   ///       able to execute multiple times.
0100   /// @return A new policy factory including the function
0101   template <typename Fn, typename... Args>
0102     requires(NavigationPolicyIsolatedFactoryConcept<Fn, Args...>)
0103   constexpr auto add(Fn&& fn, Args&&... args) {
0104     auto factory = [=](const GeometryContext& gctx,
0105                        const TrackingVolume& volume, const Logger& logger) {
0106       return fn(gctx, volume, logger, args...);
0107     };
0108 
0109     return NavigationPolicyFactoryImpl<decltype(factory)>{
0110         std::make_tuple(std::move(factory))};
0111   }
0112 };
0113 
0114 template <typename F, typename... Fs>
0115 class NavigationPolicyFactoryImpl<F, Fs...> : public NavigationPolicyFactory {
0116  public:
0117   /// Create a factory with the specified policy added
0118   /// @tparam P The policy type to add
0119   /// @param args The arguments to pass to the policy constructor
0120   /// @note Arguments need to be copy constructible because the factory must be
0121   ///       able to execute multiple times.
0122   /// @return A new policy factory including the @c P policy.
0123   template <NavigationPolicyConcept P, typename... Args>
0124     requires(std::is_constructible_v<P, const GeometryContext&,
0125                                      const TrackingVolume&, const Logger&,
0126                                      Args...> &&
0127              (std::is_copy_constructible_v<Args> && ...))
0128   constexpr auto add(Args&&... args) && {
0129     auto factory = [=](const GeometryContext& gctx,
0130                        const TrackingVolume& volume, const Logger& logger) {
0131       return P{gctx, volume, logger, args...};
0132     };
0133 
0134     return NavigationPolicyFactoryImpl<F, Fs..., decltype(factory)>{
0135         std::tuple_cat(std::move(m_factories),
0136                        std::make_tuple(std::move(factory)))};
0137   }
0138 
0139   /// Create a factory with a policy returned by a factory function
0140   /// @tparam Fn The type of the function to construct the policy
0141   /// @param args The arguments to pass to the policy factory
0142   /// @note Arguments need to be copy constructible because the factory must be
0143   ///       able to execute multiple times.
0144   /// @return A new policy factory including the function
0145   template <typename Fn, typename... Args>
0146     requires(NavigationPolicyIsolatedFactoryConcept<Fn, Args...>)
0147   constexpr auto add(Fn&& fn, Args&&... args) && {
0148     auto factory = [=](const GeometryContext& gctx,
0149                        const TrackingVolume& volume, const Logger& logger) {
0150       return fn(gctx, volume, logger, args...);
0151     };
0152 
0153     return NavigationPolicyFactoryImpl<F, Fs..., decltype(factory)>{
0154         std::tuple_cat(std::move(m_factories),
0155                        std::make_tuple(std::move(factory)))};
0156   }
0157 
0158   /// Move the factory into a unique pointer
0159   /// @note Only callable on rvalue references
0160   /// @return A unique pointer to the factory
0161   constexpr std::unique_ptr<NavigationPolicyFactoryImpl<F, Fs...>>
0162   asUniquePtr() && {
0163     return std::make_unique<NavigationPolicyFactoryImpl<F, Fs...>>(
0164         std::move(*this));
0165   }
0166 
0167   /// Construct a navigation policy using the factories
0168   /// @param gctx The geometry context
0169   /// @param volume The tracking volume
0170   /// @param logger The logger
0171   auto operator()(const GeometryContext& gctx, const TrackingVolume& volume,
0172                   const Logger& logger) const {
0173     return std::apply(
0174         [&](auto&&... factories) {
0175           // Deduce policy type explicitly here...
0176           using policy_type = decltype(MultiNavigationPolicy{
0177               std::invoke(factories, std::declval<const GeometryContext&>(),
0178                           std::declval<const TrackingVolume&>(),
0179                           std::declval<const Logger&>())...});
0180 
0181           // ... so we can create a unique_ptr of the concrete type here rather
0182           // than the base. (`make_unique` can't do type deduction)
0183           return std::make_unique<policy_type>(
0184               std::invoke(factories, gctx, volume, logger)...);
0185         },
0186         m_factories);
0187   }
0188 
0189   /// Construct a navigation policy using the factories
0190   /// @param gctx The geometry context
0191   /// @param volume The tracking volume
0192   /// @param logger The logger
0193   std::unique_ptr<INavigationPolicy> build(
0194       const GeometryContext& gctx, const TrackingVolume& volume,
0195       const Logger& logger) const override {
0196     return operator()(gctx, volume, logger);
0197   }
0198 
0199  private:
0200   template <typename...>
0201   friend class NavigationPolicyFactoryImpl;
0202 
0203   explicit NavigationPolicyFactoryImpl(std::tuple<F, Fs...>&& factories)
0204       : m_factories(std::move(factories)) {}
0205 
0206   std::tuple<F, Fs...> m_factories;
0207 };
0208 
0209 }  // namespace detail
0210 
0211 inline auto NavigationPolicyFactory::make() {
0212   return detail::NavigationPolicyFactoryImpl<>{};
0213 }
0214 
0215 }  // namespace Acts