diff --git a/README.md b/README.md index c6fffc45..f4c3b068 100644 --- a/README.md +++ b/README.md @@ -117,29 +117,13 @@ So for example to create a `dimension_velocity` type we have to do: struct dimension_velocity : make_dimension_t, exp> {}; ``` -Also for example to return the result of multiplying two different dimensions we have to -create a final dimension type using: - -```cpp -template -struct dimension_multiply; - -template -struct dimension_multiply, dimension> { - using type = upcasting_traits_t>; -}; - -template -using dimension_multiply_t = typename dimension_multiply::type; -``` - In order to make `make_dimension_t` work as expected it has to provide unique ordering for contained base dimensions. Beside providing ordering to base dimensions it also has to: - aggregate two arguments of the same base dimension but different exponents - eliminate two arguments of the same base dimension and with opposite equal exponents Additionally, it would be good if the final type produced by `make_dimension_t` would be easy to -understand by the user. For example we may decide to order base dimensions with decreasing order of +understand for the user. For example we may decide to order base dimensions with decreasing order of their exponents. That is why second sorting of a type list may be required. For example: ```cpp @@ -149,6 +133,39 @@ struct make_dimension { }; ``` + +#### `merge_dimension` + +`units::merge_dimension` is similar to `make_dimension` but instead of sorting the whole list +of base dimensions from scratch it assumes that provided input `dimension` types are already +sorted as a result of `make_dimension`. + +Typical use case for `merge_dimension` is to produce final `dimension` return type of multiplying +two different dimensions: + +```cpp +template +struct dimension_multiply; + +template +struct dimension_multiply, dimension> { + using type = upcasting_traits_t>; +}; + +template +using dimension_multiply_t = typename dimension_multiply::type; +``` + +Example implementation of `merge_dimension` may look like: + +```cpp +template +struct merge_dimension { + using type = mp::type_list_sort_t, exp_dim_id_less>>, exp_greater_equal>; +}; +``` + + ### `Units` `units::unit` is a class template that expresses the unit of a specific physical dimension: @@ -414,7 +431,7 @@ Additionally, it should make the error logs even shorter thus easier to understa In such a case all the operators have to be provided to a child class. Or maybe use CRTP? -3. What to do with time which ia ambiguous? +3. What to do with `time` which is ambiguous? 4. What to do with `std::chrono::duration`? diff --git a/src/include/units/dimension.h b/src/include/units/dimension.h index 62463f26..52dc6221 100644 --- a/src/include/units/dimension.h +++ b/src/include/units/dimension.h @@ -162,13 +162,21 @@ namespace units { template using make_dimension_t = typename make_dimension::type; + template + struct merge_dimension { + using type = mp::type_list_sort_t, exp_dim_id_less>>, exp_greater_equal>; + }; + + template + using merge_dimension_t = typename merge_dimension::type; + // dimension_multiply template struct dimension_multiply; template - struct dimension_multiply, dimension> : std::type_identity>> {}; + struct dimension_multiply, dimension> : std::type_identity>> {}; template using dimension_multiply_t = typename dimension_multiply::type;