diff --git a/Core/include/Acts/EventData/Charge.hpp b/Core/include/Acts/EventData/Charge.hpp index 64073538a3f..75d32d8f59f 100644 --- a/Core/include/Acts/EventData/Charge.hpp +++ b/Core/include/Acts/EventData/Charge.hpp @@ -60,7 +60,7 @@ struct Neutral { /// Construct and verify the input charge magnitude (in debug builds). /// /// This constructor is only provided to allow consistent construction. - constexpr Neutral(float absQ) noexcept { + constexpr explicit Neutral(float absQ) noexcept { assert((absQ == 0) && "Input charge must be zero"); (void)absQ; } @@ -102,7 +102,7 @@ struct SinglyCharged { /// Construct and verify the input charge magnitude (in debug builds). /// /// This constructor is only provided to allow consistent construction. - constexpr SinglyCharged(float absQ) noexcept { + constexpr explicit SinglyCharged(float absQ) noexcept { assert((absQ == UnitConstants::e) && "Input charge magnitude must be e"); (void)absQ; } @@ -141,10 +141,10 @@ static_assert(ChargeConcept, class NonNeutralCharge { public: /// Construct with the magnitude of the input charge. - constexpr NonNeutralCharge(float absQ) noexcept : m_absQ{absQ} { + constexpr explicit NonNeutralCharge(float absQ) noexcept : m_absQ{absQ} { assert((0 < absQ) && "Input charge magnitude must be positive"); } - constexpr NonNeutralCharge(SinglyCharged /*unused*/) noexcept + constexpr explicit NonNeutralCharge(SinglyCharged /*unused*/) noexcept : m_absQ{UnitConstants::e} {} constexpr float absQ() const noexcept { return m_absQ; } @@ -182,12 +182,12 @@ static_assert(ChargeConcept, class AnyCharge { public: /// Construct with the magnitude of the input charge. - constexpr AnyCharge(float absQ) noexcept : m_absQ{absQ} { + constexpr explicit AnyCharge(float absQ) noexcept : m_absQ{absQ} { assert((0 <= absQ) && "Input charge magnitude must be zero or positive"); } - constexpr AnyCharge(SinglyCharged /*unused*/) noexcept + constexpr explicit AnyCharge(SinglyCharged /*unused*/) noexcept : m_absQ{UnitConstants::e} {} - constexpr AnyCharge(Neutral /*unused*/) noexcept {} + constexpr explicit AnyCharge(Neutral /*unused*/) noexcept {} constexpr float absQ() const noexcept { return m_absQ; } diff --git a/Core/include/Acts/EventData/GenericBoundTrackParameters.hpp b/Core/include/Acts/EventData/GenericBoundTrackParameters.hpp index 22567d8adf5..6c495a023f6 100644 --- a/Core/include/Acts/EventData/GenericBoundTrackParameters.hpp +++ b/Core/include/Acts/EventData/GenericBoundTrackParameters.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Definitions/Tolerance.hpp" +#include "Acts/EventData/ParticleHypothesis.hpp" #include "Acts/EventData/TrackParameterHelpers.hpp" #include "Acts/EventData/TransformationHelpers.hpp" #include "Acts/EventData/detail/PrintParameters.hpp" @@ -69,12 +70,17 @@ class GenericBoundTrackParameters { /// Converts a bound track parameter with a different hypothesis. template - GenericBoundTrackParameters( + explicit GenericBoundTrackParameters( const GenericBoundTrackParameters& other) : GenericBoundTrackParameters(other.referenceSurface().getSharedPtr(), other.parameters(), other.covariance(), other.particleHypothesis()) {} + /// Convert this track parameter object to the general type-erased one + GenericBoundTrackParameters toBound() const { + return GenericBoundTrackParameters{*this}; + } + /// Factory to construct from four-position, direction, absolute momentum, and /// charge. /// diff --git a/Core/include/Acts/EventData/MultiComponentTrackParameters.hpp b/Core/include/Acts/EventData/MultiComponentTrackParameters.hpp index 5e079af0df7..bf9dea6fa61 100644 --- a/Core/include/Acts/EventData/MultiComponentTrackParameters.hpp +++ b/Core/include/Acts/EventData/MultiComponentTrackParameters.hpp @@ -121,6 +121,9 @@ class MultiComponentBoundTrackParameters { MultiComponentBoundTrackParameters& operator=( MultiComponentBoundTrackParameters&&) = default; + /// Comply with bound convertible, in this case return a copy + MultiComponentBoundTrackParameters toBound() const { return *this; } + /// Access the parameters const auto& components() const { return m_components; } diff --git a/Core/include/Acts/EventData/ParticleHypothesis.hpp b/Core/include/Acts/EventData/ParticleHypothesis.hpp index f236441ede6..8bbf830023c 100644 --- a/Core/include/Acts/EventData/ParticleHypothesis.hpp +++ b/Core/include/Acts/EventData/ParticleHypothesis.hpp @@ -27,7 +27,8 @@ class SinglyChargedParticleHypothesis public: constexpr SinglyChargedParticleHypothesis(PdgParticle absPdg, float mass) : GenericParticleHypothesis(absPdg, mass, {}) {} - SinglyChargedParticleHypothesis(PdgParticle absPdg) + + explicit SinglyChargedParticleHypothesis(PdgParticle absPdg) : GenericParticleHypothesis(absPdg) {} template @@ -70,7 +71,7 @@ class NeutralParticleHypothesis : public GenericParticleHypothesis { public: constexpr NeutralParticleHypothesis(PdgParticle absPdg, float mass) : GenericParticleHypothesis(absPdg, mass, {}) {} - NeutralParticleHypothesis(PdgParticle absPdg) + explicit NeutralParticleHypothesis(PdgParticle absPdg) : GenericParticleHypothesis(absPdg) {} template @@ -102,7 +103,7 @@ class NonNeutralChargedParticleHypothesis constexpr NonNeutralChargedParticleHypothesis(PdgParticle absPdg, float mass, NonNeutralCharge chargeType) : GenericParticleHypothesis(absPdg, mass, chargeType) {} - NonNeutralChargedParticleHypothesis(PdgParticle absPdg) + explicit NonNeutralChargedParticleHypothesis(PdgParticle absPdg) : GenericParticleHypothesis(absPdg) {} template @@ -127,8 +128,8 @@ class NonNeutralChargedParticleHypothesis } static NonNeutralChargedParticleHypothesis pionLike(float absQ) { - return NonNeutralChargedParticleHypothesis(pion().absolutePdg(), - pion().mass(), absQ); + return NonNeutralChargedParticleHypothesis( + pion().absolutePdg(), pion().mass(), NonNeutralCharge{absQ}); } static NonNeutralChargedParticleHypothesis chargedGeantino() { @@ -136,7 +137,8 @@ class NonNeutralChargedParticleHypothesis return cache; } static NonNeutralChargedParticleHypothesis chargedGeantino(float absQ) { - return NonNeutralChargedParticleHypothesis(PdgParticle::eInvalid, 0, absQ); + return NonNeutralChargedParticleHypothesis(PdgParticle::eInvalid, 0, + NonNeutralCharge{absQ}); } }; @@ -148,7 +150,8 @@ class ParticleHypothesis : public GenericParticleHypothesis { constexpr ParticleHypothesis(PdgParticle absPdg, float mass, AnyCharge chargeType) : GenericParticleHypothesis(absPdg, mass, chargeType) {} - ParticleHypothesis(PdgParticle absPdg) : GenericParticleHypothesis(absPdg) {} + explicit ParticleHypothesis(PdgParticle absPdg) + : GenericParticleHypothesis(absPdg) {} template constexpr ParticleHypothesis( @@ -179,7 +182,8 @@ class ParticleHypothesis : public GenericParticleHypothesis { } static ParticleHypothesis pionLike(float absQ) { - return ParticleHypothesis(pion().absolutePdg(), pion().mass(), absQ); + return ParticleHypothesis(pion().absolutePdg(), pion().mass(), + AnyCharge{absQ}); } static ParticleHypothesis geantino() { @@ -190,7 +194,7 @@ class ParticleHypothesis : public GenericParticleHypothesis { return cache; } static ParticleHypothesis chargedGeantino(float absQ) { - return ParticleHypothesis(PdgParticle::eInvalid, 0, absQ); + return ParticleHypothesis(PdgParticle::eInvalid, 0, AnyCharge{absQ}); } }; diff --git a/Core/include/Acts/EventData/TrackParametersConcept.hpp b/Core/include/Acts/EventData/TrackParametersConcept.hpp index 4369fe57141..488193e57f3 100644 --- a/Core/include/Acts/EventData/TrackParametersConcept.hpp +++ b/Core/include/Acts/EventData/TrackParametersConcept.hpp @@ -66,4 +66,11 @@ concept BoundTrackParametersConcept = }; }; +namespace Concepts { +template +concept BoundConvertibleTrackParameters = requires(const Parameters &p) { + { p.toBound() } -> BoundTrackParametersConcept; +}; +} // namespace Concepts + } // namespace Acts diff --git a/Core/include/Acts/Propagator/Propagator.hpp b/Core/include/Acts/Propagator/Propagator.hpp index 6a38e5d2a8f..fefc93fd6b0 100644 --- a/Core/include/Acts/Propagator/Propagator.hpp +++ b/Core/include/Acts/Propagator/Propagator.hpp @@ -299,7 +299,9 @@ class Propagator final template auto makeState(const parameters_t& start, - const propagator_options_t& options) const; + const propagator_options_t& options) const + requires Concepts::BasicTrackParameters && + Concepts::BoundConvertibleTrackParameters; /// @brief Builds the propagator state object /// @@ -322,7 +324,9 @@ class Propagator final typename target_aborter_t = SurfaceReached, typename path_aborter_t = PathLimitReached> auto makeState(const parameters_t& start, const Surface& target, - const propagator_options_t& options) const; + const propagator_options_t& options) const + requires Concepts::BasicTrackParameters && + Concepts::BoundConvertibleTrackParameters; /// @brief Propagate track parameters /// diff --git a/Core/include/Acts/Propagator/Propagator.ipp b/Core/include/Acts/Propagator/Propagator.ipp index 8a7c560a725..eb97013138c 100644 --- a/Core/include/Acts/Propagator/Propagator.ipp +++ b/Core/include/Acts/Propagator/Propagator.ipp @@ -150,7 +150,10 @@ template template auto Acts::Propagator::makeState( - const parameters_t& start, const propagator_options_t& options) const { + const parameters_t& start, const propagator_options_t& options) const + requires Concepts::BasicTrackParameters && + Concepts::BoundConvertibleTrackParameters +{ static_assert(BoundTrackParametersConcept, "Parameters do not fulfill bound parameters concept."); @@ -177,8 +180,8 @@ auto Acts::Propagator::makeState( // Initialize the internal propagator state StateType state{ eOptions, - m_stepper.makeState(eOptions.geoContext, eOptions.magFieldContext, start, - eOptions.stepping.maxStepSize), + m_stepper.makeState(eOptions.geoContext, eOptions.magFieldContext, + start.toBound(), eOptions.stepping.maxStepSize), m_navigator.makeState(eOptions.navigation)}; static_assert( @@ -196,7 +199,10 @@ template auto Acts::Propagator::makeState( const parameters_t& start, const Surface& target, - const propagator_options_t& options) const { + const propagator_options_t& options) const + requires Concepts::BasicTrackParameters && + Concepts::BoundConvertibleTrackParameters +{ static_assert(BoundTrackParametersConcept, "Parameters do not fulfill bound parameters concept."); diff --git a/Core/include/Acts/Surfaces/Surface.hpp b/Core/include/Acts/Surfaces/Surface.hpp index 43d8161aa8c..322050aa99d 100644 --- a/Core/include/Acts/Surfaces/Surface.hpp +++ b/Core/include/Acts/Surfaces/Surface.hpp @@ -89,7 +89,7 @@ class Surface : public virtual GeometryObject, /// /// @param transform Transform3 positions the surface in 3D global space /// @note also acts as default constructor - Surface(const Transform3& transform = Transform3::Identity()); + explicit Surface(const Transform3& transform = Transform3::Identity()); /// Copy constructor /// @@ -97,12 +97,12 @@ class Surface : public virtual GeometryObject, /// to detector element and layer /// /// @param other Source surface for copy. - Surface(const Surface& other); + explicit Surface(const Surface& other); /// Constructor from DetectorElementBase: Element proxy /// /// @param detelement Detector element which is represented by this surface - Surface(const DetectorElementBase& detelement); + explicit Surface(const DetectorElementBase& detelement); /// Copy constructor with optional shift /// diff --git a/Core/include/Acts/Utilities/Logger.hpp b/Core/include/Acts/Utilities/Logger.hpp index b9e499b74f3..8a6bc632494 100644 --- a/Core/include/Acts/Utilities/Logger.hpp +++ b/Core/include/Acts/Utilities/Logger.hpp @@ -446,8 +446,8 @@ class TimedOutputDecorator final : public OutputDecorator { /// /// @param [in] wrappee output print policy object to be wrapped /// @param [in] format format of time stamp (see std::strftime) - TimedOutputDecorator(std::unique_ptr wrappee, - const std::string& format = "%X") + explicit TimedOutputDecorator(std::unique_ptr wrappee, + const std::string& format = "%X") : OutputDecorator(std::move(wrappee)), m_format(format) {} /// @brief flush the debug message to the destination stream diff --git a/Examples/Python/src/EventData.cpp b/Examples/Python/src/EventData.cpp index 3f8cfa50342..01643473349 100644 --- a/Examples/Python/src/EventData.cpp +++ b/Examples/Python/src/EventData.cpp @@ -25,12 +25,16 @@ void addEventData(Context& ctx) { auto [m, mex] = ctx.get("main", "examples"); py::class_(m, "ParticleHypothesis") - .def(py::init(), py::arg("pdg"), - py::arg("mass"), py::arg("absCharge")) + .def(py::init([](Acts::PdgParticle absPdg, float mass, float absCharge) { + return Acts::ParticleHypothesis(absPdg, mass, + AnyCharge{absCharge}); + }), + py::arg("pdg"), py::arg("mass"), py::arg("absCharge")) .def(py::init([](std::underlying_type_t absPdg, float mass, float absCharge) { return Acts::ParticleHypothesis( - static_cast(absPdg), mass, absCharge); + static_cast(absPdg), mass, + AnyCharge{absCharge}); }), py::arg("absPdg"), py::arg("mass"), py::arg("absCharge")) .def("__str__", diff --git a/Fatras/include/ActsFatras/EventData/Particle.hpp b/Fatras/include/ActsFatras/EventData/Particle.hpp index fbf9244fcea..50511a2b93c 100644 --- a/Fatras/include/ActsFatras/EventData/Particle.hpp +++ b/Fatras/include/ActsFatras/EventData/Particle.hpp @@ -167,7 +167,9 @@ class Particle { /// Particle hypothesis. Acts::ParticleHypothesis hypothesis() const { - return Acts::ParticleHypothesis(absolutePdg(), mass(), absoluteCharge()); + return Acts::ParticleHypothesis( + absolutePdg(), mass(), + Acts::AnyCharge{static_cast(absoluteCharge())}); } /// Particl qOverP. double qOverP() const { diff --git a/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackContainer.hpp b/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackContainer.hpp index 79ccf2249a1..944013c40ea 100644 --- a/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackContainer.hpp +++ b/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackContainer.hpp @@ -135,7 +135,7 @@ class PodioTrackContainerBase { auto track = instance.m_collection->at(itrack); const auto& src = track.getParticleHypothesis(); return ParticleHypothesis{static_cast(src.absPdg), src.mass, - src.absQ}; + AnyCharge{src.absQ}}; } static void populateSurfaceBuffer( diff --git a/Tests/UnitTests/Core/Propagator/VolumeMaterialInteractionTests.cpp b/Tests/UnitTests/Core/Propagator/VolumeMaterialInteractionTests.cpp index 5bc361fc0a0..1786d8f80d4 100644 --- a/Tests/UnitTests/Core/Propagator/VolumeMaterialInteractionTests.cpp +++ b/Tests/UnitTests/Core/Propagator/VolumeMaterialInteractionTests.cpp @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(volume_material_interaction_test) { // Create a propagator state State state; state.stepping.particleHypothesis = - ParticleHypothesis(static_cast(11), 10., 9.); + ParticleHypothesis(static_cast(11), 10., AnyCharge{9.}); state.stepping.pos = Vector3(1., 2., 3.); state.stepping.dir = Vector3(4., 5., 6.); state.stepping.t = 7.;