diff --git a/README.md b/README.md index da45f8f0..0ccf03fc 100644 --- a/README.md +++ b/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(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 d1(123); -auto d2 = 123km; // units::quantity +units::quantity 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 -concept Length = QuantityOf; +units::si::length 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 +``` + +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 avg_speed(si::length d, si::time 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 distance(220); -constexpr quantity time(2); -constexpr Velocity speed = avg_speed(distance, time); - -static_assert(std::same_as, quantity>); -static_assert(speed.count() == 110); +template +constexpr auto avg_speed(si::length d, si::time 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(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(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