diff --git a/docs/DESIGN.md b/docs/DESIGN.md index f50c95fe..20816cb1 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -97,12 +97,12 @@ All below class templates indirectly derive from a `scaled_unit` class template - Defines a named, in most cases base or coherent unit that is then passed to a dimension's definition. - A named unit may be used by other units defined with the prefix of the same type, unless - `no_prefix` is provided for `PrefixType` template parameter (in such a case it is impossible + `no_prefix` is provided for `PrefixFamily` template parameter (in such a case it is impossible to define a prefixed unit based on this one). - `named_scaled_unit` - Defines a new named unit that is a scaled version of another unit. - Such unit can be used by other units defined with the prefix of the same type, unless - `no_prefix` is provided for `PrefixType` template parameter (in such a case it is impossible + `no_prefix` is provided for `PrefixFamily` template parameter (in such a case it is impossible to define a prefixed unit based on this one). - `prefixed_unit` - Defines a new unit that is a scaled version of another unit by the provided prefix. @@ -115,26 +115,26 @@ All below class templates indirectly derive from a `scaled_unit` class template - All of the units provided should also be a named ones so it is possible to create a deduced symbol text. -Some of the above types depend on `PrefixType` and `no_prefix`. `PrefixType` is a concept that +Some of the above types depend on `PrefixFamily` and `no_prefix`. `PrefixFamily` is a concept that is defined as: ```cpp template -concept PrefixType = std::derived_from; +concept PrefixFamily = std::derived_from; ``` -where `prefix_type` is just an empty tag type used to identify the beginning of prefix types +where `prefix_family` is just an empty tag type used to identify the beginning of prefix types hierarchy and `no_prefix` is one of its children: ```cpp -struct prefix_type {}; -struct no_prefix : prefix_type {}; +struct prefix_family {}; +struct no_prefix : prefix_family {}; ``` Concrete prefix derives from a `prefix` class template: ```cpp -template +template requires (!std::same_as) struct prefix; ``` @@ -151,7 +151,7 @@ Coming back to units, here are a few examples of unit definitions: namespace units::si { // prefixes -struct prefix : prefix_type {}; +struct prefix : prefix_family {}; struct centi : units::prefix> {}; struct kilo : units::prefix> {}; @@ -508,7 +508,7 @@ a series of checks: dimension: - prefix: - if ratio of the scaled unit is `1`, than no prefix is being printed, - - otherwise, if `PrefixType` template parameter of a reference unit is different than + - otherwise, if `PrefixFamily` template parameter of a reference unit is different than `no_prefix`, and if the ratio of scaled unit matches the ratio of a prefix of a specified type, than the symbol of this prefix will be used, - otherwise, non-standard ratio (i.e. `2 [60]Hz`) will be printed. @@ -781,7 +781,7 @@ adds support for digital information quantities. In summary it adds: ```cpp namespace units::data { - struct prefix : prefix_type {}; + struct prefix : prefix_family {}; struct kibi : units::prefix> {}; struct mebi : units::prefix> {}; diff --git a/docs/_static/img/units.png b/docs/_static/img/units.png index 311abd6f..be543e5f 100644 Binary files a/docs/_static/img/units.png and b/docs/_static/img/units.png differ diff --git a/docs/framework/units.rst b/docs/framework/units.rst index a2f10be0..b38c6546 100644 --- a/docs/framework/units.rst +++ b/docs/framework/units.rst @@ -219,7 +219,7 @@ complete list of all the :term:`SI` prefixes supported by the library:: namespace si { - struct prefix : prefix_type {}; + struct prefix : prefix_family {}; struct yocto : units::prefix> {}; struct zepto : units::prefix> {}; @@ -249,7 +249,7 @@ domain:: namespace data { - struct prefix : prefix_type {}; + struct prefix : prefix_family {}; struct kibi : units::prefix> {}; struct mebi : units::prefix> {}; @@ -322,11 +322,11 @@ of a `scaled_unit` class template: #direction: right - [scaled_unit]<:-[unit] - [scaled_unit]<:-[named_unit] - [scaled_unit]<:-[named_scaled_unit] - [scaled_unit]<:-[prefixed_unit] - [scaled_unit]<:-[deduced_unit] + [scaled_unit]<:-[unit] + [scaled_unit]<:-[named_unit] + [scaled_unit]<:-[named_scaled_unit] + [scaled_unit]<:-[prefixed_unit] + [scaled_unit]<:-[deduced_unit] `scaled_unit` is a class template used exclusively by the library's framework and user should not instantiate it by him/her-self. However the user can sometimes diff --git a/docs/reference/concepts.rst b/docs/reference/concepts.rst index d8b42b9d..2e18c4b9 100644 --- a/docs/reference/concepts.rst +++ b/docs/reference/concepts.rst @@ -5,58 +5,69 @@ Concepts .. note:: - All names defined in this chapter reside in the :any:`units` namespace unless specified otherwise. + All names defined in this chapter reside in the :any:`units` namespace unless + specified otherwise. -.. concept:: template PrefixType +.. concept:: template PrefixFamily - Satisfied by all types derived from :class:`prefix_type`. + A concept matching a prefix family. Satisfied by all types derived from :class:`prefix_family`. .. concept:: template Prefix - Satisfied by all instantiations of :class:`prefix`. + A concept matching a symbol prefix. Satisfied by all instantiations of :class:`prefix`. .. concept:: template Ratio - Satisfied by all instantiations of :class:`ratio`. + A concept matching a ratio. Satisfied by all instantiations of :class:`ratio`. .. concept:: template UnitRatio - Satisfied by all types that satisfy :expr:`Ratio` and for which :expr:`R::num > 0` and :expr:`R::den > 0`. + A concept matching unit's ratio. Satisfied by all types that satisfy :expr:`Ratio` and + for which :expr:`R::num > 0` and :expr:`R::den > 0`. .. concept:: template BaseDimension - Satisfied by all dimension types derived from instantiation of :class:`base_dimension`. + A concept matching all base dimensions in the library. Satisfied by all dimension types + derived from the instantiation of :class:`base_dimension`. .. concept:: template Exponent - Satisfied by all instantiations of :class:`exp`. + A concept matching dimension's exponents. Satisfied by all instantiations of :class:`exp`. .. concept:: template DerivedDimension - Satisfied by all dimension types derived from instantiation of :class:`detail::derived_dimension_base`. + A concept matching all derived dimensions in the library. Satisfied by all dimension + types derived from the instantiation of :class:`detail::derived_dimension_base`. .. concept:: template Dimension - Satisfied by all dimension types for which either :expr:`BaseDimension` or :expr:`DerivedDimension` is ``true``. + A concept matching all dimensions in the library. Satisfied by all dimension types for + which either :expr:`BaseDimension` or :expr:`DerivedDimension` is ``true``. .. concept:: template Unit - Satisfied by all unit types derived from instantiation of :class:`scaled_unit`. + A concept matching all unit types in the library. Satisfied by all unit types derived + from the instantiation of :class:`scaled_unit`. .. concept:: template UnitOf - Satisfied by all unit types that satisfy :expr:`Unit`, :expr:`Dimension`, and for which - :expr:`U::reference` and :expr:`dimension_unit::reference` denote the same unit type. + A concept matching only units of a specified dimension. Satisfied by all unit types that + satisfy :expr:`Unit`, :expr:`Dimension`, and for which :expr:`U::reference` and + :expr:`dimension_unit::reference` denote the same unit type. + + :tparam U: Type to verify against concept constraints. + :tparam D: Dimension type to use for verification. .. concept:: template Quantity - Satisfied by all instantiations of :class:`quantity`. + A concept matching all quantities in the library. Satisfied by all instantiations of :class:`quantity`. .. concept:: template WrappedQuantity - Satisfied by all wrapper types that satisfy :expr:`Quantity` recursively - (i.e. :expr:`std::optional>`). + A concept matching types that wrap quantity objects. Satisfied by all wrapper types that + satisfy :expr:`Quantity` recursively + (i.e. :expr:`std::optional>`). .. concept:: template Scalar - Satisfied by types that satisfy :expr:`(!Quantity) && (!WrappedQuantity) && std::regular`. + A concept matching non-Quantity types. Satisfied by types that satisfy :expr:`(!Quantity) && (!WrappedQuantity) && std::regular`. diff --git a/src/include/units/bits/to_string.h b/src/include/units/bits/to_string.h index 31f844d7..3e91f9da 100644 --- a/src/include/units/bits/to_string.h +++ b/src/include/units/bits/to_string.h @@ -64,7 +64,7 @@ constexpr auto ratio_text() } } -template +template constexpr auto prefix_or_ratio_text() { if constexpr(Ratio::num == 1 && Ratio::den == 1 && Ratio::exp == 0) { @@ -72,11 +72,11 @@ constexpr auto prefix_or_ratio_text() return basic_fixed_string(""); } else { - if constexpr (!std::is_same_v) { + if constexpr (!std::is_same_v) { // try to form a prefix - using prefix = downcast>; + using prefix = downcast>; - if constexpr(!std::is_same_v>) { + if constexpr(!std::is_same_v>) { // print as a prefixed unit return prefix::symbol; } @@ -149,7 +149,7 @@ constexpr auto unit_text() // print as a prefix or ratio of a coherent unit using coherent_unit = dimension_unit; using ratio = ratio_divide; - auto prefix_txt = prefix_or_ratio_text(); + auto prefix_txt = prefix_or_ratio_text(); if constexpr(has_symbol) { // use predefined coherent unit symbol diff --git a/src/include/units/concepts.h b/src/include/units/concepts.h index 8bb3e666..f1a5b9cf 100644 --- a/src/include/units/concepts.h +++ b/src/include/units/concepts.h @@ -42,11 +42,16 @@ concept basic_arithmetic = // exposition only } // namespace detail -// PrefixType -struct prefix_type; +// PrefixFamily +struct prefix_family; +/** + * @brief A concept matching a prefix family + * + * Satisfied by all types derived from `prefix_family` + */ template -concept PrefixType = std::derived_from; +concept PrefixFamily = std::derived_from; // Prefix // TODO gcc:92150 @@ -56,11 +61,16 @@ concept PrefixType = std::derived_from; // template // inline constexpr bool is_prefix = false; -// template -// inline constexpr bool is_prefix> = true; +// template +// inline constexpr bool is_prefix> = true; // } // namespace detail +/** + * @brief A concept matching a symbol prefix + * + * Satisfied by all instantiations of `prefix`. + */ template // concept Prefix = detail::is_prefix; concept Prefix = true; @@ -73,11 +83,19 @@ inline constexpr bool is_ratio = false; } // namespace detail +/** + * @brief A concept matching a ratio + * + * Satisfied by all instantiations of `ratio`. + */ template concept Ratio = detail::is_ratio; - -// UnitRatio +/** + * @brief A concept matching unit's ratio + * + * Satisfied by all types that satisfy `Ratio` and for which `R::num > 0` and `R::den > 0` + */ template concept UnitRatio = Ratio && R::num > 0 && R::den > 0; // double negatives not allowed @@ -85,10 +103,14 @@ concept UnitRatio = Ratio && R::num > 0 && R::den > 0; // double negatives no template struct scaled_unit; +/** + * @brief A concept matching all unit types in the library + * + * Satisfied by all unit types derived from the instantiation of :class:`scaled_unit`. + */ template concept Unit = is_derived_from_instantiation; -// BaseDimension template requires U::is_named struct base_dimension; @@ -112,6 +134,11 @@ inline constexpr bool is_base_dimension> = true; } // namespace detail +/** + * @brief A concept matching all base dimensions in the library. + * + * Satisfied by all dimension types derived from the instantiation of `base_dimension`. + */ template concept BaseDimension = detail::is_base_dimension; @@ -123,6 +150,11 @@ inline constexpr bool is_exp = false; } // namespace detail +/** + * @brief A concept matching dimension's exponents. + * + * Satisfied by all instantiations of :class:`exp`. + */ template concept Exponent = detail::is_exp; @@ -135,10 +167,20 @@ struct derived_dimension_base; } // namespace detail +/** + * @brief A concept matching all derived dimensions in the library. + * + * Satisfied by all dimension types derived from the instantiation of `detail::derived_dimension_base`. + */ template concept DerivedDimension = is_instantiation, detail::derived_dimension_base>; // Dimension +/** + * @brief A concept matching all dimensions in the library. + * + * Satisfied by all dimension types for which either `BaseDimension` or `DerivedDimension` is `true`. + */ template concept Dimension = BaseDimension || DerivedDimension; @@ -163,6 +205,15 @@ struct dimension_unit_impl { template using dimension_unit = detail::dimension_unit_impl::type; +/** + * @brief A concept matching only units of a specified dimension. + * + * Satisfied by all unit types that satisfy `Unit`, `Dimension`, and for which + * `U::reference` and `dimension_unit::reference` denote the same unit type. + * + * @tparam U Type to verify. + * @tparam D Dimension type to use for verification. + */ template concept UnitOf = Unit && @@ -177,6 +228,11 @@ inline constexpr bool is_quantity = false; } // namespace detail +/** + * @brief A concept matching all quantities in the library. + * + * Satisfied by all instantiations of :class:`quantity`. + */ template concept Quantity = detail::is_quantity; @@ -193,11 +249,22 @@ inline constexpr bool is_wrapped_quantity = Quantity } // namespace detail +/** + * @brief A concept matching types that wrap quantity objects. + * + * Satisfied by all wrapper types that satisfy `Quantity` + * recursively (i.e. `std::optional>`). + */ template concept WrappedQuantity = detail::is_wrapped_quantity; // Scalar +/** + * @brief A concept matching non-Quantity types. + * + * Satisfied by types that satisfy `(!Quantity) && (!WrappedQuantity) && std::regular`. + */ template -concept Scalar = (!Quantity) && (!WrappedQuantity) && std::regular; // && std::totally_ordered;// && detail::basic_arithmetic; +concept Scalar = (!Quantity) && (!WrappedQuantity) && std::regular; // TODO: && std::totally_ordered;// && detail::basic_arithmetic; } // namespace units diff --git a/src/include/units/data/prefixes.h b/src/include/units/data/prefixes.h index 5cdd3e21..4e6e683a 100644 --- a/src/include/units/data/prefixes.h +++ b/src/include/units/data/prefixes.h @@ -26,7 +26,7 @@ namespace units::data { -struct prefix : prefix_type {}; +struct prefix : prefix_family {}; struct kibi : units::prefix> {}; struct mebi : units::prefix> {}; diff --git a/src/include/units/physical/si/prefixes.h b/src/include/units/physical/si/prefixes.h index 30d3e8ad..4a0dcf99 100644 --- a/src/include/units/physical/si/prefixes.h +++ b/src/include/units/physical/si/prefixes.h @@ -26,7 +26,7 @@ namespace units::si { -struct prefix : prefix_type {}; +struct prefix : prefix_family {}; // clang-format off struct yocto : units::prefix> {}; diff --git a/src/include/units/prefix.h b/src/include/units/prefix.h index 06bb76ce..46951bfd 100644 --- a/src/include/units/prefix.h +++ b/src/include/units/prefix.h @@ -29,11 +29,11 @@ namespace units { /** - * @brief The base for all prefix types + * @brief The base for all prefix families * - * Every prefix type should inherit from this type to satisfy PrefixType concept. + * Every prefix family should inherit from this type to satisfy PrefixFamily concept. */ -struct prefix_type {}; +struct prefix_family {}; /** * @brief No prefix possible for the unit @@ -41,13 +41,13 @@ struct prefix_type {}; * This is a special prefix type tag specifying that the unit can not be scaled with any kind * of the prefix. */ -struct no_prefix : prefix_type {}; +struct no_prefix : prefix_family {}; namespace detail { -template +template struct prefix_base : downcast_base> { - using prefix_type = PT; + using prefix_family = PT; using ratio = R; }; @@ -68,7 +68,7 @@ struct prefix_base : downcast_base> { * @tparam Symbol a text representation of the prefix * @tparam R factor to be used to scale a unit */ -template +template requires (!std::same_as) struct prefix : downcast_child> { static constexpr auto symbol = Symbol; diff --git a/src/include/units/unit.h b/src/include/units/unit.h index 9471f993..2654eafd 100644 --- a/src/include/units/unit.h +++ b/src/include/units/unit.h @@ -72,7 +72,7 @@ struct same_unit_reference : std::is_same struct unit : downcast_child, Child>> { static constexpr bool is_named = false; - using prefix_type = no_prefix; + using prefix_family = no_prefix; }; /** @@ -94,11 +94,11 @@ struct unknown_coherent_unit : unit {}; * @tparam Symbol a short text representation of the unit * @tparam PT no_prefix or a type of prefix family */ -template +template struct named_unit : downcast_child, Child>> { static constexpr bool is_named = true; static constexpr auto symbol = Symbol; - using prefix_type = PT; + using prefix_family = PT; }; /** @@ -115,11 +115,11 @@ struct named_unit : downcast_child, Child>> { * @tparam R a scale to apply to U * @tparam U a reference unit to scale */ -template +template struct named_scaled_unit : downcast_child, typename U::reference>> { static constexpr bool is_named = true; static constexpr auto symbol = Symbol; - using prefix_type = PT; + using prefix_family = PT; }; /** @@ -134,12 +134,12 @@ struct named_scaled_unit : downcast_child - requires U::is_named && std::same_as + requires U::is_named && std::same_as struct prefixed_unit : downcast_child, typename U::reference>> { static constexpr bool is_named = true; static constexpr auto symbol = P::symbol + U::symbol; - using prefix_type = no_prefix; + using prefix_family = no_prefix; }; /** @@ -161,14 +161,14 @@ template struct deduced_unit : downcast_child> { static constexpr bool is_named = false; static constexpr auto symbol = detail::deduced_symbol_text(); - using prefix_type = no_prefix; + using prefix_family = no_prefix; }; -// template +// template // struct named_deduced_derived_unit : downcast_child> { // static constexpr bool is_named = true; // static constexpr auto symbol = Symbol; -// using prefix_type = PT; +// using prefix_family = PT; // }; } // namespace units