diff --git a/example/v2_framework.cpp b/example/v2_framework.cpp index 9fbf1f4c..1167c7f0 100644 --- a/example/v2_framework.cpp +++ b/example/v2_framework.cpp @@ -27,22 +27,36 @@ namespace units::isq { inline constexpr struct dim_length : base_dimension<"L"> { } dim_length; +inline constexpr struct dim_mass : base_dimension<"M"> { +} dim_mass; +inline constexpr struct dim_time : base_dimension<"T"> { +} dim_time; +inline constexpr struct dim_electric_current : base_dimension<"I"> { +} dim_electric_current; +// TODO Should the below use basic_symbol_text? How to name it for ASCII? +inline constexpr struct dim_thermodynamic_temperature : base_dimension<"Θ"> { +} dim_thermodynamic_temperature; +inline constexpr struct dim_amount_of_substance : base_dimension<"N"> { +} dim_amount_of_substance; +inline constexpr struct dim_luminous_intensity : base_dimension<"J"> { +} dim_luminous_intensity; + +// using dim_speed = decltype(dim_length / dim_time); +// inline constexpr dim_speed dim_speed; // template // concept Length = QuantityOf; -inline constexpr struct dim_time : base_dimension<"T"> { -} dim_time; -inline constexpr struct dim_frequency : decltype(1 / dim_time) { -} dim_frequency; -inline constexpr struct dim_area : decltype(dim_length * dim_length) { -} dim_area; -inline constexpr struct dim_volume : decltype(dim_area * dim_length) { -} dim_volume; -inline constexpr struct dim_speed : decltype(dim_length / dim_time) { -} dim_speed; -inline constexpr struct dim_acceleration : decltype(dim_speed / dim_time) { -} dim_acceleration; +// inline constexpr struct dim_frequency : decltype(1 / dim_time) { +// } dim_frequency; +// inline constexpr struct dim_area : decltype(dim_length * dim_length) { +// } dim_area; +// inline constexpr struct dim_volume : decltype(dim_area * dim_length) { +// } dim_volume; +// inline constexpr struct dim_speed : decltype(dim_length / dim_time) { +// } dim_speed; +// inline constexpr struct dim_acceleration : decltype(dim_speed / dim_time) { +// } dim_acceleration; // inline constexpr auto speed = length / time; @@ -198,15 +212,21 @@ inline constexpr struct length : system_reference { } length; inline constexpr struct time : system_reference { } time; -inline constexpr struct frequency : system_reference { +// inline constexpr struct frequency : system_reference { +inline constexpr struct frequency : system_reference { } frequency; -inline constexpr struct area : system_reference { +// inline constexpr struct area : system_reference { +inline constexpr struct area : system_reference { } area; -inline constexpr struct volume : system_reference { +// inline constexpr struct volume : system_reference { +inline constexpr struct volume : system_reference { } volume; -inline constexpr struct speed : system_reference { +// inline constexpr struct speed : system_reference { +inline constexpr struct speed : system_reference { } speed; -inline constexpr struct acceleration : system_reference { +// inline constexpr struct acceleration : system_reference { +inline constexpr struct acceleration : + system_reference { } acceleration; } // namespace units::isq::si @@ -257,47 +277,51 @@ static_assert(is_of_type, per>>>); static_assert(is_of_type); -static_assert( - is_of_type>>); -static_assert( - is_of_type>>); -static_assert(is_of_type, per>>); -static_assert(is_of_type<1 / (dim_speed * dim_speed) * dim_length, - derived_dimension>>>); +// static_assert( +// is_of_type>>); +// static_assert( +// is_of_type>>); +// static_assert(is_of_type, per>>); +// static_assert(is_of_type<1 / (dim_speed * dim_speed) * dim_length, +// derived_dimension>>>); + +namespace si { // comparisons of equivalent dimensions static_assert(dim_length / dim_length == dim_one); -static_assert(1 / dim_time == dim_frequency); -static_assert(1 / dim_frequency == dim_time); -static_assert(dim_frequency * dim_time == dim_one); +static_assert(1 / dim_time == frequency::dimension); +static_assert(1 / frequency::dimension == dim_time); +static_assert(frequency::dimension * dim_time == dim_one); -static_assert(dim_length * dim_length == dim_area); -static_assert(dim_length * dim_length != dim_volume); -static_assert(dim_area / dim_length == dim_length); +static_assert(dim_length * dim_length == area::dimension); +static_assert(dim_length * dim_length != volume::dimension); +static_assert(area::dimension / dim_length == dim_length); -static_assert(dim_length * dim_length * dim_length == dim_volume); -static_assert(dim_area * dim_length == dim_volume); -static_assert(dim_volume / dim_length == dim_area); -static_assert(dim_volume / dim_length / dim_length == dim_length); -static_assert(dim_area * dim_area / dim_length == dim_volume); -static_assert(dim_area * (dim_area / dim_length) == dim_volume); -static_assert(dim_volume / (dim_length * dim_length) == dim_length); +static_assert(dim_length * dim_length * dim_length == volume::dimension); +static_assert(area::dimension * dim_length == volume::dimension); +static_assert(volume::dimension / dim_length == area::dimension); +static_assert(volume::dimension / dim_length / dim_length == dim_length); +static_assert(area::dimension * area::dimension / dim_length == volume::dimension); +static_assert(area::dimension * (area::dimension / dim_length) == volume::dimension); +static_assert(volume::dimension / (dim_length * dim_length) == dim_length); -static_assert(dim_length / dim_time == dim_speed); -static_assert(dim_length * dim_time != dim_speed); -static_assert(dim_length / dim_time / dim_time != dim_speed); -static_assert(dim_length / dim_speed == dim_time); -static_assert(dim_speed * dim_time == dim_length); +static_assert(dim_length / dim_time == speed::dimension); +static_assert(dim_length * dim_time != speed::dimension); +static_assert(dim_length / dim_time / dim_time != speed::dimension); +static_assert(dim_length / speed::dimension == dim_time); +static_assert(speed::dimension * dim_time == dim_length); -static_assert(dim_length / dim_time / dim_time == dim_acceleration); -static_assert(dim_length / (dim_time * dim_time) == dim_acceleration); -static_assert(dim_speed / dim_time == dim_acceleration); -static_assert(dim_speed / dim_acceleration == dim_time); -static_assert(dim_acceleration * dim_time == dim_speed); -static_assert(dim_acceleration * (dim_time * dim_time) == dim_length); -static_assert(dim_acceleration / dim_speed == dim_frequency); +static_assert(dim_length / dim_time / dim_time == acceleration::dimension); +static_assert(dim_length / (dim_time * dim_time) == acceleration::dimension); +static_assert(speed::dimension / dim_time == acceleration::dimension); +static_assert(speed::dimension / acceleration::dimension == dim_time); +static_assert(acceleration::dimension * dim_time == speed::dimension); +static_assert(acceleration::dimension * (dim_time * dim_time) == dim_length); +static_assert(acceleration::dimension / speed::dimension == frequency::dimension); + +} // namespace si } // namespace units::isq @@ -344,35 +368,35 @@ static_assert(is_of_type #include -#include #include namespace units { @@ -87,99 +86,24 @@ concept Dimension = BaseDimension || DerivedDimension; namespace detail { -/** - * @brief Unpacks the list of potentially derived dimensions to a list containing only base dimensions - * - * @tparam Es Exponents of potentially derived dimensions - */ -template -struct dim_extract; - -template<> -struct dim_extract, type_list<>> { - using num = type_list<>; - using den = type_list<>; -}; - -template - requires BaseDimension || BaseDimension -struct dim_extract, type_list> { - using impl = dim_extract, type_list>; - using num = type_list_push_front; - using den = TYPENAME impl::den; -}; - -template - requires BaseDimension || BaseDimension -struct dim_extract, type_list> { - using impl = dim_extract, type_list>; - using num = TYPENAME impl::num; - using den = type_list_push_front; -}; - -template -struct dim_extract, type_list> : - dim_extract, - type_list_push_back> {}; - -template -struct dim_extract, NRest...>, type_list> : - dim_extract::num, power::den>::type, - NRest...>, - type_list_push_back< - typename expr_power::num, power::den>::type, - Dens...>> {}; - - -template -struct dim_extract, type_list> : - dim_extract> {}; - -template -struct dim_extract, type_list, DRest...>> : - dim_extract::num, power::den>::type, - type_list_push_back< - typename expr_power::num, power::den>::type, - DRest...>> {}; template using type_list_of_base_dimension_less = expr_less; -/** - * @brief Converts user provided derived dimension specification into a valid units::normalized_dimension definition - * - * User provided definition of a derived dimension may contain the same base dimension repeated more than once on the - * list possibly hidden in other derived units provided by the user. The process here should: - * 1. Extract derived dimensions into exponents of base dimensions. - * 2. Sort the exponents so the same dimensions are placed next to each other. - * 3. Consolidate contiguous range of exponents of the same base dimensions to a one (or possibly zero) exponent for - * this base dimension. - */ -template -struct normalized_dimension : detail::expr_fractions { -private: - using base = detail::expr_fractions; - using extracted = dim_extract; - using num_list = expr_consolidate>; - using den_list = expr_consolidate>; - using simple = expr_simplify; -public: - using normalized_num = TYPENAME simple::num; - using normalized_den = TYPENAME simple::den; -}; +template +inline constexpr bool is_dim_one = false; } // namespace detail // TODO add checking for `per` and power elements as well template -concept DimensionSpec = Dimension || is_specialization_of || detail::is_specialization_of_power; +concept DimensionSpec = + BaseDimension || detail::is_dim_one || is_specialization_of || detail::is_specialization_of_power; // User should not instantiate this type!!! +// It should not be exported from the module template -struct derived_dimension : detail::normalized_dimension, Ds...> {}; - -// TODO move type_list_fractions out of +struct derived_dimension : detail::expr_fractions, Ds...> {}; template std::true_type is_derived_dimension(const volatile derived_dimension*); @@ -195,66 +119,42 @@ inline constexpr struct dim_one : derived_dimension<> { namespace detail { -template -struct dimension_less : std::bool_constant() < type_name()> {}; - -template -using type_list_of_dimension_less = expr_less; +template<> +inline constexpr bool is_dim_one = true; } // namespace detail template -constexpr Dimension auto operator*(D1, D2) +[[nodiscard]] constexpr Dimension auto operator*(D1, D2) { - return detail::expr_multiply(); + return detail::expr_multiply(); } template -constexpr Dimension auto operator/(D1, D2) +[[nodiscard]] constexpr Dimension auto operator/(D1, D2) { - return detail::expr_divide(); + return detail::expr_divide(); } template -constexpr Dimension auto operator/(int value, D) +[[nodiscard]] constexpr Dimension auto operator/(int value, D) { gsl_Assert(value == 1); return detail::expr_invert(); } template -constexpr bool operator==(D1, D2) +[[nodiscard]] constexpr bool operator==(D1, D2) { return false; } -template -constexpr bool operator==(D1, D2) +template +[[nodiscard]] constexpr bool operator==(D, D) { - return D1::symbol == D2::symbol; + return true; } -template - requires(type_list_size == 0) && (type_list_size == 1) && - BaseDimension> -constexpr bool operator==(D1, D2) -{ - return D1::symbol == type_list_front::symbol; -} - -template - requires(type_list_size == 0) && (type_list_size == 1) && - BaseDimension> -constexpr bool operator==(D1, D2) -{ - return type_list_front::symbol == D2::symbol; -} - -template -constexpr bool operator==(D1, D2) -{ - return is_same_v && - is_same_v; -} +// TODO consider adding the support for text output of the dimensional equation } // namespace units