mp-units
- A Units Library for C++
Summary
Units
is a compile-time enabled Modern C++ library that provides compile-time dimensional
analysis and unit/quantity manipulation. The basic idea and design heavily bases on
std::chrono::duration
and extends it to work properly with many dimensions.
Here is a small example of possible operations:
// simple numeric operations
static_assert(10km / 2 == 5km);
// unit conversions
static_assert(1h == 3600s);
static_assert(1km + 1m == 1001m);
// dimension conversions
static_assert(1km / 1s == 1000mps);
static_assert(2kmph * 2h == 4km);
static_assert(2km / 2kmph == 1h);
static_assert(1000 / 1s == 1kHz);
static_assert(10km / 5km == 2);
Usage Overview
The library framework consists of a few concepts: quantities, units, dimensions and their exponents. From the user's
point of view the most important is a quantity
.
Quantity is a concrete amount of a unit for a specified dimension with a specific representation:
units::quantity<units::kilometre, double> d1(123);
auto d2 = 123km; // units::quantity<units::kilometre, std::int64_t>
There are C++ concepts provided for each such quantity type:
template<typename T>
concept Length = QuantityOf<T, length>;
With that we can easily write a function template like this:
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t)
{
return d / t;
}
Concepts usage in the function above guarantee correctness enforced in compile-time and the guarantee that no unneeded intermediate conversions will ever be applied no matter which units the user will decide to pass to such function template:
using namespace units;
constexpr quantity<kilometre> distance(220);
constexpr quantity<hour> time(2);
constexpr Velocity speed = avg_speed(distance, time);
static_assert(std::same_as<std::remove_cvref_t<decltype(speed)>, quantity<kilometre_per_hour>>);
static_assert(speed.count() == 110);
The units library also tries really hard to printing any quantity in the most user friendly fashion:
std::cout << speed << '\n';
std::cout << quantity_cast<metre_per_second>(speed) << '\n';
std::cout << avg_speed(140.mi, 2h) << '\n';
Try it on Compiler Explorer.
Library design
mp-units
library design rationale and documentation can be found in doc/DESIGN.md
Repository structure
That repository contains the following independent cmake
-based projects:
./src
- header-only project forunits
.
- project used for development needs that wraps./src
project together with usage examples and unit tests./test_package
- library installation and Conan package verification
Please note that the projects depend on cmake
git submodule in the ./cmake/common
subdirectory.
Building, testing, and installation
For a detailed information on project compilation, testing and reuse please refer to doc/INSTALL.md.
NOTE: This library as of now compiles correctly only with gcc-9.1 and newer.
Release notes
-
0.4.0 Nov 17, 2019
- Support for derived dimensions in
exp
added - Added
pow()
andsqrt()
operations on quantities units
removed from astd::experimental
namespace- Downcasting facility refactored so the user does not have to write the boilerplate code anymore
- From now on base dimensions should inherit from
base_dimension
class template - Added unit symbols definitions to
base_dimension
and derived units - Added support for
operator<<
onquantity
fmt
support added- Derived unit factory helpers refactored
- Refactored the way prefixed units are defined
- Support for derived dimensions in
-
0.3.1 Sep 18, 2019
- cmcstl2 dependency changed to range-v3 0.9.1
-
0.3.0 Sep 16, 2019 (CppCon 2019 design)
- The design as described on CppCon 2019 talk (https://youtu.be/0YW6yxkdhlU)
- Applied the feedback from the Cologne evening session
upcasting_traits
renamed todowncasting_traits
Dimension
template parameter removed from quantity
units
moved to astd::experimental
namespace- Leading underscore prefix removed from UDLs
- Added a few more derived dimensions
meter
renamed tometre
- Missing
operator*
added - Predefined dimensions moved to a dedicated directory
dimension_
prefix removed from names of derived dimensions- cmcstl2 library updated to 2019.09.19
base_dimension
is a value provided asconst&
to theexp
type- integrated with Compiler Explorer
- gsl-lite dependency removed
- Fractional dimension exponents support added
QuantityOf
concept introducedquantity_cast<U, Rep>()
support added
-
0.2.0 July 18, 2019 (C++Now 2019 design)
- The design as described on C++Now 2019 talk (https://youtu.be/wKchCktZPHU)
- Added C++20 features supported by gcc-9.1 (
std::remove_cvref_t
, down with typename,std::type_identity
) - Compile-time performance optimizations (
type_list
,common_ratio
,ratio
,conditional_t
)
-
0.1.0 May 18, 2019
- Initial library release
- Begin semantic versioning
- The last version to work with gcc-8