Implementing a Physical Units Library for C++
Mateusz Pusz April 12, 2019 Famous motivating example The Mars Climate Orbiter
• Robotic space probe launched by NASA on December 11, 1998
ACCU 2019 | Implementing a Physical Units Library for C++ 3 The Mars Climate Orbiter
• Robotic space probe launched by NASA on December 11, 1998 • Project costs: $327.6 million – spacecra development: $193.1 million – launching it: $91.7 million – mission operations: $42.8 million
ACCU 2019 | Implementing a Physical Units Library for C++ 3 The Mars Climate Orbiter
• Robotic space probe launched by NASA on December 11, 1998 • Project costs: $327.6 million – spacecra development: $193.1 million – launching it: $91.7 million – mission operations: $42.8 million • Mars Climate Orbiter began the planned orbital insertion maneuver on September 23, 1999 at 09:00:46 UTC
ACCU 2019 | Implementing a Physical Units Library for C++ 3
The Mars Climate Orbiter
• Space probe went out of radio contact when it passed behind Mars at 09:04:52 UTC, 49 seconds earlier than expected • Communication was never reestablished • The spacecra disintegrated due to atmospheric stresses
ACCU 2019 | Implementing a Physical Units Library for C++ 6 What went wrong?
ACCU 2019 | Implementing a Physical Units Library for C++ 7 What went wrong?
• The primary cause of this discrepancy was that – one piece of ground so ware supplied by Lockheed Martin produced results in a United States customary unit, contrary to its So ware Interface Specification (SIS) – second system, supplied by NASA, expected those results to be in SI units, in accordance with the SIS
ACCU 2019 | Implementing a Physical Units Library for C++ 7 What went wrong?
• The primary cause of this discrepancy was that – one piece of ground so ware supplied by Lockheed Martin produced results in a United States customary unit, contrary to its So ware Interface Specification (SIS) – second system, supplied by NASA, expected those results to be in SI units, in accordance with the SIS • Specifically – so ware that calculated the total impulse produced by thruster firings calculated results in pound- seconds – the trajectory calculation so ware then used these results to update the predicted position of the spacecra and expected it to be in newton-seconds
ACCU 2019 | Implementing a Physical Units Library for C++ 7
Human error occurs all the time
Human error occurs all the time. But even so we have a tremendous success rate because we have systems that detect and correct the errors. The problem here is that our system failed to do that. -- Carl Pilcher science director at NASA
ACCU 2019 | Implementing a Physical Units Library for C++ 9 ANOTHER EXAMPLE
Why do I care? A long time ago in a galaxy far far away...
ACCU 2019 | Implementing a Physical Units Library for C++ 11 A long time ago in a galaxy far far away...
ACCU 2019 | Implementing a Physical Units Library for C++ 11 Tactical Flight Computer
ACCU 2019 | Implementing a Physical Units Library for C++ 12 Tactical Flight Computer
ACCU 2019 | Implementing a Physical Units Library for C++ 13 What is the correct order?
void DistanceBearing(double lat1, double lon1, double lat2, double lon2, double *Distance, double *Bearing);
ACCU 2019 | Implementing a Physical Units Library for C++ 14 What is the correct order?
void DistanceBearing(double lat1, double lon1, double lat2, double lon2, double *Distance, double *Bearing);
void FindLatitudeLongitude(double Lat, double Lon, double Bearing, double Distance, double *lat_out, double *lon_out);
ACCU 2019 | Implementing a Physical Units Library for C++ 14 What is the correct order?
void DistanceBearing(double lat1, double lon1, double lat2, double lon2, double *Distance, double *Bearing);
void FindLatitudeLongitude(double Lat, double Lon, double Bearing, double Distance, double *lat_out, double *lon_out);
ACCU 2019 | Implementing a Physical Units Library for C++ 14 double - an ultimate type to express quantity
double GlidePolar::MacCreadyAltitude(double emcready, double Distance, const double Bearing, const double WindSpeed, const double WindBearing, double *BestCruiseTrack, double *VMacCready, const bool isFinalGlide, double *TimeToGo, const double AltitudeAboveTarget, const double cruise_efficiency, const double TaskAltDiff);
ACCU 2019 | Implementing a Physical Units Library for C++ 15 We shouldn't write the code like that anymore
// Air Density(kg/m3) from relative humidity(%), // temperature(°C) and absolute pressure(Pa) double AirDensity(double hr, double temp, double abs_press) { return (1/(287.06*(temp+273.15))) * (abs_press - 230.617 * hr * exp((17.5043*temp)/(241.2+temp))); }
ACCU 2019 | Implementing a Physical Units Library for C++ 16 DID YOU EVER HAVE TO WRITE THE CODE THIS WAY?
ACCU 2019 | Implementing a Physical Units Library for C++ 17 Why do we write our code this way?
ACCU 2019 | Implementing a Physical Units Library for C++ 18 Why do we write our code this way?
• No support in the C++ Standard Library – std::chrono helped a lot for time and duration – date support comes in C++20 – still not enough for full dimensional analysis
ACCU 2019 | Implementing a Physical Units Library for C++ 18 Why do we write our code this way?
• No support in the C++ Standard Library – std::chrono helped a lot for time and duration – date support comes in C++20 – still not enough for full dimensional analysis • Lack of good alternatives – poor user experience (i.e. compilation errors) – heavy dependencies (i.e. Boost.Units) – custom 3rd party libraries o en not allowed in production code
ACCU 2019 | Implementing a Physical Units Library for C++ 18 Why do we write our code this way?
• No support in the C++ Standard Library – std::chrono helped a lot for time and duration – date support comes in C++20 – still not enough for full dimensional analysis • Lack of good alternatives – poor user experience (i.e. compilation errors) – heavy dependencies (i.e. Boost.Units) – custom 3rd party libraries o en not allowed in production code • Implementing a good library by ourselves is hard
ACCU 2019 | Implementing a Physical Units Library for C++ 18 Why do we write our code this way?
• No support in the C++ Standard Library – std::chrono helped a lot for time and duration – date support comes in C++20 – still not enough for full dimensional analysis • Lack of good alternatives – poor user experience (i.e. compilation errors) – heavy dependencies (i.e. Boost.Units) – custom 3rd party libraries o en not allowed in production code • Implementing a good library by ourselves is hard
Let's do something about that!
ACCU 2019 | Implementing a Physical Units Library for C++ 18 TERMS AND DEFINITIONS
ACCU 2019 | Implementing a Physical Units Library for C++ 19 International System of Units (SI)
• 7 base units • 22 named units • 20 prefixes to the unit names and unit symbols
ACCU 2019 | Implementing a Physical Units Library for C++ 20 SI Base Units
QUANTITY DIMENSION SYMBOL UNIT SYMBOL UNIT NAME
time T s second
length L m metre
mass M kg kilogram
electric current I A ampere
thermodynamic temperature Θ K kelvin
amount of substance N mol mole
luminous intensity J cd candela
ACCU 2019 | Implementing a Physical Units Library for C++ 21 Examples of SI derived units expressed in SI Based Units
QUANTITY DIMENSION SYMBOL UNIT SYMBOL UNIT NAME
area A m2 square metre
volume V m3 cubic metre
−1 velocity v m⋅ s metre per second
−2 acceleration a m⋅ s metre per second squared
−3 density ρ kg⋅ m kilogram per cubic metre
−1 magnetic field strength H A⋅ m ampere per metre
−2 luminance Lv cd⋅ m candela per square metre
ACCU 2019 | Implementing a Physical Units Library for C++ 22 Examples of SI derived units with special name
QUANTITY UNIT SYMBOL UNIT NAME IN OTHER SI UNITS IN SI BASE UNITS
frequency Hz hertz --- s-1
-2 force N newton --- kg⋅ m⋅ s
2 −1 −2 preassure Pa pascal N/m kg⋅ m ⋅ s
2 −2 ⋅ energy J joule N m kg⋅ m ⋅ s
2 −3 power W watt J/s kg⋅ m ⋅ s
electric charge C coulomb --- s⋅ A
2 −3 −1 voltage V volt W/A kg⋅ m ⋅ s ⋅ A
−1 −2 4 2 capacitance F farad C/V kg ⋅ m ⋅ s ⋅ A
2 −3 −2 resistance Ω ohm V/A kg⋅ m ⋅ s ⋅ A
ACCU 2019 | Implementing a Physical Units Library for C++ 23 Dimensional Analysis
Power = Energy / Time
ACCU 2019 | Implementing a Physical Units Library for C++ 24 Dimensional Analysis
Power = Energy / Time
• W
ACCU 2019 | Implementing a Physical Units Library for C++ 24 Dimensional Analysis
Power = Energy / Time
• W • J/s
ACCU 2019 | Implementing a Physical Units Library for C++ 24 Dimensional Analysis
Power = Energy / Time
• W • J/s
• N⋅ m/s −2 • kg⋅ m⋅ s ⋅ m/s 2 −2 • kg⋅ m ⋅ s /s 2 −3 • kg⋅ m ⋅ s
ACCU 2019 | Implementing a Physical Units Library for C++ 24 Dimensional Analysis
// simple numeric operations static_assert(10_km / 2 == 5_km);
ACCU 2019 | Implementing a Physical Units Library for C++ 25 Dimensional Analysis
// 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);
ACCU 2019 | Implementing a Physical Units Library for C++ 25 Dimensional Analysis
// 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);
// dimension conversions static_assert(1_km / 1_s == 1000_mps); static_assert(2_kmph * 2_h == 4_km); static_assert(2_km / 2_kmph == 1_h); static_assert(1000 / 1_s == 1_kHz); static_assert(10_km / 5_km == 2);
ACCU 2019 | Implementing a Physical Units Library for C++ 25 SI pre xes
template
ACCU 2019 | Implementing a Physical Units Library for C++ 26 SI pre xes
template
typedef ratio<1, 1000000000000000000> atto; typedef ratio<1, 1000000000000000> femto; typedef ratio<1, 1000000000000> pico; typedef ratio<1, 1000000000> nano; typedef ratio<1, 1000000> micro; typedef ratio<1, 1000> milli; typedef ratio<1, 100> centi; typedef ratio<1, 10> deci; typedef ratio< 10, 1> deca; typedef ratio< 100, 1> hecto; typedef ratio< 1000, 1> kilo; typedef ratio< 1000000, 1> mega; typedef ratio< 1000000000, 1> giga; typedef ratio< 1000000000000, 1> tera; typedef ratio< 1000000000000000, 1> peta; typedef ratio< 1000000000000000000, 1> exa;
ACCU 2019 | Implementing a Physical Units Library for C++ 26 More than one system of measurement
• United States customary units • Imperial units • ...
ACCU 2019 | Implementing a Physical Units Library for C++ 27 After Boost.Units
BASE DIMENSION • measurable entity of interest • essentially a tag type and provide no dimensional analysis functionality by itself • i.e. length [L], mass [M], time [T], etc.
ACCU 2019 | Implementing a Physical Units Library for C++ 28 After Boost.Units
BASE DIMENSION • measurable entity of interest • essentially a tag type and provide no dimensional analysis functionality by itself • i.e. length [L], mass [M], time [T], etc.
DIMENSION • a collection of zero or more base dimensions • each potentially raised to a di erent rational power • i.e. length = [L]1, area = [L]2, velocity = [L]1/[T]1, etc.
ACCU 2019 | Implementing a Physical Units Library for C++ 28 After Boost.Units
BASE UNIT • a specific measure of a dimension • conversions are defined using base units • i.e. [L] -> m (meter)
ACCU 2019 | Implementing a Physical Units Library for C++ 29 After Boost.Units
BASE UNIT • a specific measure of a dimension • conversions are defined using base units • i.e. [L] -> m (meter)
UNIT • a set of base units raised to rational exponents • i.e. m1, kg1, m1/s2, etc.
ACCU 2019 | Implementing a Physical Units Library for C++ 29 After Boost.Units
SYSTEM • a collection of base units representing all the measurable entities of interest for a specific problem
ACCU 2019 | Implementing a Physical Units Library for C++ 30 After Boost.Units
SYSTEM • a collection of base units representing all the measurable entities of interest for a specific problem
QUANTITY • a concrete amount of a unit • i.e. 10 meters
ACCU 2019 | Implementing a Physical Units Library for C++ 30 CURRENT STATE REVIEW OF EXISTING SOLUTIONS
ACCU 2019 | Implementing a Physical Units Library for C++ 31 Toy example
/* velocity */ avg_speed(/* length */ distance, /* time */ duration) { return distance / duration; }
ACCU 2019 | Implementing a Physical Units Library for C++ 32 Toy example
/* velocity */ avg_speed(/* length */ distance, /* time */ duration) { return distance / duration; }
const auto kmph = avg_speed(/* 220 km */, /* 2 hours */); std::cout << /* kmph */ << " km/h\n";
ACCU 2019 | Implementing a Physical Units Library for C++ 32 Toy example
/* velocity */ avg_speed(/* length */ distance, /* time */ duration) { return distance / duration; }
const auto kmph = avg_speed(/* 220 km */, /* 2 hours */); std::cout << /* kmph */ << " km/h\n";
const auto mph = avg_speed(/* 140 miles */, /* 2 hours */); std::cout << /* mph */ << " mph\n";
ACCU 2019 | Implementing a Physical Units Library for C++ 32 Toy example
/* velocity */ avg_speed(/* length */ distance, /* time */ duration) { return distance / duration; }
const auto kmph = avg_speed(/* 220 km */, /* 2 hours */); std::cout << /* kmph */ << " km/h\n";
const auto mph = avg_speed(/* 140 miles */, /* 2 hours */); std::cout << /* mph */ << " mph\n";
• Compile time safety to make sure that the result is of a correct dimension
ACCU 2019 | Implementing a Physical Units Library for C++ 32 Toy example
/* velocity */ avg_speed(/* length */ distance, /* time */ duration) { return distance / duration; }
const auto kmph = avg_speed(/* 220 km */, /* 2 hours */); std::cout << /* kmph */ << " km/h\n";
const auto mph = avg_speed(/* 140 miles */, /* 2 hours */); std::cout << /* mph */ << " mph\n";
• Compile time safety to make sure that the result is of a correct dimension • Support for multiple units and unit prefixes
ACCU 2019 | Implementing a Physical Units Library for C++ 32 Toy example
/* velocity */ avg_speed(/* length */ distance, /* time */ duration) { return distance / duration; }
const auto kmph = avg_speed(/* 220 km */, /* 2 hours */); std::cout << /* kmph */ << " km/h\n";
const auto mph = avg_speed(/* 140 miles */, /* 2 hours */); std::cout << /* mph */ << " mph\n";
• Compile time safety to make sure that the result is of a correct dimension • Support for multiple units and unit prefixes • No runtime overhead
ACCU 2019 | Implementing a Physical Units Library for C++ 32 Toy example
/* velocity */ avg_speed(/* length */ distance, /* time */ duration) { return distance / duration; }
const auto kmph = avg_speed(/* 220 km */, /* 2 hours */); std::cout << /* kmph */ << " km/h\n";
const auto mph = avg_speed(/* 140 miles */, /* 2 hours */); std::cout << /* mph */ << " mph\n";
• Compile time safety to make sure that the result is of a correct dimension • Support for multiple units and unit prefixes • No runtime overhead • I/O output is out-of-scope for now (waiting for std::format())
ACCU 2019 | Implementing a Physical Units Library for C++ 32 Existing solutions
• Boost.Units – authors: Matthias C. Schabel, Steven Watanabe – https://www.boost.org/doc/libs/1_69_0/doc/html/boost_units.html
ACCU 2019 | Implementing a Physical Units Library for C++ 33 Existing solutions
• Boost.Units – authors: Matthias C. Schabel, Steven Watanabe – https://www.boost.org/doc/libs/1_69_0/doc/html/boost_units.html • Units – author: Nic Holthaus – https://github.com/nholthaus/units
ACCU 2019 | Implementing a Physical Units Library for C++ 33 Existing solutions
• Boost.Units – authors: Matthias C. Schabel, Steven Watanabe – https://www.boost.org/doc/libs/1_69_0/doc/html/boost_units.html • Units – author: Nic Holthaus – https://github.com/nholthaus/units • std::chrono – author: Howard Hinnant
ACCU 2019 | Implementing a Physical Units Library for C++ 33 Boost.Units: Toy example
#include
ACCU 2019 | Implementing a Physical Units Library for C++ 34 Boost.Units: Toy example
#include
namespace bu = boost::units;
ACCU 2019 | Implementing a Physical Units Library for C++ 34 Boost.Units: Toy example
#include
namespace bu = boost::units;
using kilometer_base_unit = bu::make_scaled_unit
ACCU 2019 | Implementing a Physical Units Library for C++ 34 Boost.Units: Toy example
#include
namespace bu = boost::units;
using kilometer_base_unit = bu::make_scaled_unit
using length_mile = bu::us::mile_base_unit::unit_type; BOOST_UNITS_STATIC_CONSTANT(miles, length_mile);
ACCU 2019 | Implementing a Physical Units Library for C++ 34 Boost.Units: Toy example
#include
namespace bu = boost::units;
using kilometer_base_unit = bu::make_scaled_unit
using length_mile = bu::us::mile_base_unit::unit_type; BOOST_UNITS_STATIC_CONSTANT(miles, length_mile);
using time_hour = bu::metric::hour_base_unit::unit_type; BOOST_UNITS_STATIC_CONSTANT(hours, time_hour);
ACCU 2019 | Implementing a Physical Units Library for C++ 34 Boost.Units: Toy example
constexpr bu::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 35 Boost.Units: Toy example
constexpr bu::quantity
const auto v = avg_speed(220 * bu::si::kilo * bu::si::meters, 2 * hours); using kilometers_per_hour = bu::divide_typeof_helper
ACCU 2019 | Implementing a Physical Units Library for C++ 35 Boost.Units: Toy example
constexpr bu::quantity
const auto v = avg_speed(220 * bu::si::kilo * bu::si::meters, 2 * hours); using kilometers_per_hour = bu::divide_typeof_helper
const auto v = avg_speed(140 * miles, 2 * hours); using miles_per_hour = bu::divide_typeof_helper
ACCU 2019 | Implementing a Physical Units Library for C++ 35 Boost.Units: Toy example
constexpr bu::quantity
const auto v = avg_speed(220 * bu::si::kilo * bu::si::meters, 2 * hours); using kilometers_per_hour = bu::divide_typeof_helper
const auto v = avg_speed(140 * miles, 2 * hours); using miles_per_hour = bu::divide_typeof_helper
Works, but runtime does unnecessary operations, and I may loose some bits of information while doing that
ACCU 2019 | Implementing a Physical Units Library for C++ 35 Boost.Units: Toy example
• Too generic
template
ACCU 2019 | Implementing a Physical Units Library for C++ 36 Boost.Units: Toy example
• Too generic
template
• Is it really a velocity dimension?
template
ACCU 2019 | Implementing a Physical Units Library for C++ 36 Boost.Units: Toy example
• Too generic
template
• Is it really a velocity dimension?
template
• Manually repeats built-in dimensional analysis logic
template
ACCU 2019 | Implementing a Physical Units Library for C++ 36 Boost.Units: Toy example
template
ACCU 2019 | Implementing a Physical Units Library for C++ 37 Boost.Units: Toy example
template
const auto kmph = avg_speed(220 * bu::si::kilo * bu::si::meters, 2 * hours); std::cout << kmph.value() << " km/h\n";
ACCU 2019 | Implementing a Physical Units Library for C++ 37 Boost.Units: Toy example
template
const auto kmph = avg_speed(220 * bu::si::kilo * bu::si::meters, 2 * hours); std::cout << kmph.value() << " km/h\n";
const auto mph = avg_speed(140 * miles, 2 * hours); std::cout << mph.value() << " mph\n";
ACCU 2019 | Implementing a Physical Units Library for C++ 37 Boost.Units: Toy example
template
bu::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 38 Boost.Units: Toy example
template
bu::quantity
bu::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 38 Boost.Units: Summary
PROS • The widest adoption thanks to Boost • A wide range of systems and base units • High flexibility and extensibility • constexpr usage helps in compile-time • quantity can use any number-like type for its representation
ACCU 2019 | Implementing a Physical Units Library for C++ 39 Boost.Units: Summary
PROS CONS • The widest adoption thanks to Boost • Pre-C++11 design • A wide range of systems and base units • Heavily relies on macros and Boost.MPL • High flexibility and extensibility • Domain and C++ experts only • constexpr usage helps in compile-time – poor compile-time error messages • quantity can use any number-like type for its – no easy way to use non-SI units representation – spread over too many small headers (hard to compile a simple program) – designed around custom unit systems • Not possible to explicitly construct a quantity of known unit from a plain value (even if no truncation occurs)
ACCU 2019 | Implementing a Physical Units Library for C++ 39 Units: Toy example
#include "units.h"
using namespace units::literals;
ACCU 2019 | Implementing a Physical Units Library for C++ 40 Units: Toy example
#include "units.h"
using namespace units::literals;
template
const auto v = d / t;
return v; }
ACCU 2019 | Implementing a Physical Units Library for C++ 40 Units: Toy example
#include "units.h"
using namespace units::literals;
template
ACCU 2019 | Implementing a Physical Units Library for C++ 40 Units: Toy example
#include "units.h"
using namespace units::literals;
template
• Not possible to define template arguments that will provide proper overload resolution because of unit nesting
using meter_t = units::unit_t
ACCU 2019 | Implementing a Physical Units Library for C++ 40 Units: Toy example
template
ACCU 2019 | Implementing a Physical Units Library for C++ 41 Units: Toy example
template
const auto kmph = avg_speed(220_km, 2_hr); std::cout << kmph.value() << " km/h\n";
ACCU 2019 | Implementing a Physical Units Library for C++ 41 Units: Toy example
template
const auto kmph = avg_speed(220_km, 2_hr); std::cout << kmph.value() << " km/h\n";
const auto mph = avg_speed(140_mi, 2_hr); std::cout << mph.value() << " mph\n";
ACCU 2019 | Implementing a Physical Units Library for C++ 41 Units: Toy example
template
const auto kmph = avg_speed(units::length::kilometer_t(220), units::time::hour_t(2)); std::cout << kmph.value() << " km/h\n";
const auto mph = avg_speed(units::length::mile_t(140), units::time::hour_t(2)); std::cout << mph.value() << " mph\n";
ACCU 2019 | Implementing a Physical Units Library for C++ 42 Units: Toy example
template
units::length::kilometer_t d(220); units::time::hour_t t(2); const auto kmph = avg_speed(d, t); std::cout << kmph.value() << " km/h\n";
units::length::mile_t d(140); units::time::hour_t t(2); const auto mph = avg_speed(d, t); std::cout << mph.value() << " mph\n";
ACCU 2019 | Implementing a Physical Units Library for C++ 43 Units: Toy example
template
units::length::kilometer_t d(220); units::time::hour_t t(2); const auto kmph = avg_speed(d, t); std::cout << kmph.value() << " km/h\n";
units::length::mile_t d(140); units::time::hour_t t(2); const auto mph = avg_speed(d, t); std::cout << mph.value() << " mph\n";
meter is a unit not a quantity! -- Walter Brown
ACCU 2019 | Implementing a Physical Units Library for C++ 43 Units: Summary
PROS • Single header file units.h • The conversions between units are defined as ratios at compile time • UDL support
ACCU 2019 | Implementing a Physical Units Library for C++ 44 Units: Summary
PROS CONS • Single header file units.h • Not possible to extend with own base units • The conversions between units are defined as • Poor compile-time error messages ratios at compile time • No types that represent dimensions (units only) • UDL support • Mixing quantities with units • Not easily suitable for generic programming
ACCU 2019 | Implementing a Physical Units Library for C++ 44 ISSUES WITH CURRENT SOLUTIONS
ACCU 2019 | Implementing a Physical Units Library for C++ 45 User experience: Compilation: Boost.Units
bu::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 46 User experience: Compilation: Boost.Units
bu::quantity
GCC-8 error: conversion from ‘quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 46 User experience: Compilation: Boost.Units
bu::quantity
CLANG-7 error: no viable conversion from 'quantity >, dimensionless_type>, list
ACCU 2019 | Implementing a Physical Units Library for C++ 47 User experience: Compilation: Boost.Units
bu::quantity
CLANG-7 error: no viable conversion from 'quantity >, dimensionless_type>, list
Can you guess what is wrong here?
ACCU 2019 | Implementing a Physical Units Library for C++ 47 User experience: Compilation: Boost.Units
bu::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 48 User experience: Compilation: Boost.Units
constexpr bu::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 49 User experience: Compilation: Boost.Units
constexpr bu::quantity
GCC-8 error: could not convert ‘boost::units::operator*(const boost::units::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 49 User experience: Compilation: Boost.Units
constexpr bu::quantity
GCC-8 (CONTINUED) ... boost::units::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 50 User experience: Compilation: Boost.Units
constexpr bu::quantity
CLANG-7 error: no viable conversion from returned value of type 'quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 51 User experience: Compilation: Boost.Units
constexpr bu::quantity
CLANG-7 error: no viable conversion from returned value of type 'quantity
Sometimes shorter error message is not necessary better ;-)
ACCU 2019 | Implementing a Physical Units Library for C++ 51 User experience: Compilation: Units
template
ACCU 2019 | Implementing a Physical Units Library for C++ 52 User experience: Compilation: Units
template
GCC-8 error: static assertion failed: Units are not compatible. static_assert(traits::is_convertible_unit
ACCU 2019 | Implementing a Physical Units Library for C++ 52 User experience: Compilation: Units
template
GCC-8 error: static assertion failed: Units are not compatible. static_assert(traits::is_convertible_unit
static_assert's are o en not the best solution • do not influence the overload resolution process • for some compilers do not provide enough context
ACCU 2019 | Implementing a Physical Units Library for C++ 52 User experience: Compilation: Units
template
CLANG-7 error: static_assert failed due to requirement 'traits::is_convertible_unit
ACCU 2019 | Implementing a Physical Units Library for C++ 53 User experience: Debugging: Boost.Units
ACCU 2019 | Implementing a Physical Units Library for C++ 54 User experience: Debugging: Boost.Units
ACCU 2019 | Implementing a Physical Units Library for C++ 54 User experience: Debugging: Boost.Units
Breakpoint 1, (anonymous namespace)::avg_speed
ACCU 2019 | Implementing a Physical Units Library for C++ 55 User experience: Debugging: Boost.Units
(gdb) ptype d type = class boost::units::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 56 User experience: Debugging: Units
ACCU 2019 | Implementing a Physical Units Library for C++ 57 User experience: Debugging: Units
ACCU 2019 | Implementing a Physical Units Library for C++ 57 User experience: Debugging: Units
Breakpoint 1, (anonymous namespace)::avg_speed
ACCU 2019 | Implementing a Physical Units Library for C++ 58 User experience: Debugging: Units
(gdb) ptype d type = class units::unit_t
ACCU 2019 | Implementing a Physical Units Library for C++ 59 Macros omnipresence: Boost.Units
BOOST_UNITS_DEFINE_CONVERSION_FACTOR(foot_base_unit, meter_base_unit, double, 0.3048);
BOOST_UNITS_DEFINE_CONVERSION_OFFSET(celsius_base_unit, fahrenheit_base_unit, double, 32.0);
BOOST_UNITS_DEFAULT_CONVERSION(my_unit_tag, SI::force);
BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE((long N1)(long N2), currency_base_unit
ACCU 2019 | Implementing a Physical Units Library for C++ 60 Macros omnipresence: Units
#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_LENGTH_UNITS) UNIT_ADD_WITH_METRIC_PREFIXES(length, meter, meters, m, unit
UNIT_ADD_CATEGORY_TRAIT(length) #endif
ACCU 2019 | Implementing a Physical Units Library for C++ 61 Extensibility
• Adding derived dimensions is pretty easy in all the libraries • Adding base dimensions is hard or nearly impossible
ACCU 2019 | Implementing a Physical Units Library for C++ 62 Extensibility
• Adding derived dimensions is pretty easy in all the libraries • Adding base dimensions is hard or nearly impossible
BOOST.UNITS
struct length_base_dimension : base_dimension
• Order is completely arbitrary as long as each tag has a unique enumerable value • Non-unique ordinals are flagged as errors at compile-time • Negative ordinals are reserved for use by the library • Two independent libraries can easily choose the same ordinal (i.e. 1)
ACCU 2019 | Implementing a Physical Units Library for C++ 62 Extensibility
• Adding derived dimensions is pretty easy in all the libraries • Adding base dimensions is hard or nearly impossible
UNITS
template
• Requires refactoring the engine, all existing predefined and users' unit types
ACCU 2019 | Implementing a Physical Units Library for C++ 63 MY UNITS LIBRARY (WIP!!!) HTTPS://GITHUB.COM/MPUSZ/UNITS
ACCU 2019 | Implementing a Physical Units Library for C++ 64 Requirements
• Safety and performance – strong types – template metaprogramming – constexpr all the things
ACCU 2019 | Implementing a Physical Units Library for C++ 65 Requirements
• Safety and performance – strong types – template metaprogramming – constexpr all the things • The best possible user experience – compiler errors – debugging
ACCU 2019 | Implementing a Physical Units Library for C++ 65 Requirements
• Safety and performance – strong types – template metaprogramming – constexpr all the things • The best possible user experience – compiler errors – debugging • No macros in the user interface • No external dependencies • Easy extensibility
ACCU 2019 | Implementing a Physical Units Library for C++ 65 Requirements
• Safety and performance – strong types – template metaprogramming – constexpr all the things • The best possible user experience – compiler errors – debugging • No macros in the user interface • No external dependencies • Easy extensibility • Possibility to be standardized as a freestanding part of the C++ Standard Library
ACCU 2019 | Implementing a Physical Units Library for C++ 65 Dimensions
• units::dimension - a type-list-like type that stores an ordered list of exponents of one or more base dimensions
template
ACCU 2019 | Implementing a Physical Units Library for C++ 66 Dimensions
• units::dimension - a type-list-like type that stores an ordered list of exponents of one or more base dimensions
template
• units::exp - a base dimension and its exponent in a derived dimension
template
ACCU 2019 | Implementing a Physical Units Library for C++ 66 Dimensions
• BaseDimension is a unique sortable compile-time value
ACCU 2019 | Implementing a Physical Units Library for C++ 67 Dimensions
• BaseDimension is a unique sortable compile-time value
template
ACCU 2019 | Implementing a Physical Units Library for C++ 67 Dimensions
• BaseDimension is a unique sortable compile-time value
template
EXAMPLE
struct base_dim_length : dim_id<0> {}; struct base_dim_mass : dim_id<1> {}; struct base_dim_time : dim_id<2> {};
ACCU 2019 | Implementing a Physical Units Library for C++ 67 Dimensions
• BaseDimension is a unique sortable compile-time value
template
EXAMPLE
struct base_dim_length : dim_id<0> {}; struct base_dim_mass : dim_id<1> {}; struct base_dim_time : dim_id<2> {};
The same problem with extensibility as with Boost.Units. If two users will select the same ID for their types than we have problems
ACCU 2019 | Implementing a Physical Units Library for C++ 67 P0732 Class Types in Non-Type Template Parameters
• Allow non-union class types to appear in non-type template parameters • Require that types used as such, and all of their bases and non-static data members recursively, have a non-user-provided operator<=> returning a type that is implicitly convertible to std::strong_equality, and contain no references
ACCU 2019 | Implementing a Physical Units Library for C++ 68 P0732 Class Types in Non-Type Template Parameters
• Allow non-union class types to appear in non-type template parameters • Require that types used as such, and all of their bases and non-static data members recursively, have a non-user-provided operator<=> returning a type that is implicitly convertible to std::strong_equality, and contain no references
template
ACCU 2019 | Implementing a Physical Units Library for C++ 68 C++20 Exponent and Base Dimension
• base_dimension can be either directly fixed_string or a type that will include additional information (i.e. user's namespace name)
using base_dimension = fixed_string;
ACCU 2019 | Implementing a Physical Units Library for C++ 69 C++20 Exponent and Base Dimension
• base_dimension can be either directly fixed_string or a type that will include additional information (i.e. user's namespace name)
using base_dimension = fixed_string;
• exp with C++20 support
template
ACCU 2019 | Implementing a Physical Units Library for C++ 69 C++20 Exponent and Base Dimension
• base_dimension can be either directly fixed_string or a type that will include additional information (i.e. user's namespace name)
using base_dimension = fixed_string;
• exp with C++20 support
template
EXAMPLE
inline constexpr base_dimension base_dim_length("length"); inline constexpr base_dimension base_dim_time("time");
ACCU 2019 | Implementing a Physical Units Library for C++ 69 C++20 Exponent and Base Dimension
• base_dimension can be either directly fixed_string or a type that will include additional information (i.e. user's namespace name)
using base_dimension = fixed_string;
• exp with C++20 support
template
EXAMPLEMuch easier to extend the library with new base dimension without identifier
inlinecollisions constexpr between base_dimension vendors base_dim_length("length"); inline constexpr base_dimension base_dim_time("time");
ACCU 2019 | Implementing a Physical Units Library for C++ 69 Dimensions
• We can express velocity in the following way
dimension
– improves user experience – as short as possible template instantiations – easy to understand by every engineer
ACCU 2019 | Implementing a Physical Units Library for C++ 70 Dimensions
• We can express velocity in the following way
dimension
– improves user experience – as short as possible template instantiations – easy to understand by every engineer
PROBLEM • The same type expected for both operations
constexpr auto v1 = 1_m / 1_s; constexpr auto v2 = 2 / 2_s * 1_m; static_assert(std::is_same
ACCU 2019 | Implementing a Physical Units Library for C++ 70 Dimensions: make_dimension factory helper
template
• Provides unique ordering for contained base dimensions • Aggregates two arguments of the same base dimension but di erent exponents • Eliminates two arguments of the same base dimension and with opposite equal exponents
ACCU 2019 | Implementing a Physical Units Library for C++ 71 Dimensions: make_dimension factory helper
template
• Provides unique ordering for contained base dimensions • Aggregates two arguments of the same base dimension but di erent exponents • Eliminates two arguments of the same base dimension and with opposite equal exponents
EXAMPLE • To form a velocity
make_dimension_t
ACCU 2019 | Implementing a Physical Units Library for C++ 71 Units
• unit - the unit of a specific physical dimension
template
ACCU 2019 | Implementing a Physical Units Library for C++ 72 Units
• unit - the unit of a specific physical dimension
template
EXAMPLE To express meter
unit
ACCU 2019 | Implementing a Physical Units Library for C++ 72 Quantities
• quantity - the amount of a specific dimension expressed in a specific unit of that dimension
template
ACCU 2019 | Implementing a Physical Units Library for C++ 73 Quantities
• quantity - the amount of a specific dimension expressed in a specific unit of that dimension
template
• Interface similar to std::chrono::duration + additional member functions – multiplication of 2 quantities with di erent dimensions
1_kmph * 1_h == 1_km
– division of 2 quantities of di erent dimensions
1_km / 1_h == 1_kmph
– division of a scalar with a quantity
1 / 1_s == 1_Hz
ACCU 2019 | Implementing a Physical Units Library for C++ 73 Quantities
• quantity - the amount of a specific dimension expressed in a specific unit of that dimension
template
• Interface similar to std::chrono::duration + additional member functions – quantity value equal to 1 expressed in a specific Rep
[[nodiscard]] static constexpr quantity one() noexcept;
ACCU 2019 | Implementing a Physical Units Library for C++ 74 Quantities
• quantity - the amount of a specific dimension expressed in a specific unit of that dimension
template
EXAMPLE
template
ACCU 2019 | Implementing a Physical Units Library for C++ 75 Struggling with the user experience
1 Generic programming
2 Compile-time errors
3 Debugging
ACCU 2019 | Implementing a Physical Units Library for C++ 76 Do you remember that?
BOOST.UNITS • Is it really a velocity dimension?
template
UNITS
template
• Not possible to define template arguments that will provide proper overload resolution
ACCU 2019 | Implementing a Physical Units Library for C++ 77 C++ Concepts to the rescue
BOOST.UNITS
#include
ACCU 2019 | Implementing a Physical Units Library for C++ 78 C++ Concepts to the rescue
BOOST.UNITS
#include
template
ACCU 2019 | Implementing a Physical Units Library for C++ 78 C++ Concepts to the rescue
BOOST.UNITS
#include
template
constexpr Velocity auto avg_speed(Length auto d, Time auto t) { return d / t; }
ACCU 2019 | Implementing a Physical Units Library for C++ 78 C++ Concepts to the rescue
UNITS
template
ACCU 2019 | Implementing a Physical Units Library for C++ 79 C++ Concepts to the rescue
UNITS
template
constexpr Velocity auto avg_speed(Length auto d, Time auto t) { return d / t; }
ACCU 2019 | Implementing a Physical Units Library for C++ 79 C++ Concepts to the rescue
UNITS
template
constexpr Velocity auto avg_speed(Length auto d, Time auto t) { return d / t; }
Concepts can be used in places where regular template argument deduction does not work (i.e. return types, class template parameters, etc).
ACCU 2019 | Implementing a Physical Units Library for C++ 79 I lied a bit ;-)
All template types are heavily embraced with concepts
ACCU 2019 | Implementing a Physical Units Library for C++ 80 I lied a bit ;-)
All template types are heavily embraced with concepts
UNITS ENGINE CONCEPTS • TypeList • Number • Ratio • Exponent • Dimension • Unit • Quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 80 I lied a bit ;-)
All template types are heavily embraced with concepts
UNITS ENGINE CONCEPTS PREDEFINED QUANTITIES CONCEPTS • TypeList • Length • Number • Time • Ratio • Frequency • Exponent • Velocity • Dimension • ...
• Unit template
ACCU 2019 | Implementing a Physical Units Library for C++ 80 Type aliases are great (but not for users)
• Velocity is one of the simplest derived dimensions one can imagine
using velocity = make_dimension_t
ACCU 2019 | Implementing a Physical Units Library for C++ 81 Type aliases are great (but not for users)
• Velocity is one of the simplest derived dimensions one can imagine
using velocity = make_dimension_t
• Type aliases names are lost quickly during compilation process
ACCU 2019 | Implementing a Physical Units Library for C++ 81 Type aliases are great (but not for users)
• Velocity is one of the simplest derived dimensions one can imagine
using velocity = make_dimension_t
• Type aliases names are lost quickly during compilation process • As a result user gets huge types in error messages
[with D = units::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 81 Type aliases are great (but not for users)
• Velocity is one of the simplest derived dimensions one can imagine
using velocity = make_dimension_t
• Type aliases names are lost quickly during compilation process • As a result user gets huge types in error messages
[with D = units::quantity
It is a pity that we still do not have strong typedef's in the C++ language :-(
ACCU 2019 | Implementing a Physical Units Library for C++ 81 Inheritance to the rescue
struct dimension_velocity : make_dimension_t
• We get strong types that do not vanish during compilation process
ACCU 2019 | Implementing a Physical Units Library for C++ 82 Inheritance to the rescue
struct dimension_velocity : make_dimension_t
• We get strong types that do not vanish during compilation process • Easily applicable only to simple classes because of problems with – constructors – assignment operators – comparison operators – ...
ACCU 2019 | Implementing a Physical Units Library for C++ 82 Inheritance to the rescue
struct dimension_velocity : make_dimension_t
• We get strong types that do not vanish during compilation process • Easily applicable only to simple classes because of problems with – constructors – assignment operators – comparison operators – ... • CRTP could help but it complicates the design
ACCU 2019 | Implementing a Physical Units Library for C++ 82 Inheritance to the rescue
struct dimension_velocity : make_dimension_t
• We get strong types that do not vanish during compilation process • Easily applicable only to simple classes because of problems with – constructors – assignment operators – comparison operators – ... • CRTP could help but it complicates the design • Anyway velocity should be considered a helper alias for quantity rather than a strong type
template
ACCU 2019 | Implementing a Physical Units Library for C++ 82 Upcasting problem
struct dimension_velocity : make_dimension_t
Velocity auto v = 10_m / 2_s;
ACCU 2019 | Implementing a Physical Units Library for C++ 83 Upcasting problem
struct dimension_velocity : make_dimension_t
Velocity auto v = 10_m / 2_s;
How to form dimension_velocity class from division of dimension_length by dimension_time?
ACCU 2019 | Implementing a Physical Units Library for C++ 83 P0887 The identity metafunction
template
ACCU 2019 | Implementing a Physical Units Library for C++ 84 Upcasting facility
BASE CLASS
template
template
ACCU 2019 | Implementing a Physical Units Library for C++ 85 Upcasting facility
BASE CLASS
template
template
HELPER ALIASES
template
ACCU 2019 | Implementing a Physical Units Library for C++ 85 Upcasting facility
UPCASTING TRAITS
template
ACCU 2019 | Implementing a Physical Units Library for C++ 86 Upcasting facility
template
struct dimension_velocity : make_dimension_t
ACCU 2019 | Implementing a Physical Units Library for C++ 87 Upcasting facility
template
struct dimension_velocity : make_dimension_t
template<> struct upcasting_traits
ACCU 2019 | Implementing a Physical Units Library for C++ 87 Upcasting facility
template
struct dimension_velocity : make_dimension_t
template<> struct upcasting_traits
Help needed: How to automate the last line?
ACCU 2019 | Implementing a Physical Units Library for C++ 87 Upcasting facility
BASE UNIT
struct meter : unit
ACCU 2019 | Implementing a Physical Units Library for C++ 88 Upcasting facility
BASE UNIT
struct meter : unit
UNIT WITH PREFIX
struct kilometer : kilo
ACCU 2019 | Implementing a Physical Units Library for C++ 88 Upcasting facility
BASE UNIT
struct meter : unit
UNIT WITH PREFIX
struct kilometer : kilo
DERIVED UNIT
struct kilometer_per_hour : derived_unit
ACCU 2019 | Implementing a Physical Units Library for C++ 88 Upcasting facility
BEFORE [with D = units::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 89 Upcasting facility
BEFORE [with D = units::quantity
AFTER [with D = units::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 89 Upcasting facility
BEFORE [with D = units::quantity
AFTER [with D = units::quantity
POSSIBLE WITH A DESIGN COST [with D = units::velocity
ACCU 2019 | Implementing a Physical Units Library for C++ 89 Upcasting facility
BEFORE [with D = units::quantity
AFTER [with D = units::quantity
POSSIBLE WITH A DESIGN COST [with D = units::velocity
Do we want the last option with a cost of CRTP usage in quantity?
ACCU 2019 | Implementing a Physical Units Library for C++ 89 C++17 CTAD (Class Template Argument Deduction)
CLASS TEMPLATE
template
ACCU 2019 | Implementing a Physical Units Library for C++ 90 C++17 CTAD (Class Template Argument Deduction)
CLASS TEMPLATE
template
vector v = {1, 2, 3}; vector v2(cont.begin(), cont.end());
ACCU 2019 | Implementing a Physical Units Library for C++ 90 C++17 CTAD (Class Template Argument Deduction)
CLASS TEMPLATE
template
vector v = {1, 2, 3}; vector v2(cont.begin(), cont.end());
ALIAS TEMPLATE
namespace pmr { template
ACCU 2019 | Implementing a Physical Units Library for C++ 90 C++17 CTAD (Class Template Argument Deduction)
CLASS TEMPLATE
template
vector v = {1, 2, 3}; vector v2(cont.begin(), cont.end());
ALIAS TEMPLATE
namespace pmr { template
pmr::vector
ACCU 2019 | Implementing a Physical Units Library for C++ 90 P1021 Filling holes in Class Template Argument Deduction
ALIAS TEMPLATE • Adds CTAD support for – aggregate templates – type aliases – inherited constructors
pmr::vector v = {1, 2, 3}; pmr::vector v2(cont.begin(), cont.end());
ACCU 2019 | Implementing a Physical Units Library for C++ 91 C++20 CTAD in Units
template
ACCU 2019 | Implementing a Physical Units Library for C++ 92 C++20 CTAD in Units
template
units::length d1(3); // OK -> quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 92 C++20 CTAD in Units
template
units::length d1(3); // OK -> quantity
WORKAROUND THAT I WOULD PREFER NOT TO DO ("METER IS A UNIT NOT A QUANTITY! ")
template
units::miles d3(3); // OK -> quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 92 Contracts
template
ACCU 2019 | Implementing a Physical Units Library for C++ 93 Contracts
template
ACCU 2019 | Implementing a Physical Units Library for C++ 93 Contracts
template
ACCU 2019 | Implementing a Physical Units Library for C++ 94 Contracts
template
ACCU 2019 | Implementing a Physical Units Library for C++ 95 Contracts
template
Still not the best solution: • usage of a macro in a header file (possible ODR issue) • not a part of a function signature
ACCU 2019 | Implementing a Physical Units Library for C++ 95 C++20 Contracts
template
ACCU 2019 | Implementing a Physical Units Library for C++ 96 Toy example
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t) { return d / t; }
ACCU 2019 | Implementing a Physical Units Library for C++ 97 Toy example
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t) { return d / t; }
const auto kmph = avg_speed(220_km, 2_h); std::cout << kmph.count() << " km/h\n";
const auto mph = avg_speed(140_mi, 2_h); std::cout << mph.count() << " mph\n";
ACCU 2019 | Implementing a Physical Units Library for C++ 97 Toy example
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t) { return d / t; }
const auto kmph = avg_speed(units::length
const auto mph = avg_speed(units::length
ACCU 2019 | Implementing a Physical Units Library for C++ 98 Toy example
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t) { return d / t; }
units::length
units::length
ACCU 2019 | Implementing a Physical Units Library for C++ 99 User experience: Compilation
constexpr units::velocity
ACCU 2019 | Implementing a Physical Units Library for C++ 100 User experience: Compilation
constexpr units::velocity
GCC-8 error: conversion from ‘quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 100 User experience: Compilation
constexpr units::velocity
GCC-8 error: conversion from ‘quantity
Repeating of broken dimension type is unfortunate here, but it actually makes some code (i.e. using CTAD) easier to understand. Design decision tradeo still to decide...
ACCU 2019 | Implementing a Physical Units Library for C++ 101 User experience: Compilation after possible refactoring
constexpr units::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 102 User experience: Compilation after possible refactoring
constexpr units::quantity
GCC-8 error: conversion from ‘quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 102 User experience: Compilation after possible refactoring
constexpr units::quantity
GCC-8 error: conversion from ‘quantity
BEFORE AFTER
template
template
units::length d(3); // 3 meters units::quantity d(3); // Huh???
void foo(Quantity auto q) { void foo(Quantity auto q) { units::length d(q); // Yay, we are working with length units::quantity d(q); // Huh??? } }
ACCU 2019 | Implementing a Physical Units Library for C++ 102 User experience: Compilation
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t) { return d * t; }
ACCU 2019 | Implementing a Physical Units Library for C++ 103 User experience: Compilation
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t) { return d * t; }
GCC-8 (FULL ERROR LOG) velocity.cpp: In instantiation of ‘constexpr units::Velocity {anonymous}::avg_speed(D, T) [with D = units::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 103 User experience: Compilation
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t) { return d * t; }
GCC-8 (FULL ERROR LOG - CONTINUED) ... include/meta/meta_fwd.hpp:206:18: note: within ‘template
ACCU 2019 | Implementing a Physical Units Library for C++ 104 User experience: Compilation
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t) { return d * t; }
GCC-8 (FULL ERROR LOG - CONTINUED) ... include/meta/meta_fwd.hpp:206:18: note: within ‘template
Probably it will be improved even more with time...
ACCU 2019 | Implementing a Physical Units Library for C++ 104 User experience: Debugging
ACCU 2019 | Implementing a Physical Units Library for C++ 105 User experience: Debugging
ACCU 2019 | Implementing a Physical Units Library for C++ 105 User experience: Debugging
Breakpoint 1, (anonymous namespace)::avg_speed
ACCU 2019 | Implementing a Physical Units Library for C++ 106 User experience: Debugging
(gdb) ptype d type = class units::quantity
ACCU 2019 | Implementing a Physical Units Library for C++ 107 Open design questions
1 What to do with std::chrono::duration?
2 What is the best way to add support for temperatures?
3 Should we provide strong types and upcasting_traits for quantity types?
4 Should we provide aliases for quantities of units (i.e. meters
5 Do we need non-linear scale? How to support it?
ACCU 2019 | Implementing a Physical Units Library for C++ 108 Open design questions
1 What to do with std::chrono::duration?
2 What is the best way to add support for temperatures?
3 Should we provide strong types and upcasting_traits for quantity types?
4 Should we provide aliases for quantities of units (i.e. meters
5 Do we need non-linear scale? How to support it?
More design questions on the project website (https://github.com/mpusz/units)
ACCU 2019 | Implementing a Physical Units Library for C++ 108 Let's join forces!
We really need physical units and dimensional analysis support in the C++ Standard Library
ACCU 2019 | Implementing a Physical Units Library for C++ 109 Let's join forces!
We really need physical units and dimensional analysis support in the C++ Standard Library
WHY TO JOIN? • C++ community and industry really need it • Great opportunity to learn C++20 • An interesting and hard challenge to solve ;-)
ACCU 2019 | Implementing a Physical Units Library for C++ 109 Let's join forces!
We really need physical units and dimensional analysis support in the C++ Standard Library
WHY TO JOIN? • C++ community and industry really need it • Great opportunity to learn C++20 • An interesting and hard challenge to solve ;-)
Please, help...
ACCU 2019 | Implementing a Physical Units Library for C++ 109