Skip to content

hello_units

This is a really simple example showcasing the features of the mp-units library.

First, we include the headers for:

  • a system of quantities (ISQ)
  • symbols of SI units
  • symbols of international units
  • text and stream output support
hello_units.cpp
1
2
3
4
5
6
#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>

Also, to shorten the definitions, we "import" mp_units namespace.

hello_units.cpp
using namespace mp_units;

Next we define a simple function that calculates average speed based on the provided arguments of length and time:

hello_units.cpp
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d, QuantityOf<isq::time> auto t)
{
  return d / t;
}

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 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 of what to expect from a function than just using auto.

hello_units.cpp
int main()
{
  using namespace mp_units::si::unit_symbols;
  using namespace mp_units::international::unit_symbols;

The above lines explicitly opt-in to use 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.

hello_units.cpp
  constexpr quantity v1 = 110 * (km / h);
  constexpr quantity v2 = 70 * mph;
  constexpr quantity v3 = avg_speed(220. * km, 2 * h);
  constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * isq::duration[h]);
  constexpr quantity v5 = v3.in(m / s);
  constexpr quantity v6 = value_cast<m / s>(v4);
  constexpr quantity v7 = value_cast<int>(v6);
  • Lines 16 & 17 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 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 more restrictive conversion rules.
  • Line 20 changes the unit of a quantity v3 to m / s in a value-preserving way (floating-point representations are considered to be value-preserving).
  • Line 21 does a similar operation but this time it would succeed also for value-truncating cases (if it was the case).
  • Line 22 does a value-truncating conversion of changing the underlying representation type from double to int.
hello_units.cpp
  std::cout << v1 << '\n';                                                // 110 km/h
  std::cout << v2 << '\n';                                                // 70 mi/h
  std::cout << MP_UNITS_STD_FMT::format("{}", v3) << '\n';                // 110 km/h
  std::cout << MP_UNITS_STD_FMT::format("{:*^14}", v4) << '\n';           // ***70 mi/h****
  std::cout << MP_UNITS_STD_FMT::format("{:%Q in %q}", v5) << '\n';       // 30.5556 in m/s
  std::cout << MP_UNITS_STD_FMT::format("{0:%Q} in {0:%q}", v6) << '\n';  // 31.2928 in m/s
  std::cout << MP_UNITS_STD_FMT::format("{:%Q}", v7) << '\n';             // 31
}

The above presents various ways to print a quantity. Both stream insertion operations and std::format 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.