Merge pull request #350 from JohelEGP/modules

feat: add C++ modules support
This commit is contained in:
Mateusz Pusz
2024-01-06 12:36:00 +01:00
committed by GitHub
157 changed files with 1739 additions and 1207 deletions

View File

@ -1,22 +1,12 @@
parse:
additional_commands:
add_documentation:
add_mp_units_module:
pargs:
nargs: 1
flags:
- ALL
nargs: 2
kwargs:
BREATHE_PROJECT: 1
CODE_SOURCE_DIR: 1
INSTALL_DIR: 1
CODE_DEPENDS: 1
DOCS_DEPENDS: 1
add_units_module:
pargs:
nargs: 1
kwargs:
DEPENDENCIES: +
HEADERS: +
DEPENDENCIES: "+"
HEADERS: "*"
MODULE_INTERFACE_UNIT: "?"
enable_iwyu:
pargs:
flags:
@ -26,13 +16,6 @@ parse:
kwargs:
MAPPING_FILE: 1
MAX_LINE_LENGTH: 1
metabench_add_chart:
pargs:
nargs: 1
kwargs:
TITLE: 1
SUBTITLE: 1
DATASETS: +
format:
line_width: 120
tab_size: 4

View File

@ -102,7 +102,7 @@ jobs:
cxx: "clang++-17",
},
lib: "libc++",
conan-config: "",
conan-config: "-o cxx_modules=True",
}
- {
name: "Apple Clang 15",

View File

@ -98,7 +98,7 @@ jobs:
cxx: "clang++-17",
},
lib: "libc++",
conan-config: "",
conan-config: "-o cxx_modules=True",
}
- {
name: "Apple Clang 15",

View File

@ -43,7 +43,7 @@ function(get_target_sources target paths_out)
list(APPEND targets ${target})
foreach(t ${targets})
get_target_property(sources ${t} SOURCES)
get_target_property(sources ${t} HEADER_SET)
if(sources)
get_target_property(source_dir ${t} SOURCE_DIR)
foreach(f ${sources})

View File

@ -54,6 +54,13 @@ class MPUnitsConan(ConanFile):
license = "MIT"
url = "https://github.com/mpusz/mp-units"
settings = "os", "arch", "compiler", "build_type"
options = {
"cxx_modules": [True, False],
}
default_options = {
"cxx_modules": False,
}
exports = ["LICENSE.md"]
exports_sources = [
"docs/*",
@ -104,7 +111,7 @@ class MPUnitsConan(ConanFile):
def requirements(self):
self.requires("gsl-lite/0.40.0")
if self._use_libfmt:
self.requires("fmt/10.1.0")
self.requires("fmt/10.1.1")
def build_requirements(self):
if self._build_all:
@ -133,6 +140,9 @@ class MPUnitsConan(ConanFile):
def generate(self):
tc = CMakeToolchain(self)
if self.options.cxx_modules:
tc.variables["CMAKE_CXX_SCAN_FOR_MODULES"] = True
tc.variables["MP_UNITS_BUILD_CXX_MODULES"] = True
tc.variables["MP_UNITS_BUILD_LA"] = self._build_all and not self._skip_la
tc.variables["MP_UNITS_USE_LIBFMT"] = self._use_libfmt
tc.generate()

View File

@ -1,5 +1,10 @@
# Installation And Usage
This chapter provides all the necessary information to obtain and build the code using **mp-units**.
It also describes how to build or distribute the library and generate its documentation.
## C++ compiler support { #cpp-compiler-support }
!!! info
**mp-units** library tries to provide the best user experience possible with the C++ language.
@ -12,14 +17,42 @@
a [preprocessor macro](../users_guide/framework_basics/systems_of_quantities.md#defining-quantities)
providing a backward-compatible way to use it.
As of today, the library compiles fine on the following compilers (or newer):
The below table provides the minimum compiler version required to compile the code using the
specific feature:
- gcc-12
- clang-16
- apple-clang-15
| Feature | gcc | clang | apple-clang | MSVC |
|----------------------|:----:|:-----:|:-----------:|:----:|
| **Minimum support** | 12 | 16 | 15 | None |
| **`std::format`** | None | None | None | None |
| **C++ modules** | None | 17 | None | None |
| **C++23 extensions** | None | None | None | None |
More requirements for C++ modules support can be found in the
[CMake's documentation](https://cmake.org/cmake/help/latest/manual/cmake-cxxmodules.7.html).
## Repository Structure and Dependencies
## Modules
The **mp-units** library provides the following C++ modules.
```mermaid
flowchart TD
mp_units --- mp_units.systems --- mp_units.core
```
| C++ Module | CMake Target | Contents |
|--------------------|----------------------|-----------------------------------------|
| `mp_units.core` | `mp-units::core` | Core library framework |
| `mp_units.systems` | `mp-units::systems` | All the systems of quantities and units |
| `mp_units` | `mp-units::mp-units` | Core + Systems |
!!! note
C++ modules are provided within the package only when [`cxx_modules`](#cxx_modules) Conan
option is set to `True`.
## Repository structure and dependencies
This repository contains three independent CMake-based projects:
@ -60,16 +93,18 @@ This repository contains three independent CMake-based projects:
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.
- _./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()`](https://cmake.org/cmake/help/latest/command/add_subdirectory.html) to
handle the dependencies.
To learn more about the rationale, please check our
[FAQ](faq.md#why-dont-we-have-cmake-options-to-disable-building-of-tests-and-examples).
## Obtaining Dependencies
## 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
@ -78,7 +113,7 @@ The rest of the dependencies responsible for documentation generation are provid
`python3-pip`.
### Conan Quick Intro
### Conan quick intro
In case you are not familiar with Conan, to install it (or upgrade) just do:
@ -136,9 +171,19 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
(e.g. `conan-gcc-13-23` and `conan-gcc-13-23-release`)
## Build Options
## Build options
### Conan Configuration Properties
### Conan options
[cxx_modules](#cxx_modules){ #cxx_modules }
: [:octicons-tag-24: 2.2.0][cxx modules support] · :octicons-milestone-24: `True`/`False` (Default: `False`)
Configures CMake to add C++ modules to the list of default targets.
[cxx modules support]: https://github.com/mpusz/mp-units/releases/tag/v2.2.0
### Conan configuration properties
[`user.build:all`](#user-build-all){ #user-build-all }
@ -146,7 +191,8 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
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`
It also runs unit tests during Conan build (unless
[`tools.build:skip_test`](https://docs.conan.io/2/reference/commands/config.html?highlight=tools.build:skip_test#conan-config-list)
configuration property is set to `True`).
[build all support]: https://github.com/mpusz/mp-units/releases/tag/v0.8.0
@ -164,7 +210,16 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
[skip la support]: https://github.com/mpusz/mp-units/releases/tag/v0.8.0
### CMake Options
### CMake options
[`MP_UNITS_BUILD_CXX_MODULES`](#MP_UNITS_BUILD_CXX_MODULES){ #MP_UNITS_BUILD_CXX_MODULES }
: [:octicons-tag-24: 2.2.0][build_cxx_modules support] · :octicons-milestone-24: `ON`/`OFF` (Default: `OFF`)
Adds C++ modules to the list of default targets.
[build_cxx_modules support]: https://github.com/mpusz/mp-units/releases/tag/v2.2.0
[`MP_UNITS_AS_SYSTEM_HEADERS`](#MP_UNITS_AS_SYSTEM_HEADERS){ #MP_UNITS_AS_SYSTEM_HEADERS }
@ -199,12 +254,12 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
: [:octicons-tag-24: 2.0.0][use libfmt support] · :octicons-milestone-24: `ON`/`OFF` (Default: `ON`)
Forces usage of [{fmt}](https://github.com/fmtlib/fmt) library instead of the C++20 Standard
Library feature.
Library features.
[use libfmt support]: https://github.com/mpusz/mp-units/releases/tag/v2.0.0
## CMake with Presets Support
## 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
@ -224,7 +279,7 @@ cmake --build . --config Release
which will force Conan to use an older version of the CMake Presets schema.
## Installation and Reuse
## 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.
@ -284,6 +339,9 @@ The following steps may be performed to obtain an official library release:
[requires]
mp-units/2.1.0
[options]
mp-units:cxx_modules=True
[layout]
cmake_layout
@ -341,6 +399,9 @@ with the following differences:
[requires]
mp-units/2.2.0@mpusz/testing
[options]
mp-units:cxx_modules=True
[layout]
cmake_layout
@ -387,7 +448,7 @@ you should:
```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
conan build . -pr <your_conan_profile> -s compiler.cppstd=23 -o cxx_modules=True -c user.build:all=True -b missing
```
The above will download and install all of the dependencies needed for the development of the library,
@ -433,13 +494,13 @@ After that, you can either:
To test CMake installation and Conan packaging or create a Conan package run:
```shell
conan create . --user <username> --channel <channel> -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -b missing
conan create . --user <username> --channel <channel> -pr <your_conan_profile> -s compiler.cppstd=20 -o cxx_modules=True -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
## Uploading **mp-units** package to the Conan server
```shell
conan upload -r <remote-name> --all mp-units/2.1.0@<user>/<channel>

View File

@ -2,30 +2,59 @@
Here is a small example of operations possible on scalar quantities:
```cpp
#include <mp-units/systems/si/si.h>
=== "C++ modules"
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
```cpp
import mp_units;
// simple numeric operations
static_assert(10 * km / 2 == 5 * km);
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
// unit conversions
static_assert(1 * h == 3600 * s);
static_assert(1 * km + 1 * m == 1001 * m);
// simple numeric operations
static_assert(10 * km / 2 == 5 * km);
// derived quantities
static_assert(1 * km / (1 * s) == 1000 * m / s);
static_assert(2 * km / h * (2 * h) == 4 * km);
static_assert(2 * km / (2 * km / h) == 1 * h);
// unit conversions
static_assert(1 * h == 3600 * s);
static_assert(1 * km + 1 * m == 1001 * m);
static_assert(2 * m * (3 * m) == 6 * m2);
// derived quantities
static_assert(1 * km / (1 * s) == 1000 * m / s);
static_assert(2 * km / h * (2 * h) == 4 * km);
static_assert(2 * km / (2 * km / h) == 1 * h);
static_assert(10 * km / (5 * km) == 2 * one);
static_assert(2 * m * (3 * m) == 6 * m2);
static_assert(1000 / (1 * s) == 1 * kHz);
```
static_assert(10 * km / (5 * km) == 2 * one);
static_assert(1000 / (1 * s) == 1 * kHz);
```
=== "Header files"
```cpp
#include <mp-units/systems/si/si.h>
using namespace mp_units;
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);
// derived quantities
static_assert(1 * km / (1 * s) == 1000 * m / s);
static_assert(2 * km / h * (2 * h) == 4 * km);
static_assert(2 * km / (2 * km / h) == 1 * h);
static_assert(2 * m * (3 * m) == 6 * m2);
static_assert(10 * km / (5 * km) == 2 * one);
static_assert(1000 / (1 * s) == 1 * kHz);
```
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/81Ev7qhTd)"
@ -37,44 +66,83 @@ performed without sacrificing accuracy. Please see the below example for a quick
*[NTTP]: Non-Type Template Parameter
```cpp
#include <mp-units/format.h>
#include <mp-units/ostream.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
=== "C++ modules"
using namespace mp_units;
```cpp
#include <iostream>
import mp_units;
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d,
QuantityOf<isq::time> auto t)
{
return d / t;
}
using namespace mp_units;
int main()
{
using namespace mp_units::si::unit_symbols;
using namespace mp_units::international::unit_symbols;
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d,
QuantityOf<isq::time> auto t)
{
return d / t;
}
constexpr quantity v1 = 110 * km / h;
constexpr quantity v2 = 70 * mph;
constexpr quantity v3 = avg_speed(220. * isq::distance[km], 2 * h);
constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * h);
constexpr quantity v5 = v3.in(m / s);
constexpr quantity v6 = value_cast<m / s>(v4);
constexpr quantity v7 = value_cast<int>(v6);
int main()
{
using namespace mp_units::si::unit_symbols;
using namespace mp_units::international::unit_symbols;
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
}
```
constexpr quantity v1 = 110 * km / h;
constexpr quantity v2 = 70 * mph;
constexpr quantity v3 = avg_speed(220. * isq::distance[km], 2 * h);
constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * h);
constexpr quantity v5 = v3.in(m / s);
constexpr quantity v6 = value_cast<m / s>(v4);
constexpr quantity 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
}
```
=== "Header files"
```cpp
#include <mp-units/format.h>
#include <mp-units/ostream.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/isq.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 quantity v1 = 110 * km / h;
constexpr quantity v2 = 70 * mph;
constexpr quantity v3 = avg_speed(220. * isq::distance[km], 2 * h);
constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * h);
constexpr quantity v5 = v3.in(m / s);
constexpr quantity v6 = value_cast<m / s>(v4);
constexpr quantity 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/Tsesa1Pvq)"

View File

@ -20,13 +20,25 @@ The [SI Brochure](../appendix/references.md#SIBrochure) says:
Following the above, the value of a quantity in the **mp-units** library is created by multiplying
a number with a predefined unit:
```cpp
#include <mp-units/systems/si/si.h>
=== "C++ modules"
using namespace mp_units;
```cpp
import mp_units;
quantity q = 42 * si::metre / si::second;
```
using namespace mp_units;
quantity q = 42 * si::metre / si::second;
```
=== "Header files"
```cpp
#include <mp-units/systems/si/si.h>
using namespace mp_units;
quantity q = 42 * si::metre / si::second;
```
!!! info
@ -34,25 +46,50 @@ quantity q = 42 * si::metre / si::second;
provided by this and other libraries, a quantity can also be created with a two-parameter
constructor:
```cpp
#include <mp-units/systems/si/si.h>
=== "C++ modules"
using namespace mp_units;
```cpp
import mp_units;
quantity q{42, si::metre / si::second};
```
using namespace mp_units;
quantity q{42, si::metre / si::second};
```
=== "Header files"
```cpp
#include <mp-units/systems/si/si.h>
using namespace mp_units;
quantity q{42, si::metre / si::second};
```
The above creates an instance of `quantity<derived_unit<si::metre, per<si::second>>{}, int>`.
The same can be obtained using optional unit symbols:
```cpp
#include <mp-units/systems/si/si.h>
=== "C++ modules"
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
```cpp
import mp_units;
quantity q = 42 * m / s;
```
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
quantity q = 42 * m / s;
```
=== "Header files"
```cpp
#include <mp-units/systems/si/si.h>
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
quantity q = 42 * m / s;
```
!!! tip
@ -62,14 +99,27 @@ quantity q = 42 * m / s;
Quantities of the same kind can be added, subtracted, and compared to each other:
```cpp
#include <mp-units/systems/si/si.h>
=== "C++ modules"
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
```cpp
import mp_units;
static_assert(1 * km + 50 * m == 1050 * m);
```
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
static_assert(1 * km + 50 * m == 1050 * m);
```
=== "Header files"
```cpp
#include <mp-units/systems/si/si.h>
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
static_assert(1 * km + 50 * m == 1050 * m);
```
Various quantities can be multiplied or divided by each other:
@ -96,24 +146,45 @@ Quantity points should be used in all places where adding two values is meaningl
The set of operations that can be done on quantity points is limited compared to quantities.
This introduces an additional type-safety.
```cpp
#include <mp-units/ostream.h>
#include <mp-units/systems/si/si.h>
#include <mp-units/systems/usc/usc.h>
#include <iostream>
=== "C++ modules"
int main()
{
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
using namespace mp_units::usc::unit_symbols;
```cpp
#include <iostream>
import mp_units;
quantity_point temp{20. * deg_C};
std::cout << "Temperature: "
<< temp.quantity_from_zero() << " ("
<< temp.in(deg_F).quantity_from_zero() << ")\n";
}
```
int main()
{
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
using namespace mp_units::usc::unit_symbols;
quantity_point temp{20. * deg_C};
std::cout << "Temperature: "
<< temp.quantity_from_zero() << " ("
<< temp.in(deg_F).quantity_from_zero() << ")\n";
}
```
=== "Header files"
```cpp
#include <mp-units/ostream.h>
#include <mp-units/systems/si/si.h>
#include <mp-units/systems/usc/usc.h>
#include <iostream>
int main()
{
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
using namespace mp_units::usc::unit_symbols;
quantity_point temp{20. * deg_C};
std::cout << "Temperature: "
<< temp.quantity_from_zero() << " ("
<< temp.in(deg_F).quantity_from_zero() << ")\n";
}
```
The above outputs:

View File

@ -25,28 +25,54 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
a [preprocessor macro](users_guide/framework_basics/systems_of_quantities.md#defining-quantities)
providing a backward-compatible way to use it.
As of today, the library compiles fine on the following compilers (or newer):
The below table provides the minimum compiler version required to compile the code using the
specific feature:
- gcc-12
- clang-16
- apple-clang-15
| Feature | gcc | clang | apple-clang | MSVC |
|----------------------|:----:|:-----:|:-----------:|:----:|
| **Minimum support** | 12 | 16 | 15 | None |
| **`std::format`** | None | None | None | None |
| **C++ modules** | None | 17 | None | None |
| **C++23 extensions** | None | None | None | None |
```cpp
#include <mp-units/ostream.h>
#include <mp-units/systems/si/si.h>
#include <mp-units/systems/usc/usc.h>
#include <iostream>
More requirements for C++ modules support can be found in the
[CMake's documentation](https://cmake.org/cmake/help/latest/manual/cmake-cxxmodules.7.html).
using namespace mp_units;
=== "C++ modules"
inline constexpr struct smoot : named_unit<"smoot", mag<67> * usc::inch> {} smoot;
```cpp
#include <iostream>
import mp_units;
int main()
{
constexpr quantity dist = 364.4 * smoot;
std::cout << "Harvard Bridge length = " << dist << "(" << dist.in(usc::foot) << ", " << dist.in(si::metre) << ") ± 1 εar\n";
}
```
using namespace mp_units;
inline constexpr struct smoot : named_unit<"smoot", mag<67> * usc::inch> {} smoot;
int main()
{
constexpr quantity dist = 364.4 * smoot;
std::cout << "Harvard Bridge length = " << dist << "(" << dist.in(usc::foot) << ", " << dist.in(si::metre) << ") ± 1 εar\n";
}
```
=== "Header files"
```cpp
#include <mp-units/ostream.h>
#include <mp-units/systems/si/si.h>
#include <mp-units/systems/usc/usc.h>
#include <iostream>
using namespace mp_units;
inline constexpr struct smoot : named_unit<"smoot", mag<67> * usc::inch> {} smoot;
int main()
{
constexpr quantity dist = 364.4 * smoot;
std::cout << "Harvard Bridge length = " << dist << "(" << dist.in(usc::foot) << ", " << dist.in(si::metre) << ") ± 1 εar\n";
}
```
Output:

View File

@ -14,32 +14,32 @@ library features as possible, but we will scope on different interfaces one can
with the **mp-units**. We will also describe some advantages and disadvantages of presented
solutions.
First, we include all the necessary header files and import all the identifiers from the
`mp_units` namespace:
First, we either import a module or include all the necessary header files and import all
the identifiers from the `mp_units` namespace:
```cpp title="avg_speed.cpp" linenums="1"
--8<-- "example/avg_speed.cpp:28:38"
--8<-- "example/avg_speed.cpp:28:42"
```
Next, we define two functions calculating average speed based on quantities of fixed units
and integral and floating-point representation types, respectively, and a third function
that we introduced in the [previous example](hello_units.md):
```cpp title="avg_speed.cpp" linenums="12"
--8<-- "example/avg_speed.cpp:40:54"
```cpp title="avg_speed.cpp" linenums="16"
--8<-- "example/avg_speed.cpp:44:58"
```
We also added a simple utility to print our results:
```cpp title="avg_speed.cpp" linenums="27"
--8<-- "example/avg_speed.cpp:56:62"
```cpp title="avg_speed.cpp" linenums="31"
--8<-- "example/avg_speed.cpp:60:66"
```
Now, let's analyze how those three utility functions behave with different sets of arguments.
First, we are going to use quantities of SI units and integral representation:
```cpp title="avg_speed.cpp" linenums="27"
--8<-- "example/avg_speed.cpp:64:78"
```cpp title="avg_speed.cpp" linenums="38"
--8<-- "example/avg_speed.cpp:68:82"
```
The above provides the following output:
@ -52,17 +52,17 @@ Average speed of a car that makes 220 km in 2 h is 110 km/h.
```
Please note that in the first two cases, we must convert length from `km` to `m` and
time from `h` to `s`. The converted values are used to calculate speed in `m / s` which
is then again converted to the one in `km / h`. Those conversions not only impact the
application's runtime performance but may also affect the final result. Such truncation
can be easily observed in the first case where we deal with integral representation types
(the resulting speed is `108 km / h`).
time from `h` to `s`. The converted values are used to calculate speed in `m/s` which
is then again converted to the one in `km/h`. Those conversions not only impact the
application's runtime performance but may also affect the precision of the final result.
Such truncation can be easily observed in the first case where we deal with integral
representation types (the resulting speed is `108 km/h`).
The second scenario is really similar to the previous one, but this time, function arguments
have floating-point representation types:
```cpp title="avg_speed.cpp" linenums="42"
--8<-- "example/avg_speed.cpp:80:91"
```cpp title="avg_speed.cpp" linenums="53"
--8<-- "example/avg_speed.cpp:84:95"
```
Conversion from floating-point to integral representation types is
@ -80,25 +80,25 @@ Average speed of a car that makes 220 km in 2 h is 110 km/h.
```
Next, let's do the same for integral and floating-point representations, but this time
using US Customary units:
using international mile:
```cpp title="avg_speed.cpp" linenums="54"
--8<-- "example/avg_speed.cpp:93:124"
```cpp title="avg_speed.cpp" linenums="65"
--8<-- "example/avg_speed.cpp:97:129"
```
One important difference here is the fact that as it is not possible to make a lossless conversion
of miles to meters on a quantity using an integral representation type, so this time, we need a
`value_cast<si::metre>` to force it.
`value_cast<m, int>` to force it.
If we check the text output of the above, we will see the following:
```text
US Customary Units with 'int' as representation
International mile with 'int' as representation
Average speed of a car that makes 140 mi in 2 h is 111 km/h.
Average speed of a car that makes 140 mi in 2 h is 112.654 km/h.
Average speed of a car that makes 140 mi in 2 h is 112 km/h.
US Customary Units with 'double' as representation
International mile with 'double' as representation
Average speed of a car that makes 140 mi in 2 h is 111 km/h.
Average speed of a car that makes 140 mi in 2 h is 112.654 km/h.
Average speed of a car that makes 140 mi in 2 h is 112.654 km/h.
@ -108,8 +108,8 @@ Please note how the first and third results get truncated using integral represe
In the end, we repeat the scenario for CGS units:
```cpp title="avg_speed.cpp" linenums="86"
--8<-- "example/avg_speed.cpp:126:155"
```cpp title="avg_speed.cpp" linenums="97"
--8<-- "example/avg_speed.cpp:131:161"
```
Again, we observe `value_cast` being used in the same places and consistent truncation errors
@ -129,6 +129,6 @@ Average speed of a car that makes 2.2e+07 cm in 7200 s is 110 km/h.
The example file ends with a simple `main()` function:
```cpp title="avg_speed.cpp" linenums="116"
--8<-- "example/avg_speed.cpp:157:"
```cpp title="avg_speed.cpp" linenums="128"
--8<-- "example/avg_speed.cpp:163:"
```

View File

@ -10,79 +10,79 @@ tags:
This is a really simple example showcasing the features of the **mp-units** library.
First, we include the headers for:
First, we either import the `mp_units` module or include the headers for:
- a system of quantities (ISQ)
- symbols of SI units
- symbols of international units
- text and stream output support
- an International System of Quantities (ISQ)
- an International System of units (SI)
- units derived from the International Yard and Pound
- text formatting and stream output support
```cpp title="hello_units.cpp" linenums="1"
--8<-- "example/hello_units.cpp:28:33"
--8<-- "example/hello_units.cpp:28:39"
```
Also, to shorten the definitions, we "import" `mp_units` namespace.
Also, to shorten the definitions, we "import" all the symbols from the `mp_units` namespace.
```cpp title="hello_units.cpp" linenums="7"
--8<-- "example/hello_units.cpp:35:36"
```cpp title="hello_units.cpp" linenums="12"
--8<-- "example/hello_units.cpp:40:41"
```
Next we define a simple function that calculates average speed based on the provided
Next, we define a simple function that calculates the average speed based on the provided
arguments of length and time:
```cpp title="hello_units.cpp" linenums="8"
--8<-- "example/hello_units.cpp:37:40"
```cpp title="hello_units.cpp" linenums="13"
--8<-- "example/hello_units.cpp:42:45"
```
The above function template takes any quantities implicitly convertible to `isq::length`
and `isq::time` respectively. Those quantities can use any compatible unit and a
representation type. The function returns a result of a really simple equation and ensures
and `isq::time`, respectively. Those quantities can use any compatible unit and a
representation type. The function returns a result of a straightforward equation and ensures
that its quantity type is implicitly convertible to `isq::speed`.
!!! tip
Besides verifying the type returned from the function, constraining a generic return
type is really useful for users of such a function as it provides more information
type is beneficial for users of such a function as it provides more information
of what to expect from a function than just using `auto`.
```cpp title="hello_units.cpp" linenums="12"
--8<-- "example/hello_units.cpp:42:45"
```cpp title="hello_units.cpp" linenums="17"
--8<-- "example/hello_units.cpp:47:50"
```
The above lines explicitly opt-in to use unit symbols from two systems of units.
The above lines explicitly opt into using unit symbols from two systems of units.
As this introduces a lot of short identifiers into the current scope, it is not done
implicitly while including a header file.
```cpp title="hello_units.cpp" linenums="16"
--8<-- "example/hello_units.cpp:47:53"
```cpp title="hello_units.cpp" linenums="21"
--8<-- "example/hello_units.cpp:52:58"
```
- Lines `16` & `17` create a quantity of kind `isq::length / isq::time` with the numbers
- Lines `21` & `22` create a quantity of kind `isq::length / isq::time` with the numbers
and units provided. Such quantities can be converted or assigned to any other quantity
with a matching kind.
- Line `18` calls our function template with quantities of kind `isq::length` and
- Line `23` calls our function template with quantities of kind `isq::length` and
`isq::time` and number and units provided.
- Line `19` explicitly provides quantity types of the quantities passed to a function template.
This time those will not be quantity kinds anymore and will have
- Line `24` explicitly provides quantity types of the quantities passed to a function template.
This time, those will not be quantity kinds anymore and will have
[more restrictive conversion rules](../framework_basics/simple_and_typed_quantities.md#quantity_cast-to-force-unsafe-conversions).
- Line `20` changes the unit of a quantity `v3` to `m / s` in a
- Line `25` changes the unit of a quantity `v3` to `m / s` in a
[value-preserving way](../framework_basics/value_conversions.md#value-preserving-conversions)
(floating-point representations are considered to be value-preserving).
- Line `21` does a similar operation but this time it would succeed also for
- Line `26` does a similar operation, but this time, it would also succeed for
[value-truncating cases](../framework_basics/value_conversions.md#value-truncating-conversions)
(if it was the case).
- Line `22` does a [value-truncating conversion](../framework_basics/value_conversions.md#value-truncating-conversions)
(if that was the case).
- Line `27` does a [value-truncating conversion](../framework_basics/value_conversions.md#value-truncating-conversions)
of changing the underlying representation type from `double` to `int`.
```cpp title="hello_units.cpp" linenums="23"
--8<-- "example/hello_units.cpp:55"
```cpp title="hello_units.cpp" linenums="28"
--8<-- "example/hello_units.cpp:60"
```
The above presents [various ways to print a quantity](../framework_basics/text_output.md).
Both stream insertion operations and `std::format` are supported.
Both stream insertion operations and `std::format` facilities are supported.
!!! tip
`MP_UNITS_STD_FMT` is used for compatibility reasons. In case a specific compiler
does not support `std::format` or a user prefers to use `{fmt}` library, this macro
will resolve to `fmt` namespace. Otherwise, `std` namespace will be used.
`MP_UNITS_STD_FMT` is used for compatibility reasons. If a specific compiler
does not support `std::format` or a user prefers to use the `{fmt}` library, this macro
will resolve to `fmt` namespace. Otherwise, the `std` namespace will be used.

View File

@ -13,7 +13,7 @@ how [Faster-than-lightspeed Constants](../framework_basics/faster_than_lightspee
work in practice.
```cpp title="si_constants.cpp" linenums="1"
--8<-- "example/si_constants.cpp:28:34"
--8<-- "example/si_constants.cpp:28:39"
```
As always, we start with the inclusion of all the needed header files. After that, for
@ -21,8 +21,8 @@ the simplicity of this example, we
[hack the character of quantities](../framework_basics/character_of_a_quantity.md#hacking-the-character)
to be able to express vector quantities with simple scalar types.
```cpp title="si_constants.cpp" linenums="1"
--8<-- "example/si_constants.cpp:36:"
```cpp title="si_constants.cpp" linenums="13"
--8<-- "example/si_constants.cpp:41:"
```
The main part of the example prints all of the SI-defining constants. While analyzing the output of

View File

@ -1,5 +1,11 @@
# Tags Index
!!! note
**mp-units** usage example applications are meant to be built on all of
[the supported compilers](../../getting_started/installation_and_usage.md#cpp-compiler-support).
This is why they benefit from the [Wide Compatibility](../use_cases/wide_compatibility.md) mode.
!!! tip
All usage examples in this chapter are categorized with appropriate tags to simplify navigation and

View File

@ -53,32 +53,62 @@ have shorter type identifiers, resulting in easier-to-understand error messages
Here is a simple example showing how to deal with such quantities:
```cpp
#include <mp-units/ostream.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
=== "C++ modules"
using namespace mp_units;
```cpp
#include <iostream>
import mp_units;
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
quantity<si::second> t)
{
return d / t;
}
using namespace mp_units;
int main()
{
using namespace mp_units::si::unit_symbols;
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
quantity<si::second> t)
{
return d / t;
}
const quantity distance = 110 * km;
const quantity duration = 2 * h;
const quantity speed = avg_speed(distance, duration);
int main()
{
using namespace mp_units::si::unit_symbols;
std::cout << "A car driving " << distance << " in " << duration
<< " has an average speed of " << speed
<< " (" << speed.in(km / h) << ")\n";
}
```
const quantity distance = 110 * km;
const quantity duration = 2 * h;
const quantity speed = avg_speed(distance, duration);
std::cout << "A car driving " << distance << " in " << duration
<< " has an average speed of " << speed
<< " (" << speed.in(km / h) << ")\n";
}
```
=== "Header files"
```cpp
#include <mp-units/ostream.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
using namespace mp_units;
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
quantity<si::second> t)
{
return d / t;
}
int main()
{
using namespace mp_units::si::unit_symbols;
const quantity distance = 110 * km;
const quantity duration = 2 * h;
const quantity speed = avg_speed(distance, duration);
std::cout << "A car driving " << distance << " in " << duration
<< " has an average speed of " << speed
<< " (" << speed.in(km / h) << ")\n";
}
```
The code above prints:
@ -144,38 +174,67 @@ accident.
The previous example can be re-typed using typed quantities in the following way:
```cpp
#include <mp-units/ostream.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
=== "C++ modules"
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
```cpp
#include <iostream>
import mp_units;
constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> d,
quantity<isq::time[s]> t)
{
return d / t;
}
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
int main()
{
const quantity distance = isq::distance(110 * km);
const quantity duration = isq::time(2 * h);
const quantity speed = avg_speed(distance, duration);
constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> d,
quantity<isq::time[s]> t)
{
return d / t;
}
std::cout << "A car driving " << distance << " in " << duration
<< " has an average speed of " << speed
<< " (" << speed.in(km / h) << ")\n";
}
```
int main()
{
const quantity distance = isq::distance(110 * km);
const quantity duration = isq::time(2 * h);
const quantity speed = avg_speed(distance, duration);
std::cout << "A car driving " << distance << " in " << duration
<< " has an average speed of " << speed
<< " (" << speed.in(km / h) << ")\n";
}
```
=== "Header files"
```cpp
#include <mp-units/ostream.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> d,
quantity<isq::time[s]> t)
{
return d / t;
}
int main()
{
const quantity distance = isq::distance(110 * km);
const quantity duration = isq::time(2 * h);
const quantity speed = avg_speed(distance, duration);
std::cout << "A car driving " << distance << " in " << duration
<< " has an average speed of " << speed
<< " (" << speed.in(km / h) << ")\n";
}
```
```text
A car driving 110 km in 2 h has an average speed of 15.2778 m/s (55 km/h)
```
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/q3PzMzqsh)"
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/MWxG1j4Pc)"
In case we will accidentally make the same calculation error as before, this time, we will
get a bit longer error message, this time also containing information about the quantity type:
@ -200,116 +259,228 @@ but there are scenarios where they offer additional level of safety.
Let's see another example:
=== "Simple"
=== "C++ modules"
```cpp hl_lines="42"
#include <mp-units/math.h>
#include <mp-units/systems/si/si.h>
#include <numbers>
=== "Simple"
using namespace mp_units;
```cpp hl_lines="41"
#include <numbers>
import mp_units;
class StorageTank {
quantity<square(si::metre)> base_;
quantity<si::metre> height_;
public:
constexpr StorageTank(const quantity<square(si::metre)>& base,
const quantity<si::metre>& height) :
base_(base), height_(height)
{
}
using namespace mp_units;
// ...
};
class StorageTank {
quantity<square(si::metre)> base_;
quantity<si::metre> height_;
public:
constexpr StorageTank(const quantity<square(si::metre)>& base,
const quantity<si::metre>& height) :
base_(base), height_(height)
{
}
class CylindricalStorageTank : public StorageTank {
public:
constexpr CylindricalStorageTank(const quantity<si::metre>& radius,
const quantity<si::metre>& height) :
StorageTank(std::numbers::pi * pow<2>(radius), height)
{
}
};
// ...
};
class RectangularStorageTank : public StorageTank {
public:
constexpr RectangularStorageTank(const quantity<si::metre>& length,
const quantity<si::metre>& width,
const quantity<si::metre>& height) :
StorageTank(length * width, height)
{
}
};
class CylindricalStorageTank : public StorageTank {
public:
constexpr CylindricalStorageTank(const quantity<si::metre>& radius,
const quantity<si::metre>& height) :
StorageTank(std::numbers::pi * pow<2>(radius), height)
{
}
};
int main()
{
using namespace mp_units::si::unit_symbols;
auto tank = RectangularStorageTank(1'000 * mm, 500 * mm, 200 * mm);
// ...
}
```
class RectangularStorageTank : public StorageTank {
public:
constexpr RectangularStorageTank(const quantity<si::metre>& length,
const quantity<si::metre>& width,
const quantity<si::metre>& height) :
StorageTank(length * width, height)
{
}
};
=== "Typed"
int main()
{
using namespace mp_units::si::unit_symbols;
auto tank = RectangularStorageTank(1'000 * mm, 500 * mm, 200 * mm);
// ...
}
```
```cpp hl_lines="53 54 55"
#include <mp-units/math.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/si.h>
#include <numbers>
=== "Typed"
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
```cpp hl_lines="51 52 53"
#include <numbers>
import mp_units;
// add a custom quantity type of kind isq::length
inline constexpr struct horizontal_length
: quantity_spec<isq::length> {} horizontal_length;
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
// add a custom derived quantity type of kind isq::area
// with a constrained quantity equation
inline constexpr struct horizontal_area
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
// add a custom quantity type of kind isq::length
inline constexpr struct horizontal_length
: quantity_spec<isq::length> {} horizontal_length;
class StorageTank {
quantity<horizontal_area[m2]> base_;
quantity<isq::height[m]> height_;
public:
constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
const quantity<isq::height[m]>& height) :
base_(base), height_(height)
{
}
// add a custom derived quantity type of kind isq::area
// with a constrained quantity equation
inline constexpr struct horizontal_area
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
// ...
};
class StorageTank {
quantity<horizontal_area[m2]> base_;
quantity<isq::height[m]> height_;
public:
constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
const quantity<isq::height[m]>& height) :
base_(base), height_(height)
{
}
class CylindricalStorageTank : public StorageTank {
public:
constexpr CylindricalStorageTank(const quantity<isq::radius[m]>& radius,
const quantity<isq::height[m]>& height) :
StorageTank(quantity_cast<horizontal_area>(std::numbers::pi * pow<2>(radius)),
height)
{
}
};
// ...
};
class RectangularStorageTank : public StorageTank {
public:
constexpr RectangularStorageTank(const quantity<horizontal_length[m]>& length,
const quantity<isq::width[m]>& width,
const quantity<isq::height[m]>& height) :
StorageTank(length * width, height)
{
}
};
class CylindricalStorageTank : public StorageTank {
public:
constexpr CylindricalStorageTank(const quantity<isq::radius[m]>& radius,
const quantity<isq::height[m]>& height) :
StorageTank(quantity_cast<horizontal_area>(std::numbers::pi * pow<2>(radius)),
height)
{
}
};
int main()
{
auto tank = RectangularStorageTank(horizontal_length(1'000 * mm),
isq::width(500 * mm),
isq::height(200 * mm));
// ...
}
```
class RectangularStorageTank : public StorageTank {
public:
constexpr RectangularStorageTank(const quantity<horizontal_length[m]>& length,
const quantity<isq::width[m]>& width,
const quantity<isq::height[m]>& height) :
StorageTank(length * width, height)
{
}
};
int main()
{
auto tank = RectangularStorageTank(horizontal_length(1'000 * mm),
isq::width(500 * mm),
isq::height(200 * mm));
// ...
}
```
=== "Header files"
=== "Simple"
```cpp hl_lines="42"
#include <mp-units/math.h>
#include <mp-units/systems/si/si.h>
#include <numbers>
using namespace mp_units;
class StorageTank {
quantity<square(si::metre)> base_;
quantity<si::metre> height_;
public:
constexpr StorageTank(const quantity<square(si::metre)>& base,
const quantity<si::metre>& height) :
base_(base), height_(height)
{
}
// ...
};
class CylindricalStorageTank : public StorageTank {
public:
constexpr CylindricalStorageTank(const quantity<si::metre>& radius,
const quantity<si::metre>& height) :
StorageTank(std::numbers::pi * pow<2>(radius), height)
{
}
};
class RectangularStorageTank : public StorageTank {
public:
constexpr RectangularStorageTank(const quantity<si::metre>& length,
const quantity<si::metre>& width,
const quantity<si::metre>& height) :
StorageTank(length * width, height)
{
}
};
int main()
{
using namespace mp_units::si::unit_symbols;
auto tank = RectangularStorageTank(1'000 * mm, 500 * mm, 200 * mm);
// ...
}
```
=== "Typed"
```cpp hl_lines="53 54 55"
#include <mp-units/math.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#include <numbers>
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
// add a custom quantity type of kind isq::length
inline constexpr struct horizontal_length
: quantity_spec<isq::length> {} horizontal_length;
// add a custom derived quantity type of kind isq::area
// with a constrained quantity equation
inline constexpr struct horizontal_area
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
class StorageTank {
quantity<horizontal_area[m2]> base_;
quantity<isq::height[m]> height_;
public:
constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
const quantity<isq::height[m]>& height) :
base_(base), height_(height)
{
}
// ...
};
class CylindricalStorageTank : public StorageTank {
public:
constexpr CylindricalStorageTank(const quantity<isq::radius[m]>& radius,
const quantity<isq::height[m]>& height) :
StorageTank(quantity_cast<horizontal_area>(std::numbers::pi * pow<2>(radius)),
height)
{
}
};
class RectangularStorageTank : public StorageTank {
public:
constexpr RectangularStorageTank(const quantity<horizontal_length[m]>& length,
const quantity<isq::width[m]>& width,
const quantity<isq::height[m]>& height) :
StorageTank(length * width, height)
{
}
};
int main()
{
auto tank = RectangularStorageTank(horizontal_length(1'000 * mm),
isq::width(500 * mm),
isq::height(200 * mm));
// ...
}
```
In the above example, the highlighted call doesn't look that safe anymore in the case
of simple quantities, right? Suppose someone, either by mistake or due to some refactoring,

View File

@ -0,0 +1,159 @@
# Wide Compatibility
The **mp-units** allows us to implement nice and terse code targeting a specific C++ version and
configuration. Such code is easy to write and understand but might not be portable to some older
environments.
However, sometimes, we want to develop code that can be compiled on a wide range of various
compilers and configurations. This is why the library also exposes and uses special preprocessor
macros that can be used to ensure the wide compatibility of our code.
!!! note
Those macros are used in our short [example applications](../examples/tags_index.md) as those are meant
to be built on all of [the supported compilers](../../getting_started/installation_and_usage.md#cpp-compiler-support).
Some still do not support `std::format`, C++ modules, or C++ versions newer than C++20.
## Various compatibility options
Depending on your compiler's conformance, you can choose to use any of the below styles to write
your code using **mp-units**:
=== "C++23"
```cpp
#include <format>
#include <iostream>
import mp_units;
// ...
inline constexpr struct horizontal_length : quantity_spec<isq::length> {} horizontal_length;
// ...
std::cout << std::format(...) << "\n";
```
=== "C++20"
```cpp
#include <format>
#include <iostream>
import mp_units;
// ...
inline constexpr struct horizontal_length : quantity_spec<horizontal_length, isq::length> {} horizontal_length;
// ...
std::cout << std::format(...) << "\n";
```
=== "C++20 with header files"
```cpp
#include <mp-units/format.h>
#include <mp-units/ostream.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#include <format>
#include <iostream>
// ...
inline constexpr struct horizontal_length : quantity_spec<horizontal_length, isq::length> {} horizontal_length;
// ...
std::cout << std::format(...) << "\n";
```
=== "C++20 with header files + libfmt"
```cpp
#include <mp-units/format.h>
#include <mp-units/ostream.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#include <fmt/format.h>
#include <iostream>
// ...
inline constexpr struct horizontal_length : quantity_spec<horizontal_length, isq::length> {} horizontal_length;
// ...
std::cout << fmt::format(...) << "\n";
```
=== "Wide Compatibility"
```cpp
#include <iostream>
#ifdef MP_UNITS_MODULES
#include <mp-units/compat_macros.h>
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/ostream.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#endif
// ...
QUANTITY_SPEC(horizontal_length, isq::length);
// ...
std::cout << MP_UNITS_STD_FMT::format(...) << "\n";
```
!!! tip
Depending on your preferences, you can either write:
- terse code directly targeting your specific compiler's abilities,
- verbose code using preprocessor branches and macros that provide the widest compatibility
across various compilers.
## Compatibility macros
This chapter describes only the most essential tools the **mp-units** users need.
All the compatibility macros can be found in the _mp-units/compat_macros.h_ header file.
!!! tip
The _mp-units/compat_macros.h_ header file is implicitly included when we use "legacy" headers
in our translation units. However, it has to be explicitly included when we use C++20 modules,
as those do not propagate preprocessor macros.
### `QUANTITY_SPEC(name, ...)` { #QUANTITY_SPEC }
Quantity specification definitions benefit from an
[explicit object parameter](https://en.cppreference.com/w/cpp/language/member_functions#Explicit_object_parameter)
added in C++23 to remove the need for CRTP idiom, which significantly simplifies the code.
This macro benefits from the new C++23 feature if available. Otherwise, it uses the CRTP idiom under
the hood.
*[CRTP]: Curiously Recurring Template Pattern
### `MP_UNITS_STD_FMT`
Some of the supported compilers do not support [std::format](https://en.cppreference.com/w/cpp/utility/format/format)
and related tools. Also, despite using a conformant compiler, some projects still choose to
use [fmtlib](https://github.com/fmtlib/fmt) as their primary formatting facility (e.g., to benefit
from additional features provided with the library).
This macro resolves to either the `std` or `fmt` namespace, depending on the value of
[MP_UNITS_USE_LIBFMT](../../getting_started/installation_and_usage.md#MP_UNITS_USE_LIBFMT)
CMake option.

View File

@ -22,52 +22,52 @@
cmake_minimum_required(VERSION 3.5)
add_library(example_utils INTERFACE)
target_include_directories(example_utils INTERFACE include)
# find dependencies
if(NOT TARGET gsl::gsl-lite)
find_package(gsl-lite CONFIG REQUIRED)
endif()
if(${projectPrefix}BUILD_CXX_MODULES)
add_library(example_utils INTERFACE)
target_compile_definitions(example_utils INTERFACE ${projectPrefix}MODULES)
target_include_directories(example_utils INTERFACE include)
target_link_libraries(example_utils INTERFACE gsl::gsl-lite)
endif()
add_library(example_utils-headers INTERFACE)
target_include_directories(example_utils-headers INTERFACE include)
target_link_libraries(example_utils-headers INTERFACE gsl::gsl-lite)
#
# add_example(target <depependencies>...)
#
function(add_example target)
add_executable(${target} ${target}.cpp)
target_link_libraries(${target} PRIVATE ${ARGN})
if(${projectPrefix}BUILD_CXX_MODULES)
add_executable(${target} ${target}.cpp)
target_compile_definitions(${target} PUBLIC ${projectPrefix}MODULES)
target_link_libraries(${target} PRIVATE mp-units::mp-units ${ARGN})
endif()
add_executable(${target}-headers ${target}.cpp)
list(TRANSFORM ARGN APPEND "-headers")
target_link_libraries(${target}-headers PRIVATE mp-units::mp-units ${ARGN})
endfunction()
add_example(avg_speed mp-units::core-io mp-units::si mp-units::cgs mp-units::usc)
add_example(capacitor_time_curve mp-units::core-io mp-units::si mp-units::utility)
add_example(
clcpp_response
mp-units::core-fmt
mp-units::core-io
mp-units::si
mp-units::iau
mp-units::imperial
mp-units::international
mp-units::typographic
mp-units::usc
)
add_example(conversion_factor mp-units::core-fmt mp-units::core-io mp-units::si)
add_example(currency mp-units::core-io)
add_example(foot_pound_second mp-units::core-fmt mp-units::international mp-units::imperial)
add_example(glide_computer mp-units::core-fmt mp-units::international mp-units::utility glide_computer_lib)
add_example(hello_units mp-units::core-fmt mp-units::core-io mp-units::si mp-units::usc)
add_example(measurement mp-units::core-io mp-units::si)
add_example(si_constants mp-units::core-fmt mp-units::si)
add_example(spectroscopy_units mp-units::core-fmt mp-units::si)
add_example(storage_tank mp-units::core-fmt mp-units::si mp-units::utility)
add_example(
strong_angular_quantities mp-units::core-fmt mp-units::core-io mp-units::si mp-units::isq_angle mp-units::utility
)
add_example(total_energy mp-units::core-io mp-units::si mp-units::natural mp-units::utility)
add_example(
unmanned_aerial_vehicle
mp-units::core-fmt
mp-units::core-io
mp-units::si
mp-units::international
mp-units::utility
example_utils
)
add_example(avg_speed)
add_example(capacitor_time_curve)
add_example(clcpp_response)
add_example(conversion_factor)
add_example(currency)
add_example(foot_pound_second)
add_example(glide_computer glide_computer_lib)
add_example(hello_units)
add_example(measurement)
add_example(si_constants)
add_example(spectroscopy_units)
add_example(storage_tank)
add_example(strong_angular_quantities)
add_example(total_energy)
add_example(unmanned_aerial_vehicle example_utils)
add_subdirectory(glide_computer_lib)
add_subdirectory(kalman_filter)

View File

@ -25,13 +25,17 @@
// !!! renders correctly in the documentation "Examples" section. !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include <exception>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/ostream.h>
#include <mp-units/systems/cgs/cgs.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#include <exception>
#include <iostream>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/unit_symbols.h>
#endif
namespace {
@ -90,14 +94,14 @@ void example()
print_result(distance, duration, avg_speed(distance, duration));
}
// Customary Units (int)
// International mile (int)
{
using namespace mp_units::international::unit_symbols;
constexpr auto distance = 140 * mi;
constexpr auto duration = 2 * h;
std::cout << "\nUS Customary Units with 'int' as representation\n";
std::cout << "\nInternational mile with 'int' as representation\n";
// it is not possible to make a lossless conversion of miles to meters on an integral type
// (explicit cast needed)
@ -106,14 +110,14 @@ void example()
print_result(distance, duration, avg_speed(distance, duration));
}
// Customary Units (double)
// International mile (double)
{
using namespace mp_units::international::unit_symbols;
constexpr auto distance = 140. * mi;
constexpr auto duration = 2. * h;
std::cout << "\nUS Customary Units with 'double' as representation\n";
std::cout << "\nInternational mile with 'double' as representation\n";
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
// also it is not possible to make a lossless conversion of miles to meters on an integral type

View File

@ -20,11 +20,15 @@
physical_quantities
*/
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/math.h> // IWYU pragma: keep
#include <mp-units/ostream.h>
#include <mp-units/systems/isq/electromagnetism.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
#endif
int main()
{

View File

@ -15,6 +15,11 @@
along with this program. If not, see http://www.gnu.org/licenses./
*/
#include <mp-units/compat_macros.h>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/ostream.h>
#include <mp-units/systems/iau/iau.h>
@ -24,7 +29,7 @@
#include <mp-units/systems/si/si.h>
#include <mp-units/systems/typographic/typographic.h>
#include <mp-units/systems/usc/usc.h>
#include <iostream>
#endif
namespace {

View File

@ -15,12 +15,17 @@
along with this program. If not, see http://www.gnu.org/licenses./
*/
#include <mp-units/compat_macros.h>
#include <iostream>
#include <type_traits>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <mp-units/systems/si/units.h>
#include <iostream>
#include <type_traits>
#endif
/*
get conversion factor from one dimensionally equivalent

View File

@ -20,11 +20,16 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <mp-units/compat_macros.h>
#include <iostream>
#include <map>
#ifdef MP_UNITS_MODULES
import mp_units.core;
#else
#include <mp-units/ostream.h>
#include <mp-units/quantity.h>
#include <mp-units/quantity_point.h>
#include <iostream>
#include <map>
#endif
using namespace mp_units;

View File

@ -20,14 +20,19 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <mp-units/compat_macros.h>
#include <iostream>
#include <string_view>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/systems/imperial/imperial.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/mechanics.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <iostream>
#include <string_view>
#endif
using namespace mp_units;
using namespace mp_units::international::unit_symbols;

View File

@ -21,11 +21,7 @@
// SOFTWARE.
#include "glide_computer_lib.h"
#include <mp-units/bits/fmt_hacks.h>
#include <mp-units/chrono.h>
#include <mp-units/math.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <mp-units/compat_macros.h>
#include <array>
#include <exception>
#include <iostream>
@ -33,6 +29,13 @@
#include <string>
#include <utility>
#include <vector>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/math.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/si/si.h>
#endif
namespace {

View File

@ -22,6 +22,13 @@
cmake_minimum_required(VERSION 3.5)
add_library(glide_computer_lib STATIC glide_computer_lib.cpp include/glide_computer_lib.h)
target_link_libraries(glide_computer_lib PRIVATE mp-units::core-fmt PUBLIC mp-units::si mp-units::utility example_utils)
target_include_directories(glide_computer_lib PUBLIC include)
add_library(glide_computer_lib-headers STATIC glide_computer_lib.cpp include/glide_computer_lib.h)
target_link_libraries(glide_computer_lib-headers PUBLIC mp-units::mp-units example_utils-headers)
target_include_directories(glide_computer_lib-headers PUBLIC include)
if(${projectPrefix}BUILD_CXX_MODULES)
add_library(glide_computer_lib STATIC glide_computer_lib.cpp include/glide_computer_lib.h)
target_compile_definitions(glide_computer_lib PUBLIC ${projectPrefix}MODULES)
target_link_libraries(glide_computer_lib PUBLIC mp-units::mp-units example_utils)
target_include_directories(glide_computer_lib PUBLIC include)
endif()

View File

@ -21,10 +21,14 @@
// SOFTWARE.
#include "glide_computer_lib.h"
#include <mp-units/format.h>
#include <iostream>
#include <numeric>
#include <string_view>
#ifdef MP_UNITS_MODULES
import mp_units.core;
#else
#include <mp-units/format.h>
#endif
namespace glide_computer {

View File

@ -22,11 +22,9 @@
#pragma once
#include <mp-units/compat_macros.h>
//
#include "geographic.h"
#include <mp-units/chrono.h>
#include <mp-units/math.h> // IWYU pragma: keep
#include <mp-units/quantity_point.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <algorithm>
#include <array>
#include <initializer_list>
@ -35,6 +33,14 @@
#include <ranges>
#include <string> // IWYU pragma: keep
#include <vector>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/math.h> // IWYU pragma: keep
#include <mp-units/quantity_point.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/chrono.h>
#endif
// An example of a really simplified tactical glide computer
// Simplifications:

View File

@ -25,12 +25,17 @@
// !!! renders correctly in the documentation "Examples" section. !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include <mp-units/compat_macros.h>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/ostream.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
#endif
using namespace mp_units;

View File

@ -23,18 +23,21 @@
#pragma once
#include "ranged_representation.h"
#include <mp-units/bits/fmt_hacks.h>
#include <mp-units/compare.h>
#include <mp-units/format.h>
#include <mp-units/math.h>
#include <mp-units/quantity.h>
#include <mp-units/quantity_point.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/units.h>
#include <mp-units/compat_macros.h>
#include <compare>
#include <limits>
#include <numbers>
#include <ostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/compare.h>
#include <mp-units/format.h>
#include <mp-units/quantity.h>
#include <mp-units/quantity_point.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/si.h>
#endif
namespace geographic {

View File

@ -24,11 +24,15 @@
#include "validated_type.h"
#include <mp-units/bits/external/hacks.h>
#include <mp-units/bits/fmt.h>
#include <mp-units/customization_points.h>
#include <algorithm>
#include <concepts>
#include <type_traits>
#ifdef MP_UNITS_MODULES
import mp_units.core;
#else
#include <mp-units/bits/fmt.h>
#include <mp-units/customization_points.h>
#endif
template<std::movable T, MP_UNITS_CONSTRAINED_NTTP_WORKAROUND(std::convertible_to<T>) auto Min,
MP_UNITS_CONSTRAINED_NTTP_WORKAROUND(std::convertible_to<T>) auto Max>

View File

@ -23,11 +23,16 @@
#pragma once
#include <gsl/gsl-lite.hpp>
#include <mp-units/compat_macros.h>
#include <ostream>
#include <utility>
#ifdef MP_UNITS_MODULES
import mp_units.core;
#else
#include <mp-units/bits/external/hacks.h>
#include <mp-units/bits/fmt.h>
#include <mp-units/customization_points.h>
#include <ostream>
#include <utility>
#endif
inline constexpr struct validated_tag {
} validated;

View File

@ -22,19 +22,11 @@
cmake_minimum_required(VERSION 3.5)
#
# add_example(target <depependencies>...)
#
function(add_example target)
add_executable(${target} ${target}.cpp)
target_link_libraries(${target} PRIVATE ${ARGN})
endfunction()
add_example(kalman_filter-example_1 mp-units::core-fmt mp-units::si mp-units::utility)
add_example(kalman_filter-example_2 mp-units::core-fmt mp-units::si mp-units::utility)
add_example(kalman_filter-example_3 mp-units::core-fmt mp-units::si mp-units::utility)
add_example(kalman_filter-example_4 mp-units::core-fmt mp-units::si mp-units::utility)
add_example(kalman_filter-example_5 mp-units::core-fmt mp-units::si mp-units::utility)
add_example(kalman_filter-example_6 mp-units::core-fmt mp-units::si mp-units::utility)
add_example(kalman_filter-example_7 mp-units::core-fmt mp-units::si mp-units::utility)
add_example(kalman_filter-example_8 mp-units::core-fmt mp-units::si mp-units::utility)
add_example(kalman_filter-example_1)
add_example(kalman_filter-example_2)
add_example(kalman_filter-example_3)
add_example(kalman_filter-example_4)
add_example(kalman_filter-example_5)
add_example(kalman_filter-example_6)
add_example(kalman_filter-example_7)
add_example(kalman_filter-example_8)

View File

@ -22,13 +22,17 @@
#pragma once
#include <mp-units/bits/fmt_hacks.h>
#include <mp-units/compat_macros.h>
#include <tuple>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/math.h>
#include <mp-units/quantity.h>
#include <mp-units/quantity_point.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <tuple>
#endif
namespace kalman {

View File

@ -21,11 +21,15 @@
// SOFTWARE.
#include "kalman.h"
#include <array>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <array>
#include <iostream>
#endif
// Based on: https://www.kalmanfilter.net/alphabeta.html#ex1

View File

@ -21,11 +21,15 @@
// SOFTWARE.
#include "kalman.h"
#include <array>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <array>
#include <iostream>
#endif
// Based on: https://www.kalmanfilter.net/alphabeta.html#ex2

View File

@ -21,11 +21,15 @@
// SOFTWARE.
#include "kalman.h"
#include <array>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <array>
#include <iostream>
#endif
// Based on: https://www.kalmanfilter.net/alphabeta.html#ex3

View File

@ -21,11 +21,15 @@
// SOFTWARE.
#include "kalman.h"
#include <array>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <array>
#include <iostream>
#endif
// Based on: https://www.kalmanfilter.net/alphabeta.html#ex4

View File

@ -21,12 +21,16 @@
// SOFTWARE.
#include "kalman.h"
#include <array>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/math.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <array>
#include <iostream>
#endif
// Based on: https://www.kalmanfilter.net/kalman1d.html#ex5

View File

@ -21,13 +21,17 @@
// SOFTWARE.
#include "kalman.h"
#include <array>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/math.h>
#include <mp-units/quantity_point.h>
#include <mp-units/systems/isq/thermodynamics.h>
#include <mp-units/systems/si/si.h>
#include <array>
#include <iostream>
#endif
// Based on: https://www.kalmanfilter.net/kalman1d.html#ex6

View File

@ -21,13 +21,17 @@
// SOFTWARE.
#include "kalman.h"
#include <array>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/math.h>
#include <mp-units/quantity_point.h>
#include <mp-units/systems/isq/thermodynamics.h>
#include <mp-units/systems/si/si.h>
#include <array>
#include <iostream>
#endif
// Based on: https://www.kalmanfilter.net/kalman1d.html#ex7

View File

@ -21,13 +21,17 @@
// SOFTWARE.
#include "kalman.h"
#include <array>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/math.h>
#include <mp-units/quantity_point.h>
#include <mp-units/systems/isq/thermodynamics.h>
#include <mp-units/systems/si/si.h>
#include <array>
#include <iostream>
#endif
// Based on: https://www.kalmanfilter.net/kalman1d.html#ex8

View File

@ -20,13 +20,18 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <mp-units/compat_macros.h>
#include <cmath>
#include <exception>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/ostream.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <mp-units/systems/si/units.h>
#include <cmath>
#include <exception>
#include <iostream>
#endif
namespace {

View File

@ -25,9 +25,14 @@
// !!! renders correctly in the documentation "Examples" section. !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include <mp-units/compat_macros.h>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
#endif
template<class T>
requires mp_units::is_scalar<T>

View File

@ -20,11 +20,16 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <mp-units/compat_macros.h>
#include <iostream>
#include <tuple>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
#include <tuple>
#endif
// This example implements a table of units provided in the following article
// http://cds.cern.ch/record/1481609/files/978-3-642-18018-7_BookBackMatter.pdf

View File

@ -20,19 +20,21 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <mp-units/chrono.h>
#include <mp-units/format.h>
#include <mp-units/math.h>
#include <mp-units/systems/isq/mechanics.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/constants.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <mp-units/systems/si/units.h>
#include <mp-units/compat_macros.h>
#include <cassert>
#include <chrono>
#include <iostream>
#include <numbers>
#include <utility>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/math.h>
#include <mp-units/systems/isq/mechanics.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/si.h>
#endif
// allows standard gravity (acceleration) and weight (force) to be expressed with scalar representation
// types instead of requiring the usage of Linear Algebra library for this simple example

View File

@ -20,11 +20,15 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/math.h>
#include <mp-units/ostream.h>
#include <mp-units/systems/isq_angle/isq_angle.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <iostream>
#endif
template<class T>
requires mp_units::is_scalar<T>

View File

@ -20,14 +20,18 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <exception>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/math.h>
#include <mp-units/ostream.h>
#include <mp-units/systems/isq/mechanics.h>
#include <mp-units/systems/natural/natural.h>
#include <mp-units/systems/si/constants.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <exception>
#include <iostream>
#endif
template<class T>
requires mp_units::is_scalar<T>

View File

@ -21,13 +21,18 @@
// SOFTWARE.
#include "geographic.h"
#include <mp-units/compat_macros.h>
#include <cassert>
#include <iostream>
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/ostream.h>
#include <mp-units/quantity_point.h>
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/unit_symbols.h>
#include <cassert>
#include <iostream>
#endif
using namespace mp_units;
using namespace geographic;

View File

@ -162,6 +162,7 @@ nav:
- Using Custom Representation Types: users_guide/use_cases/using_custom_representation_types.md
- Interoperability with Other Libraries: users_guide/use_cases/interoperability_with_other_libraries.md
- Extending the Library: users_guide/use_cases/extending_the_library.md
- Wide Compatibility: users_guide/use_cases/wide_compatibility.md
- Examples:
- Tags Index: users_guide/examples/tags_index.md
- All Examples:

View File

@ -25,31 +25,35 @@ project(mp-units VERSION 2.2.0 LANGUAGES CXX)
set(projectPrefix MP_UNITS_)
option(${projectPrefix}BUILD_CXX_MODULES "Add C++ modules to the list of default targets" OFF)
message(STATUS "${projectPrefix}BUILD_CXX_MODULES: ${${projectPrefix}BUILD_CXX_MODULES}")
option(${projectPrefix}AS_SYSTEM_HEADERS "Exports library as system headers" OFF)
message(STATUS "${projectPrefix}AS_SYSTEM_HEADERS: ${${projectPrefix}AS_SYSTEM_HEADERS}")
option(${projectPrefix}USE_LIBFMT "Enables usage of libfmt instead of the one from 'std'" ON)
message(STATUS "${projectPrefix}USE_LIBFMT: ${${projectPrefix}USE_LIBFMT}")
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
include(AddUnitsModule)
include(AddMPUnitsModule)
include(GNUInstallDirs)
if(${projectPrefix}BUILD_CXX_MODULES)
set(${projectPrefix}TARGET_SCOPE "PUBLIC")
else()
set(${projectPrefix}TARGET_SCOPE "INTERFACE")
endif()
if(${projectPrefix}AS_SYSTEM_HEADERS)
set(unitsAsSystem SYSTEM)
endif()
add_subdirectory(core)
add_subdirectory(core-fmt)
add_subdirectory(core-io)
add_subdirectory(systems)
add_subdirectory(utility)
# project-wide wrapper
add_library(mp-units INTERFACE)
target_link_libraries(
mp-units INTERFACE mp-units::core mp-units::core-io mp-units::core-fmt mp-units::systems mp-units::utility
)
add_library(mp-units::mp-units ALIAS mp-units)
install(TARGETS mp-units EXPORT mp-unitsTargets)
add_mp_units_module(mp-units mp-units DEPENDENCIES mp-units::core mp-units::systems MODULE_INTERFACE_UNIT mp-units.cpp)
# local build
export(EXPORT mp-unitsTargets NAMESPACE mp-units::)

View File

@ -41,29 +41,56 @@ function(validate_arguments_exists module prefix)
endfunction()
#
# add_units_module(ModuleName
# DEPENDENCIES <depependency>...
# HEADERS <header_file>...)
# add_mp_units_module(Name TargetName
# DEPENDENCIES <depependency>...
# [HEADERS <header_file>...]
# MODULE_INTERFACE_UNIT <miu_file>)
#
function(add_units_module name)
function(add_mp_units_module name target_name)
# parse arguments
set(oneValue MODULE_INTERFACE_UNIT)
set(multiValues DEPENDENCIES HEADERS)
cmake_parse_arguments(PARSE_ARGV 1 ARG "" "" "${multiValues}")
cmake_parse_arguments(PARSE_ARGV 2 ARG "" "${oneValue}" "${multiValues}")
# validate and process arguments
validate_unparsed(${name} ARG)
validate_arguments_exists(${name} ARG DEPENDENCIES HEADERS)
validate_arguments_exists(${name} ARG DEPENDENCIES MODULE_INTERFACE_UNIT)
if(${projectPrefix}TARGET_SCOPE STREQUAL INTERFACE)
set(SCOPE "INTERFACE")
endif()
# define the target for a module
add_library(mp-units-${name} INTERFACE ${ARG_HEADERS})
target_link_libraries(mp-units-${name} INTERFACE ${ARG_DEPENDENCIES})
target_include_directories(
mp-units-${name} ${unitsAsSystem} INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
set_target_properties(mp-units-${name} PROPERTIES EXPORT_NAME ${name})
add_library(mp-units::${name} ALIAS mp-units-${name})
add_library(${target_name} ${SCOPE})
target_link_libraries(${target_name} ${${projectPrefix}TARGET_SCOPE} ${ARG_DEPENDENCIES})
set_target_properties(${target_name} PROPERTIES EXPORT_NAME ${name})
add_library(mp-units::${name} ALIAS ${target_name})
install(TARGETS mp-units-${name} EXPORT mp-unitsTargets)
install(DIRECTORY include/mp-units TYPE INCLUDE)
if(ARG_HEADERS)
target_sources(
${target_name}
${${projectPrefix}TARGET_SCOPE}
FILE_SET
HEADERS
BASE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/include
FILES
${ARG_HEADERS}
)
target_include_directories(
${target_name} ${unitsAsSystem} ${${projectPrefix}TARGET_SCOPE}
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>
)
endif()
if(${projectPrefix}BUILD_CXX_MODULES)
target_sources(${target_name} PUBLIC FILE_SET CXX_MODULES FILES ${ARG_MODULE_INTERFACE_UNIT})
install(TARGETS ${target_name}
EXPORT mp-unitsTargets
FILE_SET HEADERS FILE_SET CXX_MODULES
DESTINATION ${CMAKE_INSTALL_LIBDIR}/miu
)
else()
install(TARGETS ${target_name} EXPORT mp-unitsTargets FILE_SET HEADERS)
endif()
endfunction()

View File

@ -1,36 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.19)
option(${projectPrefix}USE_LIBFMT "Enables usage of libfmt instead of the one from 'std'" ON)
message(STATUS "${projectPrefix}USE_LIBFMT: ${${projectPrefix}USE_LIBFMT}")
add_units_module(core-fmt DEPENDENCIES mp-units::core HEADERS include/mp-units/format.h)
target_compile_definitions(mp-units-core-fmt INTERFACE ${projectPrefix}USE_LIBFMT=$<BOOL:${${projectPrefix}USE_LIBFMT}>)
if(${projectPrefix}USE_LIBFMT)
if(NOT TARGET fmt::fmt)
find_package(fmt CONFIG REQUIRED)
endif()
target_link_libraries(mp-units-core-fmt INTERFACE fmt::fmt)
endif()

View File

@ -1,77 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Formatting library for C++ - the core API for char/UTF-8
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#include <mp-units/bits/external/hacks.h>
#ifndef MP_UNITS_USE_LIBFMT
#define MP_UNITS_USE_LIBFMT 1
#endif
#if MP_UNITS_USE_LIBFMT
MP_UNITS_DIAGNOSTIC_PUSH
MP_UNITS_DIAGNOSTIC_IGNORE_UNREACHABLE
MP_UNITS_DIAGNOSTIC_IGNORE_SHADOW
#include <fmt/format.h>
MP_UNITS_DIAGNOSTIC_POP
#define MP_UNITS_STD_FMT fmt
#define MP_UNITS_FMT_LOCALE(loc) (loc).template get<std::locale>()
#define MP_UNITS_FMT_TO_ARG_ID(arg) static_cast<int>(arg)
#define MP_UNITS_FMT_FROM_ARG_ID(arg) static_cast<size_t>(arg)
// This re-uses code from fmt;
#if FMT_EXCEPTIONS
#if FMT_MSC_VERSION || defined(__NVCC__)
#define MP_UNITS_THROW(x) ::fmt::detail::do_throw(x)
#else
#define MP_UNITS_THROW(x) throw x
#endif
#else
#define MP_UNITS_THROW(x) \
do { \
FMT_ASSERT(false, (x).what()); \
} while (false)
#endif
#else
#ifndef __cpp_lib_format
#error "std::formatting facility not supported"
#endif
#include <format>
#define MP_UNITS_STD_FMT std
#define MP_UNITS_FMT_LOCALE(loc) loc
#define MP_UNITS_FMT_TO_ARG_ID(arg) arg
#define MP_UNITS_FMT_FROM_ARG_ID(arg) arg
#define MP_UNITS_THROW(arg) throw arg
#endif

View File

@ -1,25 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.19)
add_units_module(core-io DEPENDENCIES mp-units::core HEADERS include/mp-units/ostream.h)

View File

@ -28,62 +28,82 @@ if(NOT TARGET gsl::gsl-lite)
endif()
# core library definition
add_library(
mp-units-core
INTERFACE
include/mp-units/bits/external/algorithm.h
include/mp-units/bits/external/fixed_string.h
include/mp-units/bits/external/hacks.h
include/mp-units/bits/external/math_concepts.h
include/mp-units/bits/external/prime.h
include/mp-units/bits/external/type_list.h
include/mp-units/bits/external/type_name.h
include/mp-units/bits/external/type_traits.h
include/mp-units/bits/dimension_concepts.h
include/mp-units/bits/expression_template.h
include/mp-units/bits/get_associated_quantity.h
include/mp-units/bits/get_common_base.h
include/mp-units/bits/magnitude.h
include/mp-units/bits/quantity_cast.h
include/mp-units/bits/quantity_concepts.h
include/mp-units/bits/quantity_point_concepts.h
include/mp-units/bits/quantity_spec_concepts.h
include/mp-units/bits/ratio.h
include/mp-units/bits/reference_concepts.h
include/mp-units/bits/representation_concepts.h
include/mp-units/bits/sudo_cast.h
include/mp-units/bits/symbol_text.h
include/mp-units/bits/text_tools.h
include/mp-units/bits/unit_concepts.h
include/mp-units/bits/value_cast.h
include/mp-units/concepts.h
include/mp-units/core.h
include/mp-units/customization_points.h
include/mp-units/dimension.h
include/mp-units/quantity.h
include/mp-units/quantity_point.h
include/mp-units/quantity_spec.h
include/mp-units/reference.h
include/mp-units/system_reference.h
include/mp-units/unit.h
add_mp_units_module(
core mp-units-core
DEPENDENCIES gsl::gsl-lite
HEADERS include/mp-units/bits/external/algorithm.h
include/mp-units/bits/external/fixed_string.h
include/mp-units/bits/external/hacks.h
include/mp-units/bits/external/math_concepts.h
include/mp-units/bits/external/prime.h
include/mp-units/bits/external/type_list.h
include/mp-units/bits/external/type_name.h
include/mp-units/bits/external/type_traits.h
include/mp-units/bits/core_gmf.h
include/mp-units/bits/dimension_concepts.h
include/mp-units/bits/expression_template.h
include/mp-units/bits/fmt.h
include/mp-units/bits/get_associated_quantity.h
include/mp-units/bits/get_common_base.h
include/mp-units/bits/magnitude.h
include/mp-units/bits/quantity_cast.h
include/mp-units/bits/quantity_concepts.h
include/mp-units/bits/quantity_point_concepts.h
include/mp-units/bits/quantity_spec_concepts.h
include/mp-units/bits/ratio.h
include/mp-units/bits/reference_concepts.h
include/mp-units/bits/representation_concepts.h
include/mp-units/bits/sudo_cast.h
include/mp-units/bits/symbol_text.h
include/mp-units/bits/text_tools.h
include/mp-units/bits/unit_concepts.h
include/mp-units/bits/value_cast.h
include/mp-units/compare.h
include/mp-units/compat_macros.h
include/mp-units/concepts.h
include/mp-units/core.h
include/mp-units/customization_points.h
include/mp-units/dimension.h
include/mp-units/format.h
include/mp-units/math.h
include/mp-units/ostream.h
include/mp-units/quantity.h
include/mp-units/quantity_point.h
include/mp-units/quantity_spec.h
include/mp-units/random.h
include/mp-units/reference.h
include/mp-units/system_reference.h
include/mp-units/unit.h
MODULE_INTERFACE_UNIT mp-units-core.cpp
)
target_compile_features(mp-units-core INTERFACE cxx_std_20)
target_link_libraries(mp-units-core INTERFACE gsl::gsl-lite)
target_include_directories(
mp-units-core ${unitsAsSystem} INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
target_compile_definitions(
mp-units-core ${${projectPrefix}TARGET_SCOPE} ${projectPrefix}USE_LIBFMT=$<BOOL:${${projectPrefix}USE_LIBFMT}>
)
if(${projectPrefix}USE_LIBFMT)
if(NOT TARGET fmt::fmt)
find_package(fmt CONFIG REQUIRED)
endif()
target_link_libraries(mp-units-core ${${projectPrefix}TARGET_SCOPE} fmt::fmt)
endif()
if(${projectPrefix}BUILD_CXX_MODULES)
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18)
target_compile_definitions(mp-units-core PUBLIC _LIBCPP_NO_ABI_TAG)
endif()
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 18)
target_compile_options(mp-units-core PUBLIC "-Wno-include-angled-in-module-purview")
endif()
endif()
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(
mp-units-core
INTERFACE /utf-8 # Specifies both the source character set and the execution character set as UTF-8
mp-units-core ${${projectPrefix}TARGET_SCOPE}
/utf-8 # Specifies both the source character set and the execution character set as UTF-8
)
endif()
set_target_properties(mp-units-core PROPERTIES EXPORT_NAME core)
add_library(mp-units::core ALIAS mp-units-core)
# installation
install(TARGETS mp-units-core EXPORT mp-unitsTargets)
install(DIRECTORY include/mp-units TYPE INCLUDE)

View File

@ -0,0 +1,50 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
// core
#include <gsl/gsl-lite.hpp>
#include <mp-units/bits/external/hacks.h>
#include <array>
#include <cmath>
#include <compare>
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <limits>
#include <numbers>
#include <numeric>
#include <optional>
#include <random>
#include <ranges>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
// si
#include <chrono>

View File

@ -22,8 +22,6 @@
#pragma once
#include <version>
#if __clang__
#define MP_UNITS_COMP_CLANG __clang_major__
#elif __GNUC__
@ -70,9 +68,6 @@
#define MP_UNITS_DIAGNOSTIC_IGNORE_DEPRECATED
#endif
#include <compare>
#include <concepts>
#if MP_UNITS_COMP_MSVC
#define MP_UNITS_TYPENAME typename
@ -83,7 +78,7 @@
#endif
#if (defined MP_UNITS_COMP_CLANG && MP_UNITS_COMP_CLANG < 17) || (defined MP_UNITS_COMP_GCC && MP_UNITS_COMP_GCC < 12)
#if (defined MP_UNITS_COMP_CLANG && MP_UNITS_COMP_CLANG < 17)
#define MP_UNITS_CONSTEVAL constexpr
@ -104,3 +99,50 @@
#define MP_UNITS_CONSTRAINED_NTTP_WORKAROUND(X) X
#endif
#ifndef MP_UNITS_USE_LIBFMT
#define MP_UNITS_USE_LIBFMT 1
#endif
#if MP_UNITS_USE_LIBFMT
MP_UNITS_DIAGNOSTIC_PUSH
MP_UNITS_DIAGNOSTIC_IGNORE_UNREACHABLE
MP_UNITS_DIAGNOSTIC_IGNORE_SHADOW
#include <fmt/format.h>
MP_UNITS_DIAGNOSTIC_POP
#define MP_UNITS_STD_FMT fmt
#define MP_UNITS_FMT_LOCALE(loc) (loc).template get<std::locale>()
#define MP_UNITS_FMT_TO_ARG_ID(arg) static_cast<int>(arg)
#define MP_UNITS_FMT_FROM_ARG_ID(arg) static_cast<size_t>(arg)
// This re-uses code from fmt;
#if FMT_EXCEPTIONS
#if FMT_MSC_VERSION || defined(__NVCC__)
#define MP_UNITS_THROW(x) ::fmt::detail::do_throw(x)
#else
#define MP_UNITS_THROW(x) throw x
#endif
#else
#define MP_UNITS_THROW(x) \
do { \
FMT_ASSERT(false, (x).what()); \
} while (false)
#endif
#else
#ifndef __cpp_lib_format
#error "std::formatting facility not supported"
#endif
#include <format>
#define MP_UNITS_STD_FMT std
#define MP_UNITS_FMT_LOCALE(loc) loc
#define MP_UNITS_FMT_TO_ARG_ID(arg) arg
#define MP_UNITS_FMT_FROM_ARG_ID(arg) arg
#define MP_UNITS_THROW(arg) throw arg
#endif

View File

@ -30,7 +30,7 @@
#pragma once
#include <gsl/gsl-lite.hpp>
#include <mp-units/bits/fmt_hacks.h>
#include <mp-units/bits/external/hacks.h>
#include <concepts>
#include <limits>
#include <string_view>

View File

@ -0,0 +1,39 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <mp-units/bits/external/hacks.h>
#ifdef __cpp_explicit_this_parameter
#define QUANTITY_SPEC(name, ...) \
inline constexpr struct name : ::mp_units::quantity_spec<__VA_ARGS__> { \
} name
#else
#define QUANTITY_SPEC(name, ...) \
inline constexpr struct name : ::mp_units::quantity_spec<name, __VA_ARGS__> { \
} name
#endif

View File

@ -22,12 +22,18 @@
#pragma once
#include <mp-units/compare.h>
#include <mp-units/compat_macros.h>
#include <mp-units/concepts.h>
#include <mp-units/customization_points.h>
#include <mp-units/dimension.h>
#include <mp-units/format.h>
#include <mp-units/math.h>
#include <mp-units/ostream.h>
#include <mp-units/quantity.h>
#include <mp-units/quantity_point.h>
#include <mp-units/quantity_spec.h>
#include <mp-units/random.h>
#include <mp-units/reference.h>
#include <mp-units/system_reference.h>
#include <mp-units/unit.h>

View File

@ -23,27 +23,13 @@
#pragma once
#include <mp-units/bits/quantity_point_concepts.h>
#include <mp-units/compare.h>
#include <mp-units/customization_points.h>
#include <mp-units/quantity.h>
#include <compare>
namespace mp_units {
namespace detail {
template<typename T>
requires requires {
{
T::zero()
} -> std::equality_comparable_with<T>;
}
[[nodiscard]] constexpr bool is_eq_zero(T v)
{
return v == T::zero();
}
} // namespace detail
template<typename Derived, QuantitySpec auto QS>
struct absolute_point_origin {
static constexpr QuantitySpec auto quantity_spec = QS;
@ -95,11 +81,9 @@ template<PointOrigin PO1, PointOrigin PO2>
else if constexpr (detail::RelativePointOrigin<PO1> && detail::RelativePointOrigin<PO2>)
return PO1::quantity_point == PO2::quantity_point;
else if constexpr (detail::RelativePointOrigin<PO1>)
return detail::same_absolute_point_origins(po1, po2) &&
detail::is_eq_zero(PO1::quantity_point.quantity_from_zero());
return detail::same_absolute_point_origins(po1, po2) && is_eq_zero(PO1::quantity_point.quantity_from_zero());
else if constexpr (detail::RelativePointOrigin<PO2>)
return detail::same_absolute_point_origins(po1, po2) &&
detail::is_eq_zero(PO2::quantity_point.quantity_from_zero());
return detail::same_absolute_point_origins(po1, po2) && is_eq_zero(PO2::quantity_point.quantity_from_zero());
}
template<Reference R>

View File

@ -31,6 +31,7 @@
#include <mp-units/bits/quantity_spec_concepts.h>
#include <mp-units/bits/reference_concepts.h>
#include <mp-units/bits/representation_concepts.h>
#include <mp-units/compat_macros.h>
#include <mp-units/dimension.h>
#include <tuple>
@ -364,20 +365,6 @@ struct quantity_spec<Self, QS, Eq, Args...> : quantity_spec<Self, QS, Args...> {
static constexpr quantity_character character = detail::quantity_character_init<Args...>(Eq.character);
};
#ifdef __cpp_explicit_this_parameter
#define QUANTITY_SPEC(name, ...) \
inline constexpr struct name : ::mp_units::quantity_spec<__VA_ARGS__> { \
} name
#else
#define QUANTITY_SPEC(name, ...) \
inline constexpr struct name : ::mp_units::quantity_spec<name, __VA_ARGS__> { \
} name
#endif
/**
* @brief A specification of a derived quantity

View File

@ -0,0 +1,10 @@
module;
#include <mp-units/bits/core_gmf.h>
export module mp_units.core;
export
{
#include <mp-units/core.h>
}

6
src/mp-units.cpp Normal file
View File

@ -0,0 +1,6 @@
module;
export module mp_units;
export import mp_units.core;
export import mp_units.systems;

View File

@ -22,40 +22,39 @@
cmake_minimum_required(VERSION 3.19)
# systems
add_subdirectory(angular)
add_subdirectory(iec80000)
add_subdirectory(isq)
add_subdirectory(isq_angle)
add_subdirectory(natural)
add_subdirectory(si)
add_subdirectory(cgs)
add_subdirectory(hep)
add_subdirectory(iau)
add_subdirectory(imperial)
add_subdirectory(international)
add_subdirectory(typographic)
add_subdirectory(usc)
# wrapper for all the systems
add_library(mp-units-systems INTERFACE)
target_link_libraries(
mp-units-systems
INTERFACE
mp-units::angular
mp-units::iec80000
mp-units::isq
mp-units::isq_angle
mp-units::natural
mp-units::si
mp-units::cgs
mp-units::hep
mp-units::iau
mp-units::imperial
mp-units::international
mp-units::typographic
mp-units::usc
add_mp_units_module(
systems mp-units-systems
DEPENDENCIES mp-units::core
HEADERS include/mp-units/systems/angular/angular.h
include/mp-units/systems/angular/math.h
include/mp-units/systems/angular/units.h
include/mp-units/systems/cgs/cgs.h
include/mp-units/systems/hep/hep.h
include/mp-units/systems/iau/iau.h
include/mp-units/systems/iec80000/binary_prefixes.h
include/mp-units/systems/iec80000/iec80000.h
include/mp-units/systems/iec80000/quantities.h
include/mp-units/systems/iec80000/unit_symbols.h
include/mp-units/systems/iec80000/units.h
include/mp-units/systems/imperial/imperial.h
include/mp-units/systems/international/international.h
include/mp-units/systems/isq/atomic_and_nuclear_physics.h
include/mp-units/systems/isq/base_quantities.h
include/mp-units/systems/isq/electromagnetism.h
include/mp-units/systems/isq/isq.h
include/mp-units/systems/isq/mechanics.h
include/mp-units/systems/isq/space_and_time.h
include/mp-units/systems/isq/thermodynamics.h
include/mp-units/systems/isq_angle/isq_angle.h
include/mp-units/systems/natural/natural.h
include/mp-units/systems/si/chrono.h
include/mp-units/systems/si/constants.h
include/mp-units/systems/si/math.h
include/mp-units/systems/si/prefixes.h
include/mp-units/systems/si/si.h
include/mp-units/systems/si/unit_symbols.h
include/mp-units/systems/si/units.h
include/mp-units/systems/typographic/typographic.h
include/mp-units/systems/usc/usc.h
MODULE_INTERFACE_UNIT mp-units-systems.cpp
)
add_library(mp-units::systems ALIAS mp-units-systems)
set_target_properties(mp-units-systems PROPERTIES EXPORT_NAME systems)
install(TARGETS mp-units-systems EXPORT mp-unitsTargets)

View File

@ -1,25 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.19)
add_units_module(angular DEPENDENCIES mp-units::isq HEADERS include/mp-units/systems/angular/angular.h)

View File

@ -1,25 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.19)
add_units_module(cgs DEPENDENCIES mp-units::si HEADERS include/mp-units/systems/cgs/cgs.h)

View File

@ -1,25 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2021 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.19)
add_units_module(hep DEPENDENCIES mp-units::si HEADERS include/mp-units/systems/hep/hep.h)

View File

@ -1,25 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.19)
add_units_module(iau DEPENDENCIES mp-units::si HEADERS include/mp-units/systems/iau/iau.h)

View File

@ -1,31 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.19)
add_units_module(
iec80000
DEPENDENCIES mp-units::isq mp-units::si
HEADERS include/mp-units/systems/iec80000/binary_prefixes.h include/mp-units/systems/iec80000/quantities.h
include/mp-units/systems/iec80000/iec80000.h include/mp-units/systems/iec80000/unit_symbols.h
include/mp-units/systems/iec80000/units.h
)

View File

@ -1,27 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.19)
add_units_module(
imperial DEPENDENCIES mp-units::si mp-units::international HEADERS include/mp-units/systems/imperial/imperial.h
)

View File

@ -22,12 +22,5 @@
#pragma once
#include <mp-units/bits/math_angular.h>
#include <mp-units/bits/math_core.h>
#include <mp-units/bits/math_si.h>
// This header is intentionally empty and just include other headers
// `math.h` is just a convenience wrapper for not modular code
// With C++20 modules:
// - math_core will be a part of the mp_units.core module
// - math_si and math_angular will be provided with the mp_units.systems module
#include <mp-units/systems/angular/math.h>
#include <mp-units/systems/angular/units.h>

View File

@ -26,7 +26,7 @@
#include <mp-units/bits/value_cast.h>
#include <mp-units/customization_points.h>
#include <mp-units/quantity.h>
#include <mp-units/systems/angular/angular.h>
#include <mp-units/systems/angular/units.h>
#include <mp-units/unit.h>
// IWYU pragma: begin_exports

Some files were not shown because too many files have changed in this diff Show More