13 KiB
Concepts
This chapter enumerates all the user-facing concepts in the mp-units library.
Dimension<T>
Dimension concept matches a dimension of either a
base or derived quantity:
- Base dimensions are explicitly defined by the
user by inheriting from the instantiation of a
base_dimensionclass template. It should be instantiated with a unique symbol identifier describing this dimension in a specific system of quantities. - Derived dimensions are implicitly created by the library's framework based on the quantity equation provided in the quantity specification.
DimensionOf<T, V>
DimensionOf concept is satisfied when both arguments satisfy a Dimension
concept and when they compare equal.
QuantitySpec<T>
QuantitySpec concept matches all the
quantity specifications including:
- Base quantities defined by a user by inheriting
from the
quantity_specclass template instantiated with a base dimension argument. - Derived named quantities defined by a user
by inheriting from the
quantity_specclass template instantiated with a result of a quantity equation passed as an argument. - Other named quantities forming a
hierarchy of quantities of the same
kind defined by a user by inheriting from the
quantity_specclass template instantiated with another "parent" quantity specification passed as an argument. - Quantity kinds describing a family of mutually comparable quantities.
- Intermediate derived quantity specifications being a result of a quantity equations on other specifications.
QuantitySpecOf<T, V>
QuantitySpecOf concept is satisfied when both arguments satisfy a
QuantitySpec concept and when T is implicitly convertible to V.
UnitMagnitude<T>
UnitMagnitude concept is satisfied by all types defining a unit magnitude.
!!! info
Unit magnitude implementation is a private implementation detail of the library.
Unit<T>
Unit concept matches all the units in the library including:
- Base units defined by a user by inheriting from
the
named_unitclass template instantiated with a unique symbol identifier describing this unit in a specific system of units. - Named scaled units defined by a user by inheriting from the
named_unitclass template instantiated with a unique symbol identifier and a product of multiplying another unit with some magnitude. - Prefixed units defined by a user by inheriting from the
prefixed_unitclass template instantiated with a prefix symbol, a magnitude, and a unit to be prefixed. - Derived named units defined by a user by
inheriting from the
named_unitclass template instantiated with a unique symbol identifier and a result of unit equation passed as an argument. - Derived unnamed units being a result of a unit equations on other units.
- Physical constants defined by a user by inheriting from the
named_constantclass template instantiated with a unique symbol identifier and a product of multiplying another unit with some magnitude.
PrefixableUnit<T>
PrefixableUnit concept is satisfied by all units derived from a named_unit class template.
Such units can be passed as an argument to a prefixed_unit class template.
UnitOf<T, V>
UnitOf concept is satisfied for all units T for which an associated quantity spec is implicitly
convertible to the provided QuantitySpec value.
Reference<T>
Reference concept is satisfied by all quantity reference
types. Such types provide all the meta-information required to create a Quantity.
A Reference can either be:
- A
Unit. - The instantiation of a
referenceclass template with aQuantitySpecpassed as the first template argument and aUnitpassed as the second one.
ReferenceOf<T, V>
ReferenceOf concept is satisfied by references T which have a quantity specification
that satisfies QuantitySpecOf<V> concept.
RepresentationOf<T, V>
RepresentationOf concept constrains a type T of a number that stores the
numerical value of a quantity.
Every representation type must satisfy a common baseline:
- Weakly regular: copyable and equality comparable (default-constructibility is not required).
MagnitudeScalable: the library must be able to apply a unit magnitude ratio to it internally. Most standard types satisfy this automatically via the built-in scaling paths; custom types may additionally provideoperator*(T, UnitMagnitude)for magnitude-aware scaling that can change the representation type during unit conversion. See Representation Types for details.- Character-specific operations: additional arithmetic operations required by the
quantity character (e.g. total ordering for real
scalars,
real()/imag()/modulus()CPOs for complex scalars,norm()/magnitude()CPO for vectors).
The second template argument V further constrains which characters are accepted:
-
if the type of
VsatisfiesQuantitySpec:- by all representation types when
Vdescribes a quantity kind, - otherwise, by representation types that are of
a quantity character associated with a provided
quantity specification
V.
- by all representation types when
-
if
Vis ofquantity_charactertype:- by representation types that are of a provided quantity character.
See Representation Types for the full requirements and available customization points.
Quantity<T>
Quantity concept matches every
quantity in the library and is satisfied by all types
being or deriving from an instantiation of a quantity class template.
QuantityOf<T, V>
QuantityOf concept is satisfied by all the quantities for which a ReferenceOf<V>
is true.
QuantityLike<T>
QuantityLike concept provides interoperability with other libraries and is satisfied by a
type T for which an instantiation of quantity_like_traits type trait yields a valid type
that provides:
referencestatic data member that matches theReferenceconcept,reptype that matchesRepresentationOfconcept with the character provided inreference,explicit_importstatic data member convertible toboolthat specifies that the conversion fromTto aquantitytype should happen explicitly (iftrue),explicit_exportstatic data member convertible toboolthat specifies that the conversion from aquantitytype toTshould happen explicitly (iftrue),to_numerical_value(T)static member function returning a raw value of the quantity,from_numerical_value(rep)static member function returningT.
??? abstract "Examples"
This is how support for `std::chrono::seconds` can be provided:
```cpp
template<>
struct mp_units::quantity_like_traits<std::chrono::seconds> {
static constexpr auto reference = si::second;
static constexpr bool explicit_import = false;
static constexpr bool explicit_export = false;
using rep = std::chrono::seconds::rep;
[[nodiscard]] static constexpr rep to_numerical_value(const std::chrono::seconds& d)
{
return d.count();
}
[[nodiscard]] static constexpr std::chrono::seconds from_numerical_value(const rep& v)
{
return std::chrono::seconds(v);
}
};
quantity q = 42s;
std::chrono::seconds dur = 42 * s;
```
PointOrigin<T>
PointOrigin concept matches all
quantity point origins in the library. It is
satisfied by either:
- All types derived from an
absolute_point_originclass template. - All types derived from a
relative_point_originclass template.
PointOriginFor<T, V>
PointOriginFor concept is satisfied by all
PointOrigin types that have quantity type implicitly convertible from
quantity specification V, which means that V must satisfy
QuantitySpecOf<T::quantity_spec>.
??? abstract "Examples"
`si::ice_point` can serve as a point origin for _points_ of `isq::Celsius_temperature` because this
quantity type implicitly converts to `isq::thermodynamic_temperature`.
However, if we define `mean_sea_level` in the following way:
```cpp
inline constexpr struct mean_sea_level : absolute_point_origin<isq::altitude> {} mean_sea_level;
```
then it can't be used as a point origin for _points_ of `isq::length` or `isq::width` as none of them
is implicitly convertible to `isq::altitude`:
- not every _length_ is an _altitude_,
- _width_ is not compatible with _altitude_.
QuantityPoint<T>
QuantityPoint concept is satisfied by all types being either a specialization or derived
from quantity_point class template.
QuantityPointOf<T, V>
QuantityPointOf concept is satisfied by all the quantity points T that match the
following value V:
V |
Condition |
|---|---|
QuantitySpec |
The quantity point quantity specification satisfies ReferenceOf<V> concept. |
PointOrigin |
The point and V have the same absolute point origin. |
QuantityPointLike<T>
QuantityPointLike concept provides interoperability with other libraries and is satisfied
by a type T for which an instantiation of quantity_point_like_traits type trait yields
a valid type that provides:
referencestatic data member that matches theReferenceconcept.point_originstatic data member that matches thePointOriginconcept.reptype that matchesRepresentationOfconcept with the character provided inreference.explicit_importstatic data member convertible toboolthat specifies that the conversion fromTto aquantity_pointtype should happen explicitly (iftrue),explicit_exportstatic data member convertible toboolthat specifies that the conversion from aquantity_pointtype toTshould happen explicitly (iftrue),to_numerical_value(T)static member function returning a raw value of the quantity being the offset of the point from the origin,from_numerical_value(rep)static member function returningT.
??? abstract "Examples"
This is how support for a `std::chrono::time_point` of `std::chrono::seconds` can be provided:
```cpp
template<typename C>
struct mp_units::quantity_point_like_traits<std::chrono::time_point<C, std::chrono::seconds>> {
static constexpr auto reference = si::second;
static constexpr struct point_origin_ : absolute_point_origin<isq::time> {} point_origin{};
static constexpr bool explicit_import = false;
static constexpr bool explicit_export = false;
using rep = std::chrono::seconds::rep;
using T = std::chrono::time_point<C, std::chrono::seconds>;
[[nodiscard]] static constexpr rep to_numerical_value(const T& tp)
{
return tp.time_since_epoch().count();
}
[[nodiscard]] static constexpr T from_numerical_value(const rep& v)
{
return T(std::chrono::seconds(v));
}
};
quantity_point qp = time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now());
std::chrono::sys_seconds q = qp + 42 * s;
```