docs: initial V2 documenatation added

This commit is contained in:
Mateusz Pusz
2023-06-21 10:55:18 +02:00
parent dde5bcab7e
commit 4b3e31f40d
236 changed files with 1495 additions and 7967 deletions
+83
View File
@@ -0,0 +1,83 @@
# Code Example
Here is a small example of operations possible on scalar quantities:
```cpp
#include <mp-units/systems/si/si.h>
using namespace mp_units::si::unit_symbols;
// simple numeric operations
static_assert(10 * km / 2 == 5 * km);
// unit conversions
static_assert(1 * h == 3600 * s);
static_assert(1 * km + 1 * m == 1001 * m);
// dimension conversions
inline constexpr auto kmph = km / h;
static_assert(1 * km / (1 * s) == 1000 * (m / s));
static_assert(2 * kmph * (2 * h) == 4 * km);
static_assert(2 * km / (2 * kmph) == 1 * h);
static_assert(2 * m * (3 * m) == 6 * m2);
static_assert(10 * km / (5 * km) == 2);
static_assert(1000 / (1 * s) == 1 * kHz);
```
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/j8afKnarv)"
This library requires some C++20 features ([concepts and constraints](https://en.cppreference.com/w/cpp/language/constraints),
[classes as NTTP](https://en.cppreference.com/w/cpp/language/template_parameters), ...). Thanks to them,
the user gets a powerful but still easy-to-use interface where all unit conversions and dimensional analysis can be
performed without sacrificing accuracy. Please see the below example for a quick preview of basic library features:
*[NTTP]: Non-Type Template Parameter
```cpp
#include <mp-units/format.h>
#include <mp-units/iostream.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
using namespace mp_units;
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d,
QuantityOf<isq::time> auto t)
{
return d / t;
}
int main()
{
using namespace mp_units::si::unit_symbols;
using namespace mp_units::international::unit_symbols;
constexpr auto v1 = 110 * (km / h);
constexpr auto v2 = 70 * mph;
constexpr auto v3 = avg_speed(220. * isq::distance[km], 2 * h);
constexpr auto v4 = avg_speed(isq::distance(140. * mi), 2 * h);
constexpr auto v5 = v3[m / s];
constexpr auto v6 = value_cast<m / s>(v4);
constexpr auto v7 = value_cast<int>(v6);
std::cout << v1 << '\n'; // 110 km/h
std::cout << v2 << '\n'; // 70 mi/h
std::cout << std::format("{}", v3) << '\n'; // 110 km/h
std::cout << std::format("{:*^14}", v4) << '\n'; // ***70 mi/h****
std::cout << std::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s
std::cout << std::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s
std::cout << std::format("{:%Q}", v7) << '\n'; // 31
}
```
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/T8bovrqTP)"
!!! note
You can find more code examples in the Examples chapter.
+176
View File
@@ -0,0 +1,176 @@
# Frequently Asked Questions
## Why do we spell `metre` instead of `meter`?
This is how ISO 80000 defines it (British English spelling by default).
## Why don't we use UDLs to create quantities?
Many reasons make UDLs a poor choice for a physical units library:
1. UDLs work only with literals (compile-time known values). Our observation is that besides
the unit tests, there are few compile-time known constants used in the production code.
2. Typical implementations of UDLs tend to always use the widest representation type available.
In the case of `std::chrono::duration`, the following is true:
```cpp
using namespace std::chrono_literals;
auto d1 = 42s;
auto d2 = 42.s;
static_assert(std::is_same_v<decltype(d1)::rep, std::int64_t>);
static_assert(std::is_same_v<decltype(d2)::rep, long double>);
```
3. While increasing the coverage for the library, we learned that many unit symbols conflict with
built-in types or numeric extensions. A few of those are: `F` (farad), `J` (joule), `W` (watt),
`K` (kelvin), `d` (day), `l` or `L` (litre), `erg`, `ergps`. For a while for those we used `_` prefix
to make the library work at all, but at some point, we had to unify the naming, and we came up with `_q_`
prefix, which resulted in creating a quantity of a provided unit. So in case the library is
standardized, all quantities would be created with UDLs having `q_` prefix (i.e. `42q_s`)
which is not that nice anymore.
4. UDLs with the same identifiers defined in different namespace can't be disambiguated in the C++
language. If both SI and CGS systems define `_q_s` UDL for a second unit, then it would not be possible
to specify which one to use in case both namespaces are "imported".
5. Another bad property of UDLs is that they do not compose. A coherent unit of angular momentum would
have a UDL specified as `_q_kg_m2_per_s`. Now imagine that you want to make every possible user happy.
How many variations of that unit would you predefine for differently scaled versions of unit ingredients?
6. UDLs are also really expensive to define and specify. For each unit, we need two definitions. One for
integral and another one for floating-point representation. Before the V2 framework, the coherent unit of
angular momentum was defined as:
```cpp
constexpr auto operator"" _q_kg_m2_per_s(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return angular_momentum<kilogram_metre_sq_per_second, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_kg_m2_per_s(long double l)
{
return angular_momentum<kilogram_metre_sq_per_second, long double>(l);
}
```
## Why `60 * km / h` does not compile?
The library design does not allow multiplying or dividing a quantity (the result of `60 * km`)
by another unit. This significantly limits the number of possible errors and surprises in the
quantity equations.
Consider the following expression:
```cpp
auto q = 60 * km / 2 * h;
```
Looks like `30 km/h`, right? But it is not. If the above code was allowed, it would result
in `30 km⋅h`. In case you want to divide `60 * km` by `2 * h` a parenthesis is needed
`60 * km / (2 * h)`.
Another surprising issue could result from the following code:
```cpp
template<typename T>
auto make_length(T v) { return v * si::metre; }
auto v = 42;
auto q = make_length(v);
```
The above might look like a good idea, but consider what would happen in the user provided
an already existing quantity:
```cpp
auto v = 42 * m;
auto q = make_length(v);
```
Fortunately, with the current design, such issues are detected at compile-time.
## Why a dimensionless quantity is not just a fundamental arithmetic type?
In the initial design of this library, the resulting type of division of two quantities was their
common representation type:
```cpp
static_assert(std::is_same_v<decltype(10 * km / (5 * km)), std::int64_t>);
```
First of all, this was consistent with
[`std::chrono::duration`](https://en.cppreference.com/w/cpp/chrono/duration/operator_arith4) behavior.
Additional reasoning behind it was not providing a false impression of a strong `quantity` type for
something that looks and feels like a regular number. Also, all of the mathematic and trigonometric functions
were working fine out of the box with such representation types, so we did not have to rewrite
`sin()`, `cos()`, `exp()`, and others.
However, the feedback we got from the production usage was that such an approach is really bad for generic
programming. It is hard to handle the result of the two quantities' division (or multiplication) as
it might be either a quantity or a fundamental type. If we want to raise such a result to some power, we
must use `units::pow` or `std::pow` depending on the resulting type. Those are only a few issues related
to such an approach.
Moreover, suppose you divide quantities of the same dimension but with units of significantly different
magnitudes. In that case, you may end up with a really small or a huge floating-point value, which may result
in losing lots of precision. Returning a dimensionless quantity from such cases allows us to benefit from
all the properties of scaled units and is consistent with the rest of the library.
!!! info
More information on the current design can be found in the Dimensionless Quantities chapter.
## Why Unicode quantity symbols are used by default instead of ASCII-only characters?
Both C++ and ISO 80000 are standardized by the ISO. ISO 80000 and the SI standards specify Unicode symbols
as the official unit names for some quantities (i.e. `Ω` symbol for the resistance quantity).
As **mp-units** library will be proposed for standardization as a part of the C++ Standard Library
we have to obey the rules and be consistent with ISO specifications.
!!! info
We do understand engineering reality and the constraints of some environments. This is why the library
has the option of ASCII-only Quantity Symbols.
## Why don't you have CMake options to disable the building of tests and examples?
Over time many people provided PRs proposing adding options to build tests and examples conditionally.
Here are a few examples:
- [Add CMake options for disabling docs, examples and tests](https://github.com/mpusz/mp-units/pull/124)
- [build: add options to disable part of the build](https://github.com/mpusz/mp-units/pull/402)
- [CMake Refactoring and Option Cleanup](https://github.com/mpusz/mp-units/pull/456)
We admit this is a common practice in the industry, but we also believe this is a bad pattern.
First, the only need for such options comes when a user wants to use `add_subdirectory()` in CMake
to handle dependencies. Such an approach does not scale and should be discouraged. There is little
use for such a practice in times when we have dedicated package managers like Conan.
The second thing is that our observation is that many people are fixed on disabling "unneeded" subdirectories
from compilation, but they do not see or address the biggest issue, which is polluting user's build
environment with our development-specific settings. Propagating our restrictive compilation flags to user's
project is not the best idea as it might cause a lot of harm if this project stops to compile
because of that.
Last but not least, not having those options is on purpose. Top level _CMakeLists.txt_ file should only
be used by **mp-units** developers and contributors as an entry point for project's development.
We want to ensure that everyone will build **ALL** the code correctly before pushing a commit. Having
such options would allow unintended issues to leak to PRs and CI.
This is why our projects have two entry points:
- _./CMakeLists.txt_ is to be used by projects developers to build **ALL** the project code with really
restrictive compilation flags,
- _./src/CMakeLists.txt_ contains only a pure library definition and should be used by the customers
that prefer to use CMake's `add_subdirectory()` to handle the dependencies.
!!! info
For more details on this please refer to the [CMake + Conan: 3 Years Later - Mateusz Pusz](https://youtu.be/mrSwJBJ-0z8?t=1931)
lecture that Mateusz Pusz provided at the C++Now 2021 conference.
@@ -0,0 +1,449 @@
# Installation And Usage
!!! info
**mp-units** library tries to provide the best user experience possible with the C++ language.
To achieve that, it extensively uses C++20 features and the
[explicit object parameter](https://en.cppreference.com/w/cpp/language/member_functions#Explicit_object_parameter)
from C++23.
Even though the library benefits from C++23 (if available), C++20 is enough to compile and
use all of the library's functionality. C++23 features are hidden behind a preprocessor macro
providing a backward-compatible way to use it.
Sadly, as of today, not many compilers provide full C++20 support. The library compiles fine
on the following compilers (or newer):
- gcc-12.2
In the upcoming weeks, we will be actively working to extend the support to other compilers as well.
## Repository Structure and Dependencies
This repository contains three independent CMake-based projects:
- _./src_
- header-only project containing whole **mp-units** library
- _./src/CMakeList.txt_ file is intended as an **entry point for library users**
- in case this library becomes part of the C++ standard, it will have no external dependencies
but until then, it depends on the following:
- [gsl-lite](https://github.com/gsl-lite/gsl-lite) to verify runtime contracts with
the `gsl_Expects` macro,
- [{fmt}](https://github.com/fmtlib/fmt) to provide text formatting of quantities
(if `std::format` is not supported yet on a specific compiler),
- [only for clang < 14 with libc++] [range-v3](https://github.com/ericniebler/range-v3)
to provide needed C++20 concepts and utilities.
- _._
- project used as an **entry point for library development and CI/CD**
- it wraps _./src_ project together with usage examples and tests
- additionally to the dependencies of _./src_ project, it uses:
- `Catch2 <https://github.com/catchorg/Catch2>`_ library as a unit tests framework,
- `linear algebra <https://github.com/BobSteagall/wg21/tree/master/include>`_
library based on proposal `P1385 <https://wg21.link/P1385>`_ used in some examples
and tests.
- in case you also want to generate the project's documentation, you will need:
- [Material for MkDocs](https://squidfunk.github.io/mkdocs-material)
- *./test_package*
- library installation and Conan package verification.
!!! tip
Top level _CMakeLists.txt_ file should only be used by **mp-units** developers and contributors
as an entry point for the project's development. We want to ensure that everyone will build **ALL**
the code correctly before pushing a commit. Having such options would allow unintended issues to
leak to PRs and CI.
This is why our projects have two entry points:
- _./CMakeLists.txt_ is to be used by projects developers to build **ALL** the project code with really
restrictive compilation flags,
- _./src/CMakeLists.txt_ contains only a pure library definition and should be used by the customers
that prefer to use CMake's `add_subdirectory()` to handle the dependencies.
To learn more about the rationale, please check our [FAQ](../faq/#why-dont-you-have-cmake-options-to-disable-building-of-tests-and-examples).
## Obtaining Dependencies
This library assumes that most of the dependencies will be provided by the
[Conan Package Manager](https://conan.io/). If you want to obtain required
dependencies by other means, some modifications to the library's CMake files might be needed.
The rest of the dependencies responsible for documentation generation are provided by
`python3-pip`.
### Conan Quick Intro
In case you are not familiar with Conan, to install it (or upgrade) just do:
```shell
pip3 install -U conan
```
After that, you might need to add a custom profile file for your development environment
in _~/.conan2/profiles_ directory. An example profile can look as follows:
```ini hl_lines="5" title="~/.conan2/profiles/gcc12"
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=20
compiler.libcxx=libstdc++11
compiler.version=12
os=Linux
[conf]
tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
```
!!! tip
Please note that the **mp-units** library requires C++20 to be set in a Conan profile or forced
via the Conan command line. If you do the former, you will not need to provide `-s compiler.cppstd=20`
every time your run a Conan command line (as provided in the command line instructions below).
Additionally, it is recommended to set Ninja as a CMake generator for Conan. To do so, you should create
a _~/.conan2/global.conf_ file that will set `tools.cmake.cmaketoolchain:generator` to one of Ninja
generators. For example:
```text title="~/.conan2/global.conf"
tools.cmake.cmaketoolchain:generator="Ninja Multi-Config"
```
!!! note
_~/.conan2/global.conf_ file may also set `tools.cmake.cmake_layout:build_folder_vars` which
[makes working with several compilers or build configurations easier](https://docs.conan.io/2/reference/tools/cmake/cmake_layout.html#multi-setting-option-cmake-layout).
For example, the below line will force Conan to generate separate CMake presets and folders for
each compiler:
```text title="~/.conan2/global.conf"
tools.cmake.cmake_layout:build_folder_vars=["settings.compiler", "settings.compiler.version"]
```
In such a case, you will need to use a configuration-specific preset name in the Conan instructions
provided below rather then just `conan-default` and `conan-release`
(i.e. `conan-gcc-11` and `conan-gcc-11-release`)
## Build Options
### Conan Configuration Properties
[`user.build:all`](#user-build-all){ #user-build-all }
: [:octicons-tag-24: 0.8.0][build all support] · :octicons-milestone-24: `True`/`False` (Default: `False`)
Enables compilation of all the source code including tests and examples. To support
this it requires some additional Conan build dependencies described in
[Repository Structure and Dependencies](#repository-structure-and-dependencies).
It also runs unit tests during Conan build (unless `tools.build:skip_test`
configuration property is set to `True`).
[build all support]: https://github.com/mpusz/mp-units/releases/tag/v0.8.0
[`user.build:skip_la`](#user-skip-la){ #user-skip-la }
: [:octicons-tag-24: 0.8.0][skip la support] · :octicons-milestone-24: `True`/`False` (Default: `False`)
If `user.build:all` is enabled, among others, Conan installs the external
[wg21-linear_algebra](https://conan.io/center/wg21-linear_algebra)
dependency and enables the compilation of linear algebra-based tests and usage examples.
Such behavior can be disabled with this option.
[skip la support]: https://github.com/mpusz/mp-units/releases/tag/v0.8.0
### CMake Options
[`MP_UNITS_AS_SYSTEM_HEADERS`](#MP_UNITS_AS_SYSTEM_HEADERS){ #MP_UNITS_AS_SYSTEM_HEADERS }
: [:octicons-tag-24: 2.0.0][as system headers support] · :octicons-milestone-24: `ON`/`OFF` (Default: `OFF`)
Exports library as system headers.
[as system headers support]: https://github.com/mpusz/mp-units/releases/tag/v2.0.0
[`MP_UNITS_BUILD_LA`](#MP_UNITS_BUILD_LA){ #MP_UNITS_BUILD_LA }
: [:octicons-tag-24: 2.0.0][build la support] · :octicons-milestone-24: `ON`/`OFF` (Default: `ON`)
Enables building code depending on the linear algebra library.
[build la support]: https://github.com/mpusz/mp-units/releases/tag/v2.0.0
[`MP_UNITS_IWYU`](#MP_UNITS_IWYU){ #MP_UNITS_IWYU }
: [:octicons-tag-24: 2.0.0][iwyu support] · :octicons-milestone-24: `ON`/`OFF` (Default: `OFF`)
Enables `include-what-you-use` when compiling with a clang compiler.
Additionally turns on [`MP_UNITS_AS_SYSTEM_HEADERS`](#MP_UNITS_AS_SYSTEM_HEADERS).
[iwyu support]: https://github.com/mpusz/mp-units/releases/tag/v2.0.0
[`MP_UNITS_USE_LIBFMT`](#MP_UNITS_USE_LIBFMT){ #MP_UNITS_USE_LIBFMT }
: [:octicons-tag-24: 2.0.0][use libfmt support] · :octicons-milestone-24: `ON`/`OFF` (Default: `ON`)
Enables usage of [{fmt}](https://github.com/fmtlib/fmt) library instead of the C++20 Standard
Library feature.
[use libfmt support]: https://github.com/mpusz/mp-units/releases/tag/v2.0.0
## CMake with Presets Support
It is recommended to use at least CMake 3.23 to build this project as this version introduced support
for CMake Presets schema version 4 used now by Conan to generate presets files. All build instructions
below assume that you have such support. If not, your CMake invocations have to be replaced with something
like:
```shell
mkdir build && cd build
cmake .. -G "Ninja Multi-Config" -DCMAKE_TOOLCHAIN_FILE=<path_to_generators_dir>/conan_toolchain.cmake
cmake --build . --config Release
```
!!! note
In case you can't use CMake 3.23 but you have access to CMake 3.20 or later, you can append
`-c tools.cmake.cmaketoolchain.presets:max_schema_version=2` to the `conan install` command
which will force Conan to use an older version of the CMake Presets schema.
## Installation and Reuse
There are many different ways of installing/reusing **mp-units** in your project. Below we mention
only a few of many options possible.
!!! info
The easiest and most recommended way to obtain **mp-units** is with the Conan package manager.
See [Conan + CMake (release)](#conan-cmake-release) for a detailed instruction.
### Copy
As **mp-units** is a C++ header-only library you can simply copy all needed _src/*/include_ subdirectories
to your source tree.
!!! note
In such a case, you are on your own to ensure all the dependencies are installed, and their header
files can be located during the build. Please also note that some compiler-specific flags are needed
to make the code compile without issues.
### Copy + CMake
If you copy the whole **mp-units** repository to your project's file tree, you can reuse CMake targets
defined by the library. To do so, you should use _CMakeLists.txt_ file from the _./src_ directory:
```cmake
add_subdirectory(<path_to_units_folder>/src)
# ...
target_link_libraries(<your_target> <PUBLIC|PRIVATE|INTERFACE> mp-units::mp-units)
```
!!! note
You are still on your own to make sure all the dependencies are installed and their header and CMake
configuration files can be located during the build.
### Conan + CMake (release)
!!! tip
If you are new to the Conan package manager, it is highly recommended to read
[Obtaining Dependencies](#obtaining-dependencies) and refer to
[Consuming packages](https://docs.conan.io/2/tutorial/consuming_packages.html)
chapter of the official Conan documentation for more information.
**mp-units** releases are hosted on [Conan-Center](https://conan.io/center/mp-units).
To obtain an official library release, the following steps may be performed:
1. Create Conan configuration file (either _conanfile.txt_ or _conanfile.py_) in your
project's top-level directory and add **mp-units** as a dependency of your project.
For example, the simplest file may look as follows:
```ini title="conanfile.txt"
[requires]
mp-units/0.8.0
[layout]
cmake_layout
[generators]
CMakeToolchain
CMakeDeps
```
2. Import **mp-units** and its dependencies definitions to your project's build procedure
with `find_package`:
```cmake
find_package(mp-units CONFIG REQUIRED)
```
3. Link your CMake targets with **mp-units**:
```cmake
target_link_libraries(<your_target> <PUBLIC|PRIVATE|INTERFACE> mp-units::mp-units)
```
4. Download, build, and install Conan dependencies before running the CMake configuration step:
```shell
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
cmake --preset conan-default
cmake --build --preset conan-release
```
### Conan + CMake (Live At Head)
This chapter describes the procedure to Live At Head, which means using the latest version
of **mp-units** all the time.
!!! note
Please note that even though the Conan packages that you will be using are generated **ONLY**
for builds that are considered stable (passed our CI tests) some minor regressions may happen
(our CI and C++20 build environment is not perfect yet). Also, please expect that the library
interface might, and probably will, change occasionally. Even though we do our best, such
changes might not be reflected in the project's documentation right away.
The procedure is similar to the one described in [Conan + CMake (release)](#conan-cmake-release)
with the following differences:
1. Before starting the previous procedure, add **mp-units** remote to your Conan configuration:
```shell
conan remote add conan-mpusz https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
```
2. In your Conan configuration file, provide the package identifier of the `mpusz/testing` stream:
```ini title="conanfile.txt" hl_lines="2"
[requires]
mp-units/2.0.0@mpusz/testing
[layout]
cmake_layout
[generators]
CMakeToolchain
CMakeDeps
```
!!! tip
The identifiers of the latest packages can always be found in
[the project's README file](https://github.com/mpusz/mp-units/blob/master/README.md) or on
[the project's Artifactory](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units).
3. Force Conan to check for updated recipes with `-u`:
```shell
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing -u
```
### Install
In case you don't want to use Conan in your project and just want to install the **mp-units**
library on your file system and use `find_package(mp-units)` from another repository
to find it, it is enough to perform the following steps:
```shell
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
mv CMakeUserPresets.json src
cd src
cmake --preset conan-default -DCMAKE_INSTALL_PREFIX=<your_installation_path>
cmake --build --preset conan-release --target install
```
## Contributing (or just building all the tests and examples)
In case you would like to build all the **mp-units** source code (with unit tests and examples),
you should:
1. Use the _CMakeLists.txt_ from the top-level directory.
2. Run Conan with [`user.build:all`](#user-build-all) = `True`.
```shell
git clone https://github.com/mpusz/mp-units.git && cd units
conan build . -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -b missing
```
The above will download and install all of the dependencies needed for the development of the library,
build all of the source code, and run unit tests.
If you prefer to build the project via CMake rather than Conan, then you should replace
the `conan build` with `conan install` command and then follow with a regular CMake build:
```shell
cmake --preset conan-default
cmake --build --preset conan-release
cmake --build --preset conan-release --target test
```
## Building documentation
Starting from **mp-units 2.0** we are using [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)
to build our documentation. The easiest way to install all the required dependencies
is with `pip`:
```shell
pip install -U mkdocs-material
```
After that, you can either:
- easily [start a live server to preview the documentation as you write](https://squidfunk.github.io/mkdocs-material/creating-your-site/#previewing-as-you-write)
```shell
mkdocs serve
```
- [build the documentation](https://squidfunk.github.io/mkdocs-material/creating-your-site/#building-your-site)
```shell
mkdocs build
```
## Packaging
To test CMake installation and Conan packaging or create a Conan package run:
```shell
conan create . <username>/<channel> -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -b missing
```
The above will create a Conan package and run tests provided in _./test_package_ directory.
## Uploading **mp-units** Package to the Conan Server
```shell
conan upload -r <remote-name> --all mp-units/2.0.0@<user>/<channel>
```
+50
View File
@@ -0,0 +1,50 @@
# Introduction
**mp-units** is a Modern C++ library that provides compile-time dimensional analysis and unit/quantity
manipulation. The initial versions of the library were inspired by the
[`std::chrono::duration`](https://en.cppreference.com/w/cpp/chrono/duration)
but with each release, the interfaces diverged from the original to provide a better user
experience.
## Open Source
**mp-units** is Free and Open Source, with a permissive
[MIT license](https://github.com/mpusz/mp-units/blob/master/LICENSE.md). Check out the source
code and issue tracking (for questions and support, reporting bugs, suggesting feature requests
and improvements) at <https://github.com/mpusz/mp-units>.
## With the User's Experience in Mind
Most of the critical design decisions in the library are dictated by the requirement of
providing the best user experience possible. Other C++ physical units libraries are
"famous" for their enormous and hard-to-understand error messages (one line of the error log often
do not fit on one slide). The ultimate goal of **mp-units** is to improve this and make compile-time
errors and debugging as easy and user-friendly as possible.
To achieve this goal, several techniques are applied:
- usage of C++20 concepts,
- using strong types for framework entities (instead of type aliases),
- usage of expression templates to improve the readability of generated types,
- limiting the number of template arguments to the bare minimum.
!!! note
In many generic C++ libraries compile-time errors do not happen often. It is hard to
break `std::string` or `std::vector` in a way it won't compile with a huge error
log. Physical Units libraries are different. **Generation of compile-time errors
is the main reason to use such a library.**
## Key Features
| Feature | Description |
|------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Safety** | - The affine space strong types (`quantity` and `quantity_point`)<br>- Compile-time checked conversions of quantities and units<br>- Unique support for many quantities of the same kind<br>- Type-safe equations on scalar, vector, and tensor quantities and their units<br>- Value-preserving conversions |
| **Performance** | - All the compile-time logic implemented as immediate (`consteval`) functions<br>- As fast or even faster than working with fundamental types<br>- No space size overhead needed to implement high-level abstractions |
| **Great User Experience** | - Optimized for readable compilation errors and great debugging experience<br>- Efficient and composable way to specify a unit of choice<br>- Value-based dimension, unit, and quantity equations |
| **Feature Rich** | - Systems of Quantities<br>- Systems of Units<br>- Scalar, vector, and tensor quantities<br>- The affine space<br>- [Natural units systems](https://en.wikipedia.org/wiki/Natural_units) support<br>- Strong angular system<br>- Supports any unit's magnitude (huge, small, floating-point)<br>- Faster-than-lightspeed constants<br>- Highly adjustable text-output formatting |
| **Easy to Extend** | - Each entity can be defined with a single line of code<br>- User can easily extend the systems with custom dimensions, quantities, and units |
| **Low Standardization Cost** | - Small number of predefined entities needed thanks to composability<br>- No external dependencies (assuming full C++20 support)<br>- No macros in the user interface (besides portability and standard-compliance issues)<br>- Possibility to be standardized as a [freestanding](https://en.cppreference.com/w/cpp/freestanding) part of the C++ Standard Library |
+76
View File
@@ -0,0 +1,76 @@
# Quick Start
A **quantity** is a concrete amount of a unit for a quantity type of a specified dimension with a
specific representation, and is represented in the library with a `quantity` class template.
## Creating a quantity
The quantity is created by multiplying a number with a predefined unit:
```cpp
#include <mp-units/systems/si/si.h>
using namespace mp_units;
auto q = 42 * si::metre;
```
!!! note
The above spelling of `metre` is not a typo. For motivation, please check our
[FAQ](../faq/#why-do-we-spell-metre-instead-of-meter).
The above creates an instance of `quantity<si::metre(), int>`. The same can be obtained using
an optional unit symbol:
```cpp
#include <mp-units/systems/si/si.h>
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
auto q = 42 * m;
```
!!! note
Unit symbols introduce a lot of short identifiers into the current namespace, and that is
why they are opt-in. A user has to explicitly "import" them from a dedicated `unit_symbols`
namespace.
## User-provided unit wrappers
Sometimes it might be awkward to type some derived units:
```cpp
auto speed = 60 * (km / h);
```
!!! note
Please note that `60 * km / h` will not compile. To read more about the rationale for such
a design please check our [FAQ](../faq/#why-dont-we-use-udls-to-create-a-quantity).
In case such a unit is used a lot in the project, a user can easily provide a nicely named
wrapper for it with:
```cpp
constexpr auto kmph = km / h;
auto speed = 60 * kmph;
```
or even:
```cpp
constexpr auto kilometre = si::kilo<si::metre>;
constexpr auto kilometre_per_hour = kilometre / si::hour;
constexpr auto kmph = kilometre_per_hour;
auto speed = 60 * kmph;
```
!!! note
In case you wonder why this library does not use UDLs to create quantities, please check
our [FAQ](../faq/#why-dont-we-use-udls-to-create-quantities).