mpusz / mp-units

The quantities and units library for C++
https://mpusz.github.io/mp-units/
MIT License
1.08k stars 86 forks source link

refactor(core): factor out common quantity-like requirements #627

Open JohelEGP opened 1 week ago

JohelEGP commented 1 week ago

Title: refactor(core): factor out common quantity-like requirements

Description:

QuantityLike and QuantityPointLike share many requirements: https://github.com/mpusz/mp-units/blob/89bafed9619a4a8320046e2be621172a6e88b586/src/core/include/mp-units/framework/quantity_concepts.h#L73-L83 https://github.com/mpusz/mp-units/blob/89bafed9619a4a8320046e2be621172a6e88b586/src/core/include/mp-units/framework/quantity_point_concepts.h#L137-L151

I suggest factoring them out, for example:

template<typename T, template<typename> typename Traits>
concept detail::qty_like = requires(const T& qty, const Traits<T>::rep& num) {
  typename quantity<Traits<T>::reference, typename Traits<T>::rep>;
  { Traits<T>::to_numerical_value(qty) } -> std::same_as<typename Traits<T>::rep>;
  { Traits<T>::from_numerical_value(num) } -> std::same_as<T>;
  { Traits<T>::explicit_import } -> std::same_as<const bool>;
  { Traits<T>::explicit_export } -> std::same_as<const bool>;
  typename std::bool_constant<Traits<T>::explicit_import>;
  typename std::bool_constant<Traits<T>::explicit_export>;
};

template<typename T>
concept quantity_like = detail::qty_like<T, quantity_like_traits>;

template<typename T>
concept quantity_point_like =
  detail::qty_like<T, quantity_point_like_traits> &&  //
  requires {
    typename quantity_point<quantity_point_like_traits<T>::reference,
                            typename quantity_point_like_traits<T>::point_origin,
                            typename quantity_point_like_traits<T>::rep>;
  };

See also:

JohelEGP commented 1 week ago

Don't we need to restrict T to not be a specialization of quantity and quantity_point?

mpusz commented 1 week ago

Good points!

Interfaces were different, but we unified them with #531. I am fine with refactoring as long as we do not provide public subsumptions between those two concepts.

Don't we need to restrict T to not be a specialization of quantity and quantity_point?

Another good idea. But we should use derived_from_specialization_of instead, as some users do inherit from our types, and we already account for that in interfaces (e.g., operators).