A header-only type-safe zero overhead compile-time physical units C++20 library.
Zollstock is German for folding rule. It's a funny word, because it's a lie. Zoll means inch but the so called Zollstock normaly shows centimeters these days
This library increases the type-safety of your application by providing scalars associated with physical units.
All additional checks are executed at compile-time, producing no overhead in your final application.
The library is SI-centric. All non-SI units are defined relative to their corresponding counterpart. All
built-in numeric types known in C++20 can be combined with units except char
which isn't considered a number
but a character. You can use signed char
, unsigned char
, std::int8_t
or
std::uint8_t
instead. There is currently no support for C++23 fixed width floating-point types. But their support is
planed.
The library is still in a very early development stage. So please be careful when using it in production code.
#include <zollstock/units.hpp>
#include <zollstock/quantities.hpp>
#include <iostream>
#include <cstdlib>
#include <format>
namespace zs = zollstock;
using namespace zs::quantities::constants;
using namespace zs::units;
[[noreturn]] void argument_error() noexcept
{
std::cerr << "Invalid arguments\n"
<< "Usage: pcalc <wall thickness (mm)> <outer diameter (mm)> <length (m)>\n";
std::exit(1);
}
[[nodiscard]] auto read_args(int argc, char** argv) noexcept
{
if (argc != 4)
argument_error();
try
{
return std::tuple{
zs::stod<mm>(argv[1]),
zs::stod<mm>(argv[2]),
zs::in<mm>(zs::stod<m>(argv[3])),
};
}
catch(const std::exception&)
{
argument_error();
}
}
[[nodiscard]] zs::mass_c auto calculate_pipe_mass(
zs::length_c auto wall_thickness,
zs::length_c auto outer_diameter,
zs::length_c auto pipe_length
)
{
static constexpr auto copper_density = zs::in<g/mm3>(8.1_g/cm3);
const auto outer_radius = outer_diameter / 2;
const auto inner_radius = outer_radius - wall_thickness;
const auto outer_area = pi * outer_radius * outer_radius;
const auto inner_area = pi * inner_radius * inner_radius;
const auto ring_area = outer_area - inner_area;
const auto pipe_volume = ring_area * pipe_length;
return zs::in<kg>(pipe_volume * copper_density);
}
int main(int argc, char** argv)
{
// Checking arguments
const auto [wall_thickness, outer_diameter, pipe_length] = read_args(argc, argv);
// Calculating mass of a copper pipe
std::cout << std::format(
"pipe mass: {}\n",
calculate_pipe_mass(wall_thickness, outer_diameter, pipe_length)
);
return 0;
}
prefix | Q | R | Y | Z | E | P | T | G | M | k | h | da | d | c | m | μ | n | p | f | a | z | y | r | q | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
s | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
m | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
g | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
A | |||||||||||||||||||||||||
K | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
mol | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
cd |
prefix | Q | R | Y | Z | E | P | T | G | M | k | h | da | d | c | m | μ | n | p | f | a | z | y | r | q | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
rad | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
sr | |||||||||||||||||||||||||
Hz | |||||||||||||||||||||||||
N | |||||||||||||||||||||||||
Pa | |||||||||||||||||||||||||
J | |||||||||||||||||||||||||
W | |||||||||||||||||||||||||
C | |||||||||||||||||||||||||
V | |||||||||||||||||||||||||
F | |||||||||||||||||||||||||
Ω (ohm) | |||||||||||||||||||||||||
S | |||||||||||||||||||||||||
Wb | |||||||||||||||||||||||||
T | |||||||||||||||||||||||||
°C (degc) | |||||||||||||||||||||||||
lm | |||||||||||||||||||||||||
lx | |||||||||||||||||||||||||
Bq | |||||||||||||||||||||||||
Gy | |||||||||||||||||||||||||
Sv | |||||||||||||||||||||||||
kat |
There is no finite set of unamed derived units. You can combine base units as you like. But there are some unamed derived units with predefined symbols and literals. These symbols and literals are not required. Their only purpose is to increase readability.
prefix | Q | R | Y | Z | E | P | T | G | M | k | h | da | d | c | m | μ | n | p | f | a | z | y | r | q | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
m² (m2) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
m³ (m3) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
s² (s2) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
prefix | Q | R | Y | Z | E | P | T | G | M | k | h | da | d | c | m | μ | n | p | f | a | z | y | r | q | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
asec | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
gon | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
° (deg) | — | — | — | — | — | — | — | — | — | — | — | — | ✓ | — | — | — | — | — | — | — | — | — | — | — | — |
amin | — | — | — | — | — | — | — | — | — | — | — | — | ✓ | — | — | — | — | — | — | — | — | — | — | — | — |
min | — | — | — | — | — | — | — | — | — | — | — | — | ✓ | — | — | — | — | — | — | — | — | — | — | — | — |
h | — | — | — | — | — | — | — | — | — | — | — | — | ✓ | — | — | — | — | — | — | — | — | — | — | — | — |
d | — | — | — | — | — | — | — | — | — | — | — | — | ✓ | — | — | — | — | — | — | — | — | — | — | — | — |
a | — | — | — | — | — | — | — | — | — | — | — | — | ✓ | — | — | — | — | — | — | — | — | — | — | — | — |