README updated

This commit is contained in:
Mateusz Pusz
2019-12-17 09:15:31 +01:00
parent 7617e3c374
commit a384fbd75a

149
README.md
View File

@ -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