Back to home page

EIC code displayed by LXR

 
 

    


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

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/Utilities/Delegate.hpp"
0012 #include "Acts/Utilities/TypeList.hpp"
0013 
0014 #include <tuple>
0015 #include <type_traits>
0016 #include <utility>
0017 
0018 namespace Acts {
0019 
0020 template <typename Fn, typename payload_types = TypeList<>, auto... Callables>
0021 class DelegateChainBuilder;
0022 
0023 template <typename R, typename... payload_types, auto... callables,
0024           typename... callable_args>
0025 class DelegateChainBuilder<R(callable_args...), TypeList<payload_types...>,
0026                            callables...> {
0027   using return_type =
0028       std::conditional_t<std::is_same_v<R, void>, void,
0029                          std::array<R, sizeof...(payload_types)>>;
0030   using delegate_type =
0031       Delegate<return_type(callable_args...), void, DelegateType::Owning>;
0032   using tuple_type = std::tuple<payload_types...>;
0033 
0034  public:
0035   template <typename, typename Ps, auto... Cs>
0036   friend class DelegateChainBuilder;
0037 
0038   DelegateChainBuilder() = default;
0039 
0040   template <typename D>
0041   DelegateChainBuilder(const D& /*unused*/) {}
0042 
0043   template <auto Callable, typename payload_type>
0044   constexpr auto add(payload_type payload)
0045     requires(std::is_pointer_v<payload_type>)
0046   {
0047     std::tuple<payload_types..., payload_type> payloads =
0048         std::tuple_cat(m_payloads, std::make_tuple(payload));
0049 
0050     return DelegateChainBuilder<R(callable_args...),
0051                                 TypeList<payload_types..., payload_type>,
0052                                 callables..., Callable>{payloads};
0053   }
0054 
0055   template <auto Callable>
0056   constexpr auto add() {
0057     std::tuple<payload_types..., std::nullptr_t> payloads =
0058         std::tuple_cat(m_payloads, std::make_tuple(std::nullptr_t{}));
0059 
0060     return DelegateChainBuilder<R(callable_args...),
0061                                 TypeList<payload_types..., std::nullptr_t>,
0062                                 callables..., Callable>{payloads};
0063   }
0064 
0065   delegate_type build()
0066     requires(sizeof...(callables) > 0)
0067   {
0068     auto block = std::make_unique<const DispatchBlock>(m_payloads);
0069     delegate_type delegate;
0070     delegate.template connect<&DispatchBlock::dispatch>(std::move(block));
0071     return delegate;
0072   }
0073 
0074   void store(delegate_type& delegate)
0075     requires(sizeof...(callables) > 0)
0076   {
0077     auto block = std::make_unique<const DispatchBlock>(m_payloads);
0078     delegate.template connect<&DispatchBlock::dispatch>(std::move(block));
0079   }
0080 
0081   void store(Delegate<R(callable_args...)>& delegate)
0082     requires(sizeof...(callables) == 1)
0083   {
0084     constexpr auto callable =
0085         DispatchBlock::template findCallable<0, 0, callables...>();
0086     delegate.template connect<callable>(std::get<0>(m_payloads));
0087   }
0088 
0089  private:
0090   DelegateChainBuilder(std::tuple<payload_types...> payloads)
0091       : m_payloads(payloads) {}
0092 
0093   struct DispatchBlock {
0094     template <std::size_t I, std::size_t J, auto head, auto... tail>
0095     static constexpr auto findCallable() {
0096       if constexpr (I == J) {
0097         return head;
0098       } else {
0099         return findCallable<I, J + 1, tail...>();
0100       }
0101     }
0102 
0103     template <std::size_t I = 0, typename result_ptr>
0104     static constexpr auto invoke(result_ptr result, const tuple_type* payloads,
0105                                  callable_args&&... args) {
0106       const auto& callable = findCallable<I, 0, callables...>();
0107 
0108       if constexpr (!std::is_same_v<std::tuple_element_t<I, tuple_type>,
0109                                     std::nullptr_t>) {
0110         auto payload = std::get<I>(*payloads);
0111 
0112         if constexpr (!std::is_same_v<result_ptr, std::nullptr_t>) {
0113           std::get<I>(*result) = std::invoke(
0114               callable, payload, std::forward<callable_args>(args)...);
0115         } else {
0116           std::invoke(callable, payload, std::forward<callable_args>(args)...);
0117         }
0118 
0119       } else {
0120         if constexpr (!std::is_same_v<result_ptr, std::nullptr_t>) {
0121           std::get<I>(*result) =
0122               std::invoke(callable, std::forward<callable_args>(args)...);
0123         } else {
0124           std::invoke(callable, std::forward<callable_args>(args)...);
0125         }
0126       }
0127 
0128       if constexpr (I < sizeof...(payload_types) - 1) {
0129         invoke<I + 1>(result, payloads, std::forward<callable_args>(args)...);
0130       }
0131     }
0132 
0133     DispatchBlock(tuple_type payloads) : m_payloads(std::move(payloads)) {}
0134 
0135     tuple_type m_payloads{};
0136 
0137     auto dispatch(callable_args&&... args) const {
0138       if constexpr (std::is_same_v<R, void>) {
0139         invoke(nullptr, &m_payloads, std::forward<callable_args>(args)...);
0140       } else {
0141         static_assert(
0142             std::is_same_v<R, void> || std::is_default_constructible_v<R>,
0143             "Delegate chain return type must be void or default constructible");
0144         return_type result{};
0145         invoke(&result, &m_payloads, std::forward<callable_args>(args)...);
0146         return result;
0147       }
0148     }
0149   };
0150 
0151  private:
0152   tuple_type m_payloads{};
0153 };
0154 
0155 template <typename D>
0156 DelegateChainBuilder(const D& /*unused*/)
0157     -> DelegateChainBuilder<typename D::signature_type>;
0158 
0159 }  // namespace Acts