diff --git a/src/core/include/units/bits/quantity_concepts.h b/src/core/include/units/bits/quantity_concepts.h index b4341305..9d4e08e4 100644 --- a/src/core/include/units/bits/quantity_concepts.h +++ b/src/core/include/units/bits/quantity_concepts.h @@ -25,11 +25,48 @@ #include #include #include -#include #include namespace units { +/** + * @brief Quantity character + * + * Scalars, vectors and tensors are mathematical objects that can be used to + * denote certain physical quantities and their values. They are as such + * independent of the particular choice of a coordinate system, whereas + * each scalar component of a vector or a tensor and each component vector and + * component tensor depend on that choice. + * + * A scalar is a physical quantity that has magnitude but no direction. + * + * Vectors are physical quantities that possess both magnitude and direction + * and whose operations obey the axioms of a vector space. + * + * Tensors can be used to describe more general physical quantities. + * For example, the Cauchy stress tensor possess magnitude, direction, + * and orientation qualities. + */ +enum class quantity_character { scalar, vector, tensor }; + +namespace detail { + +template +inline constexpr bool is_specialization_of_derived_quantity_spec = false; + +} + +/** + * @brief Concept matching quantity specification types + * + * Satisfied by all `derived_quantity_spec` specializations. + */ +template +concept DerivedQuantitySpec = detail::is_specialization_of_derived_quantity_spec; + +template +concept QuantitySpec = NamedQuantitySpec || DerivedQuantitySpec; + template struct reference; diff --git a/src/core/include/units/quantity_spec.h b/src/core/include/units/quantity_spec.h index bc08cdd7..ce253ebb 100644 --- a/src/core/include/units/quantity_spec.h +++ b/src/core/include/units/quantity_spec.h @@ -26,32 +26,13 @@ #include #include #include +#include #include #include #include namespace units { -/** - * @brief Quantity character - * - * Scalars, vectors and tensors are mathematical objects that can be used to - * denote certain physical quantities and their values. They are as such - * independent of the particular choice of a coordinate system, whereas - * each scalar component of a vector or a tensor and each component vector and - * component tensor depend on that choice. - * - * A scalar is a physical quantity that has magnitude but no direction. - * - * Vectors are physical quantities that possess both magnitude and direction - * and whose operations obey the axioms of a vector space. - * - * Tensors can be used to describe more general physical quantities. - * For example, the Cauchy stress tensor possess magnitude, direction, - * and orientation qualities. - */ -enum class quantity_character { scalar, vector, tensor }; - namespace detail { // TODO revise the note in the below comment @@ -90,9 +71,6 @@ template return ch; } -template -inline constexpr bool is_specialization_of_derived_quantity_spec = false; - template inline constexpr bool is_dimensionless = false; @@ -111,17 +89,6 @@ inline constexpr bool is_per_of_quantity_specs> = } // namespace detail -/** - * @brief Concept matching quantity specification types - * - * Satisfied by all `derived_quantity_spec` specializations. - */ -template -concept DerivedQuantitySpec = detail::is_specialization_of_derived_quantity_spec; - -template -concept QuantitySpec = NamedQuantitySpec || DerivedQuantitySpec; - template concept DerivedQuantitySpecExpr = NamedQuantitySpec || detail::is_dimensionless || detail::is_power_of_quantity_spec || detail::is_per_of_quantity_specs; @@ -167,9 +134,6 @@ concept associated_unit = Unit && requires(U u) { get_dimension_for_impl(get_ } // namespace detail -template -struct reference; - /** * @brief A specification of a derived quantity * @@ -247,6 +211,13 @@ struct derived_quantity_spec : detail::expr_fractions, Q return reference{}; } #endif + + template Rep, Unit U> + [[nodiscard]] consteval Quantity auto operator()(Rep&& v, U u) const + requires(dimension == detail::get_dimension_for(u)) + { + return (*this)[u](std::forward(v)); + } }; namespace detail { @@ -329,6 +300,13 @@ struct quantity_spec { { return reference{}; } + + template Rep, Unit U> + [[nodiscard]] consteval Quantity auto operator()(Rep&& v, U u) const + requires(dimension == detail::get_dimension_for(u)) + { + return (*this)[u](std::forward(v)); + } }; /** @@ -391,6 +369,13 @@ struct quantity_spec : std::remove_const_t { { return reference{}; } + + template Rep, Unit U> + [[nodiscard]] consteval Quantity auto operator()(Rep&& v, U u) const + requires(this->dimension == detail::get_dimension_for(u)) + { + return (*this)[u](std::forward(v)); + } #endif }; diff --git a/src/core/include/units/reference.h b/src/core/include/units/reference.h index f937b368..e8987a32 100644 --- a/src/core/include/units/reference.h +++ b/src/core/include/units/reference.h @@ -23,7 +23,6 @@ #pragma once #include -#include #include namespace units { @@ -51,6 +50,13 @@ struct reference { static constexpr QuantitySpec auto quantity_spec = Q; static constexpr Dimension auto dimension = Q.dimension; static constexpr Unit auto unit = U; + + template Rep> + // TODO can we somehow return an explicit quantity type here? + [[nodiscard]] constexpr Quantity auto operator()(Rep&& value) const + { + return quantity(std::forward(value)); + } }; // Reference @@ -67,12 +73,14 @@ template return {}; } +// TODO remove when all code is refactored to a new syntax template [[nodiscard]] constexpr quantity operator*(const Rep& lhs, R) { return quantity(lhs); } +// TODO remove when all code is refactored to a new syntax void /*Use `q * (1 * r)` rather than `q * r`.*/ operator*(Quantity auto, Reference auto) = delete; template