mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 02:17:16 +02:00
README updated
This commit is contained in:
149
README.md
149
README.md
@ -5,9 +5,32 @@
|
||||
|
||||
# `mp-units` - A Units Library for C++
|
||||
|
||||
## TL;DR
|
||||
|
||||
```cpp
|
||||
constexpr Velocity auto avg_speed(Length auto d, Time auto t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace si::literals;
|
||||
Velocity auto v1 = avg_speed(220km, 2h);
|
||||
Velocity auto v2 = avg_speed(140mi, 2h);
|
||||
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << quantity_cast<si::metre_per_second>(speed) << '\n'; // 30.5556 m/s
|
||||
std::cout << v2 << '\n'; // 70 mi/h
|
||||
}
|
||||
```
|
||||
|
||||
Try it on [Compiler Explorer](https://godbolt.org/z/OVpkT1).
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
`Units` is a compile-time enabled Modern C++ library that provides compile-time dimensional
|
||||
`mp-units` is a compile-time enabled Modern C++ library that provides compile-time dimensional
|
||||
analysis and unit/quantity manipulation. The basic idea and design heavily bases on
|
||||
`std::chrono::duration` and extends it to work properly with many dimensions.
|
||||
|
||||
@ -31,74 +54,120 @@ static_assert(1000 / 1s == 1kHz);
|
||||
static_assert(10km / 5km == 2);
|
||||
```
|
||||
|
||||
## Usage Overview
|
||||
|
||||
The library framework consists of a few concepts: quantities, units, dimensions and their exponents. From the user's
|
||||
point of view the most important is a `quantity`.
|
||||
## Getting Started
|
||||
|
||||
Quantity is a concrete amount of a unit for a specified dimension with a specific representation:
|
||||
The library framework consists of a few concepts: quantities, units, dimensions and their
|
||||
exponents. From the user's point of view the most important is a `quantity`.
|
||||
|
||||
A quantity is a concrete amount of a unit for a specified dimension with a specific representation:
|
||||
|
||||
```cpp
|
||||
units::quantity<units::kilometre, double> d1(123);
|
||||
auto d2 = 123km; // units::quantity<units::kilometre, std::int64_t>
|
||||
units::quantity<units::si::dim_length, units::si::kilometre, double> d(123);
|
||||
```
|
||||
|
||||
There are C++ concepts provided for each such quantity type:
|
||||
To simplify quantity creation the library provides helper aliases for quantities of different
|
||||
dimensions. Thanks to then the above example can be rewritten as follows:
|
||||
|
||||
```cpp
|
||||
template<typename T>
|
||||
concept Length = QuantityOf<T, length>;
|
||||
units::si::length<units::si::kilometre, double> d(123);
|
||||
```
|
||||
|
||||
With that we can easily write a function template like this:
|
||||
To simplify creations of compile-time known constants the library provides UDLs for each unit.
|
||||
Thanks to them the same code can be as simple as:
|
||||
|
||||
```cpp
|
||||
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t)
|
||||
using namespace units::si::literals;
|
||||
auto d = 123km; // units::length<units::si::kilometre, std::int64_t>
|
||||
```
|
||||
|
||||
For brevity, the next examples will assume:
|
||||
|
||||
```cpp
|
||||
using namespace units;
|
||||
```
|
||||
|
||||
Let's assume that the user wants to write the following code:
|
||||
|
||||
```cpp
|
||||
int main()
|
||||
{
|
||||
using namespace si::literals;
|
||||
auto v1 = avg_speed(220km, 2h);
|
||||
auto v2 = avg_speed(140mi, 2h);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
`avg_speed` is a simple function calculating an average speed from a distance and duration. It can
|
||||
be implemented as:
|
||||
|
||||
```cpp
|
||||
constexpr si::velocity<si::metre_per_second, int> avg_speed(si::length<si::metre> d, si::time<si::second> t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
```
|
||||
|
||||
Concepts usage in the function above guarantee correctness enforced in compile-time and the
|
||||
guarantee that no unneeded intermediate conversions will ever be applied no matter which
|
||||
units the user will decide to pass to such function template:
|
||||
However, this function will perform unnecessary intermediate conversions (from kilometers to meters,
|
||||
from hours to seconds, and from meters per second to kilometers per hour). To eliminate all that
|
||||
overhead we have to write a template function:
|
||||
|
||||
```cpp
|
||||
using namespace units;
|
||||
|
||||
constexpr quantity<kilometre> distance(220);
|
||||
constexpr quantity<hour> time(2);
|
||||
constexpr Velocity speed = avg_speed(distance, time);
|
||||
|
||||
static_assert(std::same_as<std::remove_cvref_t<decltype(speed)>, quantity<kilometre_per_hour>>);
|
||||
static_assert(speed.count() == 110);
|
||||
template<typename U1, typename R1, typename U2, typename R2>
|
||||
constexpr auto avg_speed(si::length<U1, R1> d, si::time<U2, R2> t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
```
|
||||
|
||||
The units library also tries really hard to printing any quantity in the most user friendly fashion:
|
||||
This function will work for every SI unit and representation without any unnecessary overhead.
|
||||
It is also simple enough to ensure that the returned type is actually a velocity. However,
|
||||
it might not always be the case. For more complicated calculations we would like to ensure
|
||||
that we are returning a correct type and also inform the user of that fact in the function
|
||||
template interface. Also we might want to implement a truly generic function that will work
|
||||
efficiently not only with SI units but also with other systems of units like CGS. The solution
|
||||
to this are C++20 concepts and generic functions.
|
||||
|
||||
```cpp
|
||||
std::cout << speed << '\n';
|
||||
std::cout << quantity_cast<metre_per_second>(speed) << '\n';
|
||||
std::cout << avg_speed(140.mi, 2h) << '\n';
|
||||
constexpr Velocity auto avg_speed(Length auto d, Time auto t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
```
|
||||
|
||||
Try it on [Compiler Explorer](https://godbolt.org/z/OVpkT1).
|
||||
The units library also tries really hard to print any quantity in the most user friendly
|
||||
fashion:
|
||||
|
||||
```cpp
|
||||
int main()
|
||||
{
|
||||
using namespace si::literals;
|
||||
Velocity auto v1 = avg_speed(220km, 2h);
|
||||
Velocity auto v2 = avg_speed(140mi, 2h);
|
||||
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << quantity_cast<si::metre_per_second>(speed) << '\n'; // 30.5556 m/s
|
||||
std::cout << v2 << '\n'; // 70 mi/h
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Library design
|
||||
|
||||
`mp-units` library design rationale and documentation can be found in [doc/DESIGN.md](doc/DESIGN.md)
|
||||
A detailed `mp-units` library design rationale and documentation can be found in
|
||||
[doc/DESIGN.md](doc/DESIGN.md)
|
||||
|
||||
|
||||
## Repository structure
|
||||
|
||||
That repository contains the following independent `cmake`-based projects:
|
||||
- `./src` - header-only project for `units`
|
||||
- `.` - project used for development needs that wraps `./src` project together with
|
||||
usage examples and unit tests
|
||||
- `./test_package` - library installation and Conan package verification
|
||||
This repository contains three independent `cmake`-based projects:
|
||||
1. `./src` - header-only project containing whole `mp-units` library
|
||||
2. `.` - project used as an entry point for library development (it wraps `./src` project
|
||||
together with usage examples and tests)
|
||||
3. `./test_package` - library installation and Conan package verification
|
||||
|
||||
Please note that the projects depend on `cmake` git submodule in the `./cmake/common`
|
||||
NOTE: Please note that this repository depends on a git submodule in the `./cmake/common`
|
||||
subdirectory.
|
||||
|
||||
|
||||
@ -112,6 +181,16 @@ NOTE: This library as of now compiles correctly only with gcc-9.1 and newer.
|
||||
|
||||
## Release notes
|
||||
|
||||
- 0.5.0 ???
|
||||
- Major refactoring and rewrite of the library
|
||||
- Units are now independent from dimensions
|
||||
- Dimensions are now depended on units (base or coherent units are provided in a class template)
|
||||
- Quantity gets a Dimension template parameter again (as unit does not provide information about
|
||||
its dimension anymore)
|
||||
- Added official CGS system support
|
||||
- Added official data information system support
|
||||
- Repository file tree cleanup
|
||||
|
||||
- 0.4.0 Nov 17, 2019
|
||||
- Support for derived dimensions in `exp` added
|
||||
- Added `pow()` and `sqrt()` operations on quantities
|
||||
|
Reference in New Issue
Block a user