|
quanta 0.1.0
Type-safe units for temperature, frequency, electrical and spatial quantities, modeled after std::chrono
|
Type-safe, header-only C++20 units for temperature, frequency, electrical and spatial quantities, modeled after std::chrono.
Each domain has its own header and namespace, and can be used on its own.
| Domain | Header | Namespace | Guide |
|---|---|---|---|
| Temperature (absolute and delta; °C, K, °F) | <quanta/thermo> | quanta::thermo | thermo |
| Frequency (mHz to THz; period, wavelength, musical intervals) | <quanta/frequency> | quanta::frequency | frequency |
| Electrical units (V, A, Ω, W, C, J, F, H) and decibels (dB, dBm, dBW, dBµV) | <quanta/electro>, <quanta/decibel> | quanta::electro | electro |
| Length, area and volume (metric and imperial) | <quanta/spatial> | quanta::spatial | spatial |
Every header is also available with a .hpp extension (<quanta/thermo.hpp>).
std::chrono::duration25_c, 2400_MHz, 3300_mV, 250_mm)std::format support** (when available), with markers for base-unit (b) and scaled (s) formsAs with std::chrono, each domain's literals are in an inline namespace of quanta::literals, and are also brought into the domain's own namespace:
Literal values are integers, written as any C++ integer literal: with digit separators (1'000_mV), in hexadecimal (0x10_V), binary (0b101_V) or, with a leading 0, octal (017_Hz is 15 Hz, as std::chrono's 017h is 15 h). A value the literal's type cannot represent is a compile error.
The traits and tags shared by every domain (quanta::treat_as_inexact, quanta::base_unit, quanta::scaled) are defined once in quanta:: and re-exported into each domain namespace, so they are never ambiguous when several domains are in use. Specialize quanta::treat_as_inexact to make a custom representation behave like a floating-point one in every domain.
/utf-8 automatically (the headers contain UTF-8 unit symbols). Projects that do not use the CMake target (e.g. a plain include path) must add /utf-8 themselves._Δc, _kΩ, _dBµV, _µm, …) are unavailable there (QUANTA_HAS_UTF8_LITERALS is 0). Each has an ASCII alternative that is always available (_delta_c, _kOhm, _dBuV, _um, …).The library can be used as an ESP-IDF component. Add it to your project's idf_component.yml:
std::format support is controlled by the CONFIG_QUANTA_STD_FORMAT_SUPPORT Kconfig option in menuconfig (under "Component config" → "Quanta Library"). Enabled (the default), std::format is supported where the toolchain provides <format> (not the GCC 12 of ESP-IDF 5.1); disabled, it is off. Outside ESP-IDF it is enabled when <format> is available, and can be disabled by defining CONFIG_QUANTA_STD_FORMAT to 0.
Copy the include/quanta/ directory to your project.
quanta replaces these four libraries. Compared with their final releases (thermo-cpp 2.2, frequency-cpp 1.3, electro-cpp 0.4 and spatial-cpp 0.1), the types, functions and literals are unchanged apart from the behaviour changes listed below the table; only their names and locations moved:
| Before | After |
|---|---|
#include <thermo/thermo> | #include <quanta/thermo> |
#include <frequency/frequency> | #include <quanta/frequency> |
#include <electro/electro>, <electro/decibel> | #include <quanta/electro>, <quanta/decibel> |
#include <spatial/spatial> | #include <quanta/spatial> |
thermo::, freq::, electro::, spatial:: | quanta::thermo::, quanta::frequency::, quanta::electro::, quanta::spatial:: |
thermo_literals, frequency_literals, … | quanta::thermo_literals, quanta::frequency_literals, … (or quanta::literals) |
thermo::treat_as_inexact (and the others) | quanta::treat_as_inexact |
CONFIG_THERMO_STD_FORMAT macro (and the others) | CONFIG_QUANTA_STD_FORMAT |
CONFIG_THERMO_STD_FORMAT Kconfig option (and the others) | CONFIG_QUANTA_STD_FORMAT_SUPPORT |
THERMO_HAS_UTF8_LITERALS (and the others) | QUANTA_HAS_UTF8_LITERALS |
thermo::thermo CMake target (and the others) | quanta::quanta |
cleishm/thermo ESP-IDF component (and the others) | cleishm/quanta |
Behaviour changes:
round on deltas rounds ties to even, as std::chrono::round and the other domains do; thermo-cpp rounded ties away from zero.floor and ceil of a delta step the cast result by one tick of the target precision only when the target rep is integral, as in the other domains; for any other target rep (floating-point or user-defined) they are a plain delta_cast. thermo-cpp stepped every target, so an inexact floating-point cast could move by a whole tick (floor<delta<double>>(delta_millicelsius(2007)) gave 1.007).difference() does, and adding two temperatures is ill-formed; thermo-cpp returned a temperature from both.to_level of a zero quantity gives a level of -infinity when the level's rep is floating-point; electro-cpp gave min(), which integral levels still get.0 makes a literal octal (0123_V is 83 V; the old libraries read it as 123 V), digit separators, hexadecimal and binary are accepted, and a value beyond unsigned long long is a compile error rather than wrapping silently.hertz(frequency<double>(1.5)) is 1 Hz, as frequency_cast gives), where the old libraries rejected the constructor. Temperatures follow the same rule with their own test for lossless (across scales, the offset must also be a whole number of target ticks). One consequence for thermo: a temperature whose rep the source rep converts to only explicitly now needs direct-initialization (T t(celsius(3)); rather than T t = celsius(3);), as deltas already did.Additions, so that every domain offers the same operations:
abs of a delta, and explicit lossy construction of a delta from another (delta_celsius(delta_millicelsius(1500))).trunc, rounding toward zero.thermo previously required C++23; quanta needs only C++20 throughout.
Migrating from an earlier release (thermo-cpp before 2.2, frequency-cpp before 1.3, electro-cpp before 0.4) also changes formatted output: a format spec such as {:.1f} now renders the value in the type's own unit (22534.0m°C for millicelsius(22534)) where those releases converted to the base unit (22.5°C). Add the b marker ({:b.1f}) for the old output. A plain {} is unchanged.
With MSVC:
Formatting is checked with clang-format 23.1.0, the version CI uses (pipx install clang-format==23.1.0):
MIT License - see [LICENSE](LICENSE) for details.