<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2023-10-15" />
  <title>Improving our safety with a physical quantities and units
library</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.csl-block{margin-left: 1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      .sourceCode { overflow: visible; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Improving our safety with a
physical quantities and units library</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2981R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2023-10-15</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      SG23 Safety and Security<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Mateusz Pusz (<a href="http://www.epam.com">Epam
Systems</a>)<br>&lt;<a href="mailto:mateusz.pusz@gmail.com" class="email">mateusz.pusz@gmail.com</a>&gt;<br>
      Dominik Berner<br>&lt;<a href="mailto:dominik.berner@gmail.com" class="email">dominik.berner@gmail.com</a>&gt;<br>
      Johel Ernesto Guerrero Peña<br>&lt;<a href="mailto:johelegp@gmail.com" class="email">johelegp@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction<span></span></a></li>
<li><a href="#terms-and-definitions" id="toc-terms-and-definitions"><span class="toc-section-number">2</span>
Terms and definitions<span></span></a></li>
<li><a href="#the-future-is-here" id="toc-the-future-is-here"><span class="toc-section-number">3</span> The future is
here<span></span></a></li>
<li><a href="#affected-industries" id="toc-affected-industries"><span class="toc-section-number">4</span> Affected
industries<span></span></a></li>
<li><a href="#mismeasure-for-measure" id="toc-mismeasure-for-measure"><span class="toc-section-number">5</span> Mismeasure for
measure<span></span></a></li>
<li><a href="#common-smells-when-there-is-no-library-for-physical-quantities" id="toc-common-smells-when-there-is-no-library-for-physical-quantities"><span class="toc-section-number">6</span> Common smells when there is no
library for physical quantities<span></span></a>
<ul>
<li><a href="#the-proliferation-of-double" id="toc-the-proliferation-of-double"><span class="toc-section-number">6.1</span> The proliferation of
<code class="sourceCode default">double</code><span></span></a></li>
<li><a href="#the-proliferation-of-magic-numbers" id="toc-the-proliferation-of-magic-numbers"><span class="toc-section-number">6.2</span> The proliferation of magic
numbers<span></span></a></li>
<li><a href="#the-proliferation-of-conversion-macros" id="toc-the-proliferation-of-conversion-macros"><span class="toc-section-number">6.3</span> The proliferation of conversion
macros<span></span></a></li>
<li><a href="#lack-of-consistency" id="toc-lack-of-consistency"><span class="toc-section-number">6.4</span> Lack of
consistency<span></span></a></li>
<li><a href="#lack-of-a-conceptual-framework" id="toc-lack-of-a-conceptual-framework"><span class="toc-section-number">6.5</span> Lack of a conceptual
framework<span></span></a></li>
</ul></li>
<li><a href="#safety-features" id="toc-safety-features"><span class="toc-section-number">7</span> Safety features<span></span></a>
<ul>
<li><a href="#unit-conversions" id="toc-unit-conversions"><span class="toc-section-number">7.1</span> Unit
conversions<span></span></a></li>
<li><a href="#preventing-truncation-of-data" id="toc-preventing-truncation-of-data"><span class="toc-section-number">7.2</span> Preventing truncation of
data<span></span></a></li>
<li><a href="#the-affine-space" id="toc-the-affine-space"><span class="toc-section-number">7.3</span> The affine
space<span></span></a></li>
<li><a href="#explicit-is-not-explicit-enough" id="toc-explicit-is-not-explicit-enough"><span class="toc-section-number">7.4</span>
<code class="sourceCode default">explicit</code> is not explicit
enough<span></span></a></li>
<li><a href="#obtaining-the-numerical-value-of-a-quantity" id="toc-obtaining-the-numerical-value-of-a-quantity"><span class="toc-section-number">7.5</span> Obtaining the numerical value of a
quantity<span></span></a></li>
<li><a href="#preventing-dangling-references" id="toc-preventing-dangling-references"><span class="toc-section-number">7.6</span> Preventing dangling
references<span></span></a></li>
<li><a href="#quantity-kinds" id="toc-quantity-kinds"><span class="toc-section-number">7.7</span> Quantity
kinds<span></span></a></li>
<li><a href="#various-quantities-of-the-same-kind" id="toc-various-quantities-of-the-same-kind"><span class="toc-section-number">7.8</span> Various quantities of the same
kind<span></span></a>
<ul>
<li><a href="#converting-between-quantities-of-the-same-kind" id="toc-converting-between-quantities-of-the-same-kind"><span class="toc-section-number">7.8.1</span> Converting between quantities of
the same kind<span></span></a></li>
<li><a href="#comparing-adding-and-subtracting-quantities-of-the-same-kind" id="toc-comparing-adding-and-subtracting-quantities-of-the-same-kind"><span class="toc-section-number">7.8.2</span> Comparing, adding, and
subtracting quantities of the same kind<span></span></a></li>
<li><a href="#modeling-a-quantity-kind" id="toc-modeling-a-quantity-kind"><span class="toc-section-number">7.8.3</span> Modeling a quantity
kind<span></span></a></li>
<li><a href="#restricting-units-to-specific-quantity-kinds" id="toc-restricting-units-to-specific-quantity-kinds"><span class="toc-section-number">7.8.4</span> Restricting units to specific
quantity kinds<span></span></a></li>
</ul></li>
<li><a href="#non-negative-quantities" id="toc-non-negative-quantities"><span class="toc-section-number">7.9</span> Non-negative
quantities<span></span></a></li>
<li><a href="#vector-and-tensor-quantities" id="toc-vector-and-tensor-quantities"><span class="toc-section-number">7.10</span> Vector and tensor
quantities<span></span></a></li>
</ul></li>
<li><a href="#safety-pitfalls" id="toc-safety-pitfalls"><span class="toc-section-number">8</span> Safety pitfalls<span></span></a>
<ul>
<li><a href="#integer-division" id="toc-integer-division"><span class="toc-section-number">8.1</span> Integer
division<span></span></a></li>
<li><a href="#lack-of-safe-numeric-types" id="toc-lack-of-safe-numeric-types"><span class="toc-section-number">8.2</span> Lack of safe numeric
types<span></span></a></li>
<li><a href="#potential-surprises-during-units-composition" id="toc-potential-surprises-during-units-composition"><span class="toc-section-number">8.3</span> Potential surprises during units
composition<span></span></a></li>
<li><a href="#structural-types" id="toc-structural-types"><span class="toc-section-number">8.4</span> Structural
types<span></span></a></li>
</ul></li>
<li><a href="#acknowledgements" id="toc-acknowledgements"><span class="toc-section-number">9</span>
Acknowledgements<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">10</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>One of the ways C++ can significantly improve the safety of
applications being written by thousands of developers is by introducing
a type-safe, well-tested, proven in production, standardized way to
handle physical quantities and their units. The rationale is that people
tend to have problems communicating or using proper units in code and
daily life. Another benefit of adding strongly typed quantities and
units to the standard is that it will allow catching some mistakes at
compile-time instead of relying on runtime checks which might have
spotty coverage.</p>
<p>This paper scopes on the safety aspects of introducing such a library
to the C++ standard. In the following chapters, we will describe which
industries are desperately looking for such standardized solutions,
enumerate some failures and accidents caused by misinterpretation of
quantities and units in human history, review all the features of such a
library that improve the safety of our code, and also discuss potential
safety issues that the library does not prevent against.</p>
<p><em>Note: This paper refers to practices used in the <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library and presents code
examples using its interfaces. Those may not exactly reflect the final
interface design that is going to be proposed in the follow-up papers.
We are still doing some small fine-tuning to improve the
library.</em></p>
<h1 data-number="2" id="terms-and-definitions"><span class="header-section-number">2</span> Terms and definitions<a href="#terms-and-definitions" class="self-link"></a></h1>
<p>This document consistently uses the official metrology vocabulary
defined in the <span class="citation" data-cites="ISO-GUIDE">[<a href="#ref-ISO-GUIDE" role="doc-biblioref">ISO/IEC Guide 99</a>]</span>
and <span class="citation" data-cites="BIPM-VIM">[<a href="#ref-BIPM-VIM" role="doc-biblioref">JCGM 200:2012</a>]</span>.</p>
<h1 data-number="3" id="the-future-is-here"><span class="header-section-number">3</span> The future is here<a href="#the-future-is-here" class="self-link"></a></h1>
<p>Not that long ago, self-driving cars were a thing from SciFi movies.
It was something so futuristic and hard to imagine that it only appeared
in movies set in the very far future. Today, autonomous cars are
becoming a reality on our streets even if they are not (yet) widely
adopted.</p>
<p>It is no longer only the space industry or airline pilots that
benefit from the autonomous operations of some machines. We live in a
world where more and more ordinary people trust machines with their
lives daily. The autonomous car is just one example which will affect
our daily life. Medical devices, such as surgical robots and smart
health care devices, are already a thing and will see wider adoption in
the future. And there will be more machines with safety- or even
life-critical tasks in the future. As a result, many more C++ engineers
are expected to write life-critical software today than a few years
ago.</p>
<p>Unfortunately, experience in this domain is hard to come by, and
training alone will not solve the issue of mistakes caused by confusing
units or quantities. Additionally, the C++ standard does not change fast
enough to enforce a safe-by-construction code, which becomes even more
critical if the code handling the physical computation is written by
domain experts such as physicists that are not necessarily fluent in
C++.</p>
<h1 data-number="4" id="affected-industries"><span class="header-section-number">4</span> Affected industries<a href="#affected-industries" class="self-link"></a></h1>
<p>When people think about industries that could use physical quantities
and unit libraries, they think of a few companies related to aerospace,
autonomous cars, or embedded industries. That is all true, but there are
many other potential users for such a library.</p>
<p>Here is a list of some less obvious candidates:</p>
<ul>
<li>Manufacturing,</li>
<li>maritime industry,</li>
<li>freight transport,</li>
<li>military,</li>
<li>astronomy,</li>
<li>3D design,</li>
<li>robotics,</li>
<li>audio,</li>
<li>medical devices,</li>
<li>national laboratories,</li>
<li>scientific institutions and universities,</li>
<li>all kinds of navigation and charting,</li>
<li>GUI frameworks,</li>
<li>finance (including HFT).</li>
</ul>
<p>As we can see, the range of domains for such a library is vast and
not limited to applications involving specifically physical units. Any
software that involves measurements, or operations on counts of some
standard or domain-specific quantities, could benefit from a zero-cost
abstraction for operating on quantity values and their units. The
library also provides affine space abstractions, which may prove useful
in many applications.</p>
<h1 data-number="5" id="mismeasure-for-measure"><span class="header-section-number">5</span> Mismeasure for measure<a href="#mismeasure-for-measure" class="self-link"></a></h1>
<p>Human history knows many expensive failures and accidents caused by
mistakes in calculations involving different physical units. The most
famous and probably the most expensive example in the software
engineering domain is the Mars Climate Orbiter that in 1999 failed to
enter Mars’ orbit and crashed while entering its atmosphere <span class="citation" data-cites="MARS_ORBITER">[<a href="#ref-MARS_ORBITER" role="doc-biblioref">Mars Orbiter</a>]</span>. This is one of many
examples here. People tend to confuse units quite often. We see similar
errors occurring in various domains over the years:</p>
<ul>
<li>On October 12, 1492, Christopher Columbus unintentionally discovered
the sea route from Europe to America because, during his travel
preparations, he mixed the Arabic mile with a Roman mile, which led to
the wrong estimation of the equator and his expected travel distance
<span class="citation" data-cites="COLUMBUS">[<a href="#ref-COLUMBUS" role="doc-biblioref">Columbus</a>]</span>.</li>
<li>In 1628, a new warship, Vasa, accidentally had an asymmetrical hull
(being thicker on the port side than the starboard side), which was one
of the reasons for her sinking less than a mile into her maiden voyage,
resulting in the death of 30 people on board. This asymmetry could have
been caused by the use of different systems of measurement, as
archaeologists have found four rulers used by the workers who built the
ship. Two were calibrated in Swedish feet, which had 12 inches, while
the other two measured Amsterdam feet, which had 11 inches <span class="citation" data-cites="VASA">[<a href="#ref-VASA" role="doc-biblioref">Vasa</a>]</span>.</li>
<li>Air Canada Flight 143 ran out of fuel on July 23, 1983, at an
altitude of 41 000 feet (12 000 metres), midway through the flight
because the fuel had been calculated in pounds instead of kilograms by
the ground crew <span class="citation" data-cites="GIMLI_GLIDER">[<a href="#ref-GIMLI_GLIDER" role="doc-biblioref">Gimli
Glider</a>]</span>.</li>
<li>The British rock band Black Sabbath, during its Born Again tour in
1983, ordered a replica of Stonehenge as props for the scene.
Unfortunately, they had to leave them in the storage area because, while
submitting the order, their manager wrote dimensions down in meters when
he meant feet, and so the stones didn’t fit the scene. “It cost a
fortune to make, but there was not a building on Earth that you could
fit it into” <span class="citation" data-cites="STONEHENGE">[<a href="#ref-STONEHENGE" role="doc-biblioref">Stonehenge</a>]</span>.</li>
<li>On April 15, 1999, Korean Air Cargo Flight 6316 crashed due to a
miscommunication between pilots about the desired flight altitude <span class="citation" data-cites="FLIGHT_6316">[<a href="#ref-FLIGHT_6316" role="doc-biblioref">Flight 6316</a>]</span>.</li>
<li>In February 2001, the crew of the Moorpark College Zoo built an
enclosure for Clarence the Tortoise with a weight of 250 pounds instead
of 250 kilograms <span class="citation" data-cites="CLARENCE">[<a href="#ref-CLARENCE" role="doc-biblioref">Clarence</a>]</span>.</li>
<li>In December 2003, one of the roller coaster’s cars at Tokyo
Disneyland’s Space Mountain attraction suddenly derailed due to a broken
axle caused by confusion after upgrading the specification from imperial
to metric units <span class="citation" data-cites="DISNEY">[<a href="#ref-DISNEY" role="doc-biblioref">Disney</a>]</span>.</li>
<li>During the construction of the Hochrheinbrücke bridge to connect the
small German town of Laufenburg with Swiss Laufenburg, the construction
team made a sign error that resulted in a discrepancy of 54 cm between
the two outer ends of the bridge <span class="citation" data-cites="HOCHRHEINBRÜCKE">[<a href="#ref-HOCHRHEINBRÜCKE" role="doc-biblioref">Hochrheinbrücke</a>]</span>.</li>
<li>An American company sold a shipment of wild rice to a Japanese
customer, quoting a price of 39 cents per pound, but the customer
thought the quote was for 39 cents per kilogram <span class="citation" data-cites="WILD_RICE">[<a href="#ref-WILD_RICE" role="doc-biblioref">Wild Rice</a>]</span>.</li>
<li>A whole set of <span class="citation" data-cites="MEDICATION_DOSE_ERRORS">[<a href="#ref-MEDICATION_DOSE_ERRORS" role="doc-biblioref">Medication dose
errors</a>]</span>…</li>
</ul>
<h1 data-number="6" id="common-smells-when-there-is-no-library-for-physical-quantities"><span class="header-section-number">6</span> Common smells when there is no
library for physical quantities<a href="#common-smells-when-there-is-no-library-for-physical-quantities" class="self-link"></a></h1>
<p>In this chapter, we are going to review typical safety issues related
to physical quantities and units in the C++ code when a proper library
is not used. Even though all the examples come from the Open Source
projects, expensive revenue-generating production source code often is
similar.</p>
<h2 data-number="6.1" id="the-proliferation-of-double"><span class="header-section-number">6.1</span> The proliferation of
<code class="sourceCode default">double</code><a href="#the-proliferation-of-double" class="self-link"></a></h2>
<p>It turns out that in the C++ software, most of our calculations in
the physical quantities and units domain are handled with fundamental
types like <code class="sourceCode default">double</code>. Code like
below is a typical example here:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> GlidePolar<span class="op">::</span>MacCreadyAltitude<span class="op">(</span><span class="dt">double</span> MCREADY,</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>                                     <span class="dt">double</span> Distance,</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>                                     <span class="kw">const</span> <span class="dt">double</span> Bearing,</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>                                     <span class="kw">const</span> <span class="dt">double</span> WindSpeed,</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>                                     <span class="kw">const</span> <span class="dt">double</span> WindBearing,</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>                                     <span class="dt">double</span> <span class="op">*</span>BestCruiseTrack,</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>                                     <span class="dt">double</span> <span class="op">*</span>VMacCready,</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>                                     <span class="kw">const</span> <span class="dt">bool</span> isFinalGlide,</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>                                     <span class="dt">double</span> <span class="op">*</span>TimeToGo,</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>                                     <span class="kw">const</span> <span class="dt">double</span> AltitudeAboveTarget<span class="op">=</span><span class="fl">1.0e6</span>,</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>                                     <span class="kw">const</span> <span class="dt">double</span> cruise_efficiency<span class="op">=</span><span class="fl">1.0</span>,</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>                                     <span class="kw">const</span> <span class="dt">double</span> TaskAltDiff<span class="op">=-</span><span class="fl">1.0e6</span><span class="op">)</span>;</span></code></pre></div>
<p><a href="https://github.com/LK8000/LK8000/blob/af404168ff5f92b03ab0c5db336ed8f01a792cda/Common/Header/McReady.h#L7-L21">Original
code here</a>.</p>
<p>There are several problems with such an approach: The abundance of
<code class="sourceCode default">double</code> parameters makes it easy
to accidentally switch values and there is no way of noticing such a
mistake at compile-time. The code is not self-documenting in what units
the parameters are expected. Is
<code class="sourceCode default">Distance</code> in meters or
kilometers? Is <code class="sourceCode default">WindSpeed</code> in
meters per second or knots? Different code bases choose different ways
to encode this information, which may be internally inconsistent. A
strong type system would help answer these questions at the time the
interface is written, and the compiler would verify it at
compile-time.</p>
<h2 data-number="6.2" id="the-proliferation-of-magic-numbers"><span class="header-section-number">6.2</span> The proliferation of magic
numbers<a href="#the-proliferation-of-magic-numbers" class="self-link"></a></h2>
<p>There are a lot of constants and conversion factors involved in the
quantity equations. Source code responsible for such computations is
often trashed with magic numbers:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> AirDensity<span class="op">(</span><span class="dt">double</span> hr, <span class="dt">double</span> temp, <span class="dt">double</span> abs_press<span class="op">)</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">(</span><span class="dv">1</span><span class="op">/(</span><span class="fl">287.06</span><span class="op">*(</span>temp<span class="op">+</span><span class="fl">273.15</span><span class="op">)))*(</span>abs_press <span class="op">-</span> <span class="fl">230.617</span> <span class="op">*</span> hr <span class="op">*</span> exp<span class="op">((</span><span class="fl">17.5043</span><span class="op">*</span>temp<span class="op">)/(</span><span class="fl">241.2</span><span class="op">+</span>temp<span class="op">)))</span>;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><a href="https://github.com/LK8000/LK8000/blob/af404168ff5f92b03ab0c5db336ed8f01a792cda/Common/Source/Library/PressureFunctions.cpp#L134-L136">Original
code here</a>.</p>
<p>Apart from the obvious readability issues, such code is hard to
maintain, and it needs a lot of domain knowledge on the developer’s
side. While it would be easy to replace these numbers with named
constants, the question of which unit the constant is in remains. Is
<code class="sourceCode default">287.06</code> in pounds per square inch
(psi) or millibars (mbar)?</p>
<h2 data-number="6.3" id="the-proliferation-of-conversion-macros"><span class="header-section-number">6.3</span> The proliferation of conversion
macros<a href="#the-proliferation-of-conversion-macros" class="self-link"></a></h2>
<p>The lack of automated unit conversions often results in handwritten
conversion functions or macros that are spread everywhere among the code
base:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef PI</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">const</span> <span class="dt">double</span> PI <span class="op">=</span> <span class="op">(</span><span class="dv">4</span><span class="op">*</span>atan<span class="op">(</span><span class="dv">1</span><span class="op">))</span>;</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#define EARTH_DIAMETER    </span><span class="fl">12733426.0</span><span class="pp">    </span><span class="co">// Diameter of earth in meters</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#define SQUARED_EARTH_DIAMETER  </span><span class="fl">162140137697476.0</span><span class="pp"> </span><span class="co">// Diameter of earth in meters (EARTH_DIAMETER*EARTH_DIAMETER)</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef DEG_TO_RAD</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#define DEG_TO_RAD  </span><span class="op">(</span>PI<span class="pp"> </span><span class="op">/</span><span class="pp"> </span><span class="dv">180</span><span class="op">)</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#define RAD_TO_DEG  </span><span class="op">(</span><span class="dv">180</span><span class="pp"> </span><span class="op">/</span><span class="pp"> </span>PI<span class="op">)</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="pp">#define NAUTICALMILESTOMETRES </span><span class="op">(</span><span class="dt">double</span><span class="op">)</span><span class="fl">1851.96</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="pp">#define KNOTSTOMETRESSECONDS </span><span class="op">(</span><span class="dt">double</span><span class="op">)</span><span class="fl">0.5144</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a><span class="pp">#define TOKNOTS </span><span class="op">(</span><span class="dt">double</span><span class="op">)</span><span class="fl">1.944</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a><span class="pp">#define TOFEETPERMINUTE </span><span class="op">(</span><span class="dt">double</span><span class="op">)</span><span class="fl">196.9</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a><span class="pp">#define TOMPH   </span><span class="op">(</span><span class="dt">double</span><span class="op">)</span><span class="fl">2.237</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="pp">#define TOKPH   </span><span class="op">(</span><span class="dt">double</span><span class="op">)</span><span class="fl">3.6</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a><span class="co">// meters to.. conversion</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a><span class="pp">#define TONAUTICALMILES </span><span class="op">(</span><span class="fl">1.0</span><span class="pp"> </span><span class="op">/</span><span class="pp"> </span><span class="fl">1852.0</span><span class="op">)</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a><span class="pp">#define TOMILES         </span><span class="op">(</span><span class="fl">1.0</span><span class="pp"> </span><span class="op">/</span><span class="pp"> </span><span class="fl">1609.344</span><span class="op">)</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a><span class="pp">#define TOKILOMETER     </span><span class="op">(</span><span class="fl">0.001</span><span class="op">)</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a><span class="pp">#define TOFEET          </span><span class="op">(</span><span class="fl">1.0</span><span class="pp"> </span><span class="op">/</span><span class="pp"> </span><span class="fl">0.3048</span><span class="op">)</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a><span class="pp">#define TOMETER         </span><span class="op">(</span><span class="fl">1.0</span><span class="op">)</span></span></code></pre></div>
<p><a href="https://github.com/LK8000/LK8000/blob/052bbc20a106fda4db41874e788e39020fb86512/Common/Header/Defines.h#L901-L924">Original
code here</a>.</p>
<p>Again, the question of which unit the constant is in remains. Without
looking at the code, it is impossible to tell from which unit
<code class="sourceCode default">TOMETER</code> converts. Also, macros
have the problem that they are not scoped to a namespace and thus can
easily clash with other macros or functions, especially if they have
such common names like <code class="sourceCode default">PI</code> or
<code class="sourceCode default">RAD_TO_DEG</code>. A quick search
through open source C++ code bases reveals that, for example, the
<code class="sourceCode default">RAD_TO_DEG</code> macro is defined in a
multitude of different ways – sometimes even within the same
repository:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define RAD_TO_DEG </span><span class="op">(</span><span class="dv">180</span><span class="pp"> </span><span class="op">/</span><span class="pp"> </span>PI<span class="op">)</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define RAD_TO_DEG </span><span class="fl">57.2957795131</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#define RAD_TO_DEG </span><span class="op">(</span><span class="pp"> </span>radians<span class="pp"> </span><span class="op">)</span><span class="pp"> </span><span class="op">((</span>radians<span class="pp"> </span><span class="op">)</span><span class="pp"> </span><span class="op">*</span><span class="pp"> </span><span class="fl">180.0</span><span class="pp"> </span><span class="op">/</span><span class="pp"> </span>M_PI<span class="op">)</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#define RAD_TO_DEG </span><span class="fl">57.2957805</span><span class="bu">f</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="op">...</span></span></code></pre></div>
<p><a href="https://github.com/search?q=lang%3AC%2B%2B++%22%23define+RAD_TO_DEG%22&amp;type=code">Example
search across multiple repositories</a></p>
<p><a href="https://github.com/search?q=repo%3ALK8000%2FLK8000%20rad_to_deg&amp;type=code">Multiple
redefinitions in the same repository</a></p>
<p>Another safety issue occurring here is the fact that macro values can
be deliberately tainted by compiler settings at built time and can
acquire values that are not present in the source code. Human reviews
won’t catch such issues.</p>
<p>Also, most of the macros do not follow best practices. Often,
necessary parentheses are missing, processing in a preprocessor ends up
with redundant casts, or some compile-time constants use too many digits
for a value to be exact for a specific type
(e.g. <code class="sourceCode default">float</code>).</p>
<h2 data-number="6.4" id="lack-of-consistency"><span class="header-section-number">6.4</span> Lack of consistency<a href="#lack-of-consistency" class="self-link"></a></h2>
<p>If we not only lack strong types to isolate the abstractions from
each other, but also lack discipline to keep our code consistent, we end
up in an awful place:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> DistanceBearing<span class="op">(</span><span class="dt">double</span> lat1, <span class="dt">double</span> lon1,</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>                     <span class="dt">double</span> lat2, <span class="dt">double</span> lon2,</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>                     <span class="dt">double</span> <span class="op">*</span>Distance, <span class="dt">double</span> <span class="op">*</span>Bearing<span class="op">)</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> DoubleDistance<span class="op">(</span><span class="dt">double</span> lat1, <span class="dt">double</span> lon1,</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>                      <span class="dt">double</span> lat2, <span class="dt">double</span> lon2,</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>                      <span class="dt">double</span> lat3, <span class="dt">double</span> lon3<span class="op">)</span>;</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> FindLatitudeLongitude<span class="op">(</span><span class="dt">double</span> Lat, <span class="dt">double</span> Lon,</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>                           <span class="dt">double</span> Bearing, <span class="dt">double</span> Distance,</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>                           <span class="dt">double</span> <span class="op">*</span>lat_out, <span class="dt">double</span> <span class="op">*</span>lon_out<span class="op">)</span>;</span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> CrossTrackError<span class="op">(</span><span class="dt">double</span> lon1, <span class="dt">double</span> lat1,</span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>                       <span class="dt">double</span> lon2, <span class="dt">double</span> lat2,</span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>                       <span class="dt">double</span> lon3, <span class="dt">double</span> lat3,</span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>                       <span class="dt">double</span> <span class="op">*</span>lon4, <span class="dt">double</span> <span class="op">*</span>lat4<span class="op">)</span>;</span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> ProjectedDistance<span class="op">(</span><span class="dt">double</span> lon1, <span class="dt">double</span> lat1,</span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">double</span> lon2, <span class="dt">double</span> lat2,</span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">double</span> lon3, <span class="dt">double</span> lat3,</span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">double</span> <span class="op">*</span>xtd, <span class="dt">double</span> <span class="op">*</span>crs<span class="op">)</span>;</span></code></pre></div>
<p><a href="https://github.com/LK8000/LK8000/blob/af404168ff5f92b03ab0c5db336ed8f01a792cda/Common/Header/NavFunctions.h#L7C1-L27">Original
code here</a>.</p>
<p>Users can easily make errors if the interface designers are not
consistent in ordering parameters. It is really hard to remember which
function takes latitude or
<code class="sourceCode default">Bearing</code> first and when a
latitude or <code class="sourceCode default">Distance</code> is in the
front.</p>
<h2 data-number="6.5" id="lack-of-a-conceptual-framework"><span class="header-section-number">6.5</span> Lack of a conceptual
framework<a href="#lack-of-a-conceptual-framework" class="self-link"></a></h2>
<p>The previous points mean that the fundamental types can’t be
leveraged to model the different concepts of quantities and units
frameworks. There is no shared vocabulary between different libraries.
User-facing APIs use ad-hoc conventions. Even internal interfaces are
inconsistent between themselves.</p>
<p>Arithmetic types such as <code class="sourceCode default">int</code>
and <code class="sourceCode default">double</code> are used to model
different concepts. They are used to represent any abstraction (be it a
magnitude, difference, point, or kind) of any quantity type of any unit.
These are weak types that make up weakly-typed interfaces. The resulting
interfaces and implementations built with these types easily allow
mixing up parameters and using operations that are not part of the
represented quantity.</p>
<h1 data-number="7" id="safety-features"><span class="header-section-number">7</span> Safety features<a href="#safety-features" class="self-link"></a></h1>
<p>This chapter describes the features that enforce safety in our code
bases. It starts with obvious things, but then it moves to probably less
known benefits of using physical quantities and units libraries. This
chapter also serves as a proof that it is not easy to implement such a
library correctly, and that there are many cases where the lack of
experience or time for the development of such a utility may easily lead
to safety issues as well.</p>
<p>Before we go through all the features, it is essential to note that
they do not introduce any runtime overhead over the raw unsafe code
doing the same thing. This is a massive benefit of C++ compared to other
programming languages (e.g., Python, Java, etc.).</p>
<h2 data-number="7.1" id="unit-conversions"><span class="header-section-number">7.1</span> Unit conversions<a href="#unit-conversions" class="self-link"></a></h2>
<p>The first thing that comes to our mind when discussing the safety of
such libraries is automated unit conversions between values of the same
physical quantity. This is probably the most important subject here. We
learned about its huge benefits long ago thanks to the
<code class="sourceCode default">std::chrono::duration</code> that made
conversions of time durations error-proof.</p>
<p>Unit conversions are typically performed either via a converting
constructor or a dedicated conversion function:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> q1 <span class="op">=</span> <span class="dv">5</span> <span class="op">*</span> km;</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> q1<span class="op">.</span>in<span class="op">(</span>m<span class="op">)</span> <span class="op">&lt;&lt;</span> <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span>;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>si<span class="op">::</span>metre, <span class="dt">int</span><span class="op">&gt;</span> q2 <span class="op">=</span> q1;</span></code></pre></div>
<p>Such a feature benefits from the fact that the library knows about
the magnitudes of the source and destination units at compile-time, and
may use that information to calculate and apply a conversion factor
automatically for the user.</p>
<p>In <code class="sourceCode default">std::chrono::duration</code>, the
magnitude of a unit is always expressed with
<code class="sourceCode default">std::ratio</code>. This is not enough
for a general-purpose physical units library. Some of the derived units
have huge or tiny ratios. The difference from the base units is so huge
that it cannot be expressed with
<code class="sourceCode default">std::ratio</code>, which is implemented
in terms of <code class="sourceCode default">std::intmax_t</code>. This
makes it impossible to define units like electronvolt (eV), where 1 eV =
1.602176634×10<sup>−19</sup> J, or Dalton (Da), where 1 Da =
1.660539040(20)×10<sup>−27</sup> kg. Moreover, some conversions, such as
radian to a degree, require a conversion factor based on an irrational
number like pi.</p>
<h2 data-number="7.2" id="preventing-truncation-of-data"><span class="header-section-number">7.2</span> Preventing truncation of data<a href="#preventing-truncation-of-data" class="self-link"></a></h2>
<p>The second safety feature of such libraries is preventing accidental
truncation of a quantity value. If we try the operations above with
swapped units, both conversions should fail to compile:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> q1 <span class="op">=</span> <span class="dv">5</span> <span class="op">*</span> m;</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> q1<span class="op">.</span>in<span class="op">(</span>km<span class="op">)</span> <span class="op">&lt;&lt;</span> <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span>;              <span class="co">// Compile-time error</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>si<span class="op">::</span>kilo<span class="op">&lt;</span>si<span class="op">::</span>metre<span class="op">&gt;</span>, <span class="dt">int</span><span class="op">&gt;</span> q2 <span class="op">=</span> q1;  <span class="co">// Compile-time error</span></span></code></pre></div>
<p>We can’t preserve the value of a source quantity when we convert it
to one with an unit of a lower resolution while dealing with an integral
representation type for a quantity. In the example above, converting
<code class="sourceCode default">5</code> meters would result in
<code class="sourceCode default">0</code> kilometers if internal
conversion is performed using regular integer arithmetic.</p>
<p>While this could be a valid behavior, the problem arises when the
user expects to be able to convert the quantity back to the original
unit without loss of information. So the library should prevent such
conversions from happening implicitly; <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> offers the named cast
<code class="sourceCode default">value_cast</code> for these conversions
marked as unsafe.</p>
<p>To make the above conversions compile, we could use a floating-point
representation type:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> q1 <span class="op">=</span> <span class="fl">5.</span> <span class="op">*</span> m;    <span class="co">// source quantity uses `double` as a representation type</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> q1<span class="op">.</span>in<span class="op">(</span>km<span class="op">)</span> <span class="op">&lt;&lt;</span> <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span>;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>si<span class="op">::</span>kilo<span class="op">&lt;</span>si<span class="op">::</span>metre<span class="op">&gt;&gt;</span> q2 <span class="op">=</span> q1;</span></code></pre></div>
<p>or:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> q1 <span class="op">=</span> <span class="dv">5</span> <span class="op">*</span> m;     <span class="co">// source quantity uses `int` as a representation type</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> value_cast<span class="op">&lt;</span><span class="dt">double</span><span class="op">&gt;(</span>q1<span class="op">).</span>in<span class="op">(</span>km<span class="op">)</span> <span class="op">&lt;&lt;</span> <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span>;</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>si<span class="op">::</span>kilo<span class="op">&lt;</span>si<span class="op">::</span>metre<span class="op">&gt;&gt;</span> q2 <span class="op">=</span> q1;  <span class="co">// `double` by default</span></span></code></pre></div>
<p><em>The <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library
follows <code class="sourceCode default">std::chrono::duration</code>
logic and treats floating-point types as value-preserving.</em></p>
<p>Another possibility would be to force such a truncating conversion
explicitly from the code:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> q1 <span class="op">=</span> <span class="dv">5</span> <span class="op">*</span> m;     <span class="co">// source quantity uses `int` as a representation type</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> q1<span class="op">.</span>force_in<span class="op">(</span>km<span class="op">)</span> <span class="op">&lt;&lt;</span> <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span>;</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>si<span class="op">::</span>kilo<span class="op">&lt;</span>si<span class="op">::</span>metre<span class="op">&gt;</span>, <span class="dt">int</span><span class="op">&gt;</span> q2 <span class="op">=</span> value_cast<span class="op">&lt;</span>km<span class="op">&gt;(</span>q1<span class="op">)</span>;</span></code></pre></div>
<p>The code above makes it clear that “something bad” may happen here if
we are not extra careful.</p>
<p>Another case for truncation happens when we assign a quantity with a
floating-point representation type to the one using an integral
representation type for its value:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> q1 <span class="op">=</span> <span class="fl">2.5</span> <span class="op">*</span> m;</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>si<span class="op">::</span>metre, <span class="dt">int</span><span class="op">&gt;</span> q2 <span class="op">=</span> q1;</span></code></pre></div>
<p>Such an operation should fail to compile as well. Again, to force
such a truncation, we have to be explicit in the code:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> q1 <span class="op">=</span> <span class="fl">2.5</span> <span class="op">*</span> m;</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>si<span class="op">::</span>metre, <span class="dt">int</span><span class="op">&gt;</span> q2 <span class="op">=</span> value_cast<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(</span>q1<span class="op">)</span>;</span></code></pre></div>
<p>As we can see, it is essential not to allow such truncating
conversions to happen implicitly, and a good physical quantities and
units library should fail at compile-time in case an user makes such a
mistake.</p>
<h2 data-number="7.3" id="the-affine-space"><span class="header-section-number">7.3</span> The affine space<a href="#the-affine-space" class="self-link"></a></h2>
<p>The affine space has two types of entities:</p>
<ul>
<li>point - a position specified with coordinate values (i.e., location,
address, etc.)</li>
<li>vector - the difference between two points (i.e., shift, offset,
displacement, duration, etc.)</li>
</ul>
<p>One can do a limited set of operations in affine space on points and
vectors. This greatly helps to prevent quantity equations that do not
have physical sense.</p>
<p>People often think that affine space is needed only to model
temperatures and maybe time points (following the <a href="https://en.cppreference.com/w/cpp/chrono/time_point"><code class="sourceCode default">std::chrono::time_point</code></a>
example). Still, the applicability of this concept is much wider.</p>
<p>For example, if we would like to model a Mount Everest climbing
expedition, we would deal with two kinds of altitude-related entities.
The first would be absolute altitudes above the mean sea level (points)
like base camp altitude, mount peak altitude, etc. The second one would
be the heights of daily climbs (vectors). As long as it makes physical
sense to add heights of daily climbs, there is no sense in adding
altitudes. What does adding the altitude of a base camp and the mountain
peak mean after all?</p>
<p>Modeling such affine space entities with the
<code class="sourceCode default">quantity</code> (vector) and
<code class="sourceCode default">quantity_point</code> (point) class
templates improves the overall project’s safety by only providing the
operators defined by the concepts.</p>
<h2 data-number="7.4" id="explicit-is-not-explicit-enough"><span class="header-section-number">7.4</span>
<code class="sourceCode default">explicit</code> is not explicit
enough<a href="#explicit-is-not-explicit-enough" class="self-link"></a></h2>
<p>Consider the following structure and a code using it:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> X <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>chrono<span class="op">::</span>milliseconds<span class="op">&gt;</span> vec;</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>X x;</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>x<span class="op">.</span>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="dv">42</span><span class="op">)</span>;</span></code></pre></div>
<p>Everything works fine for years until, at some point, someone changes
the structure to:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> X <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>chrono<span class="op">::</span>microseconds<span class="op">&gt;</span> vec;</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The code continues to compile fine, but all the calculations are now
off by orders of magnitude. This is why a good physical quantities and
units library should not provide an explicit quantity constructor taking
a raw value.</p>
<p>To solve this issue, a quantity in the <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library always requires
information about both a number and a unit during construction:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> X <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>quantity<span class="op">&lt;</span>si<span class="op">::</span>milli<span class="op">&lt;</span>si<span class="op">::</span>seconds<span class="op">&gt;&gt;&gt;</span> vec;</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>X x;</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>x<span class="op">.</span>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="dv">42</span><span class="op">)</span>;       <span class="co">// Compile-time error</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>x<span class="op">.</span>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="dv">42</span> <span class="op">*</span> ms<span class="op">)</span>;  <span class="co">// OK</span></span></code></pre></div>
<p>For consistency and to prevent similar safety issues, the
<code class="sourceCode default">quantity_point</code> in the <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library can’t be created from
a standalone value of a <code class="sourceCode default">quantity</code>
(contrary to the
<code class="sourceCode default">std::chrono::time_point</code> design).
Such a point has to always be associated with an explicit origin:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>quantity_point qp1 <span class="op">=</span> mean_sea_level <span class="op">+</span> <span class="dv">42</span> <span class="op">*</span> m;</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>quantity_point qp2 <span class="op">=</span> si<span class="op">::</span>ice_point <span class="op">+</span> <span class="dv">21</span> <span class="op">*</span> deg_C;</span></code></pre></div>
<h2 data-number="7.5" id="obtaining-the-numerical-value-of-a-quantity"><span class="header-section-number">7.5</span> Obtaining the numerical value
of a quantity<a href="#obtaining-the-numerical-value-of-a-quantity" class="self-link"></a></h2>
<p>Continuing our previous example, let’s assume that we have an
underlying “legacy” API that requires us to pass a raw numerical value
of a quantity and that we do the following to use it:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> legacy_func<span class="op">(</span>std<span class="op">::</span><span class="dt">int64_t</span> seconds<span class="op">)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>X x;</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>x<span class="op">.</span>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="dv">42</span><span class="bu">s</span><span class="op">)</span>;</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>legacy_func<span class="op">(</span>x<span class="op">.</span>vec<span class="op">[</span><span class="dv">0</span><span class="op">].</span>count<span class="op">())</span>;</span></code></pre></div>
<p>The following code is incorrect. Even though the duration stores a
quantity equal to 42 s, it is not stored in seconds (it’s either
microseconds or milliseconds, depending on which of the interfaces from
the previous chapter is the current one). Such issues can be prevented
with the usage of
<code class="sourceCode default">std::chrono::duration_cast</code>:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>legacy_func<span class="op">(</span>duration_cast<span class="op">&lt;</span>seconds<span class="op">&gt;(</span>x<span class="op">.</span>vec<span class="op">[</span><span class="dv">0</span><span class="op">]).</span>count<span class="op">())</span>;</span></code></pre></div>
<p>However, users often forget about this step, especially when, at the
moment of writing such code, the duration stores the underlying raw
value in the expected unit. But as we know, the interface can be
refactored at any point to use a different unit, and the code using an
underlying numerical value without the usage of an explicit cast will
become incorrect.</p>
<p>To prevent such safety issues, the <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library exposes only the
interface that returns a quantity numerical value in the required unit
to ensure that no data truncation happens:</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>X x;</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>x<span class="op">.</span>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="dv">42</span> <span class="op">*</span> s<span class="op">)</span>;</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>legacy_func<span class="op">(</span>x<span class="op">.</span>vec<span class="op">[</span><span class="dv">0</span><span class="op">].</span>numerical_value_in<span class="op">(</span>si<span class="op">::</span>second<span class="op">))</span>;</span></code></pre></div>
<p>or in case we are fine with data truncation:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>X x;</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>x<span class="op">.</span>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="dv">42</span> <span class="op">*</span> s<span class="op">)</span>;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>legacy_func<span class="op">(</span>x<span class="op">.</span>vec<span class="op">[</span><span class="dv">0</span><span class="op">].</span>force_numerical_value_in<span class="op">(</span>si<span class="op">::</span>second<span class="op">))</span>;</span></code></pre></div>
<p>As the above member functions may need to do a conversion to provide
a value in the expected unit, their results are prvalues.</p>
<h2 data-number="7.6" id="preventing-dangling-references"><span class="header-section-number">7.6</span> Preventing dangling
references<a href="#preventing-dangling-references" class="self-link"></a></h2>
<p>Besides returning prvalues, sometimes users need to get an actual
reference to the underlying numerical value stored in a
<code class="sourceCode default">quantity</code>. For those cases, the
<span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library exposes <code class="sourceCode default">quantity::numerical_value_ref_in(Unit)</code>
that participates in overload resolution only:</p>
<ul>
<li>for lvalues (rvalue reference qualified overload is explicitly
deleted),</li>
<li>when the provided <code class="sourceCode default">Unit</code> has
the same magnitude as the one currently used by the quantity.</li>
</ul>
<p>The first condition above limits the possibility of dangling
references. We want to increase the chances that the reference/pointer
provided to an underlying API remains valid for the time of its usage.
Performance aspects for a
<code class="sourceCode default">quantity</code> type are secondary here
as we expect the majority (if not all) of representation types to be
cheap to copy, so we do not need to optimize for moving the value out
from the temporary object. With this condition unsatisfied, the
following code doesn’t compile:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> legacy_func<span class="op">(</span><span class="kw">const</span> <span class="dt">int</span><span class="op">&amp;</span> seconds<span class="op">)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>legacy_func<span class="op">((</span><span class="dv">4</span> <span class="op">*</span> s <span class="op">+</span> <span class="dv">2</span> <span class="op">*</span> s<span class="op">).</span>numerical_value_ref_in<span class="op">(</span>si<span class="op">::</span>second<span class="op">))</span>;  <span class="co">// Compile-time error</span></span></code></pre></div>
<p>The <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library
goes one step further, by implementing all compound assignments,
pre-increment, and pre-decrement operators as non-member functions that
preserve the initial value category. Thanks to that, the following will
also not compile:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>si<span class="op">::</span>second, <span class="dt">int</span><span class="op">&gt;</span> get_duration<span class="op">()</span>;</span></code></pre></div>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>legacy_func<span class="op">((</span><span class="dv">4</span> <span class="op">*</span> s <span class="op">+=</span> <span class="dv">2</span> <span class="op">*</span> s<span class="op">).</span>numerical_value_ref_in<span class="op">(</span>si<span class="op">::</span>second<span class="op">))</span>;    <span class="co">// Compile-time error</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>legacy_func<span class="op">((++</span>get_duration<span class="op">()).</span>numerical_value_ref_in<span class="op">(</span>si<span class="op">::</span>second<span class="op">))</span>;  <span class="co">// Compile-time error</span></span></code></pre></div>
<p>The second condition above enables the usage of various equivalent
units. For example, <code class="sourceCode default">J</code> is
equivalent to <code class="sourceCode default">N * m</code>, and
<code class="sourceCode default">kg * m2 / s2</code>. As those have the
same magnitude, it does not matter exactly which one is being used here,
as the same numerical value should be returned for all of them.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> legacy_func<span class="op">(</span><span class="kw">const</span> <span class="dt">int</span><span class="op">&amp;</span> joules<span class="op">)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>quantity q1 <span class="op">=</span> <span class="dv">42</span> <span class="op">*</span> J;</span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>quantity q2 <span class="op">=</span> <span class="dv">42</span> <span class="op">*</span> N <span class="op">*</span> <span class="op">(</span><span class="dv">2</span> <span class="op">*</span> m<span class="op">)</span>;</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>quantity q3 <span class="op">=</span> <span class="dv">42</span> <span class="op">*</span> kJ;</span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>legacy_func<span class="op">(</span>q1<span class="op">.</span>numerical_value_ref_in<span class="op">(</span>si<span class="op">::</span>joule<span class="op">))</span>; <span class="co">// OK</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>legacy_func<span class="op">(</span>q2<span class="op">.</span>numerical_value_ref_in<span class="op">(</span>si<span class="op">::</span>joule<span class="op">))</span>; <span class="co">// OK</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>legacy_func<span class="op">(</span>q3<span class="op">.</span>numerical_value_ref_in<span class="op">(</span>si<span class="op">::</span>joule<span class="op">))</span>; <span class="co">// Compile-time error</span></span></code></pre></div>
<p>Here are a few examples provided by our users where enabling a
quantity type to return a reference to its underlying numerical value is
required:</p>
<ul>
<li><p>Interoperability with the <a href="https://github.com/ocornut/imgui/blob/19ae142bdddf9fcb840549b4b1279739a36c3fa6/imgui.h#L551">Dear
ImGui</a>:</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>IMGUI_API <span class="dt">bool</span> DragInt<span class="op">(</span><span class="kw">const</span> <span class="dt">char</span><span class="op">*</span> label, <span class="dt">int</span><span class="op">*</span> v,</span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>                       <span class="dt">float</span> v_speed <span class="op">=</span> <span class="fl">1.0</span><span class="bu">f</span>, <span class="dt">int</span> v_min <span class="op">=</span> <span class="dv">0</span>, <span class="dt">int</span> v_max <span class="op">=</span> <span class="dv">0</span>,</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">const</span> <span class="dt">char</span><span class="op">*</span> format <span class="op">=</span> <span class="st">&quot;</span><span class="sc">%d</span><span class="st">&quot;</span>, ImGuiSliderFlags flags <span class="op">=</span> <span class="dv">0</span><span class="op">)</span>;  <span class="co">// If v_min &gt;= v_max we have no bound</span></span></code></pre></div>
<div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>ImGui<span class="op">::</span>DragInt<span class="op">(</span><span class="st">&quot;Frames&quot;</span>, <span class="op">&amp;</span>frame_frequency<span class="op">.</span>value<span class="op">.</span>numerical_value_ref_in<span class="op">(</span>Hz<span class="op">)</span>, <span class="dv">1</span>,</span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>               frame_frequency<span class="op">.</span>min<span class="op">.</span>numerical_value_in<span class="op">(</span>Hz<span class="op">)</span>, </span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>               frame_frequency<span class="op">.</span>max<span class="op">.</span>numerical_value_in<span class="op">(</span>Hz<span class="op">)</span>, </span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>               <span class="st">&quot;</span><span class="sc">%d</span><span class="st"> Hz&quot;</span><span class="op">)</span>;</span></code></pre></div></li>
<li><p>Obtaining a temperature via the C library:</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="co">// read_temperature is in the BSP defined as </span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> read_temperature<span class="op">(</span><span class="dt">float</span><span class="op">*</span> temp_in_celsius<span class="op">)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> Celsius_point <span class="op">=</span> quantity_point<span class="op">&lt;</span>isq<span class="op">::</span>Celsius_temperature<span class="op">[</span>deg_C<span class="op">]</span>, si<span class="op">::</span>ice_point, <span class="dt">float</span><span class="op">&gt;</span>;</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>Celsius_point temp;</span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>read_temperature<span class="op">(&amp;</span>temp<span class="op">.</span>quantity_ref_from<span class="op">(</span>si<span class="op">::</span>ice_point<span class="op">).</span>numerical_value_ref_in<span class="op">(</span>si<span class="op">::</span>degree_Celsius<span class="op">))</span>;</span></code></pre></div></li>
</ul>
<p>As we can see in the second example,
<code class="sourceCode default">quantity_point</code> also provides an
lvalue-ref-qualified
<code class="sourceCode default">quantity_ref_from(PointOrigin)</code>
member function that returns a reference to its stored
<code class="sourceCode default">quantity</code>. Also, for reasons
similar to the ones described in the previous chapter, this function
requires that the argument provided by the user is the same as the
origin of a quantity point.</p>
<h2 data-number="7.7" id="quantity-kinds"><span class="header-section-number">7.7</span> Quantity kinds<a href="#quantity-kinds" class="self-link"></a></h2>
<p>What should be the result of the following quantity equation?</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> res <span class="op">=</span> <span class="dv">1</span> <span class="op">*</span> Hz <span class="op">+</span> <span class="dv">1</span> <span class="op">*</span> Bq <span class="op">+</span> <span class="dv">1</span> <span class="op">*</span> Bd;</span></code></pre></div>
<p>We have checked a few leading libraries on the market, and here are
the results:</p>
<ul>
<li><span class="citation" data-cites="BOOST-UNITS">[<a href="#ref-BOOST-UNITS" role="doc-biblioref">Boost.Units</a>]</span>
claims the answer to be 2 Hz (bauds are not supported by it, so we
removed it from the equation),</li>
<li><span class="citation" data-cites="NIC-UNITS">[<a href="#ref-NIC-UNITS" role="doc-biblioref">nholthaus/units</a>]</span>
claims it is 2 s<sup>-1</sup> (no support for bauds as well),</li>
<li><span class="citation" data-cites="PINT">[<a href="#ref-PINT" role="doc-biblioref">Pint</a>]</span> library in Python claims that the
result is 3.0 Hz,</li>
<li><span class="citation" data-cites="JSR-385">[<a href="#ref-JSR-385" role="doc-biblioref">JSR 385</a>]</span> library in Java throws an
exception saying that we can’t add those quantities.</li>
</ul>
<p>Now let’s check what <span class="citation" data-cites="ISO-GUIDE">[<a href="#ref-ISO-GUIDE" role="doc-biblioref">ISO/IEC Guide 99</a>]</span> says about quantity
kinds:</p>
<ul>
<li>Quantities may be grouped together into categories of quantities
that are <strong>mutually comparable</strong></li>
<li>Mutually comparable quantities are called <strong>quantities of the
same kind</strong></li>
<li>Two or more quantities <strong>cannot be added or subtracted unless
they belong to the same category of mutually comparable
quantities</strong></li>
<li>Quantities of the <strong>same kind</strong> within a given system
of quantities <strong>have the same quantity dimension</strong></li>
<li>Quantities of the <strong>same dimension are not necessarily of the
same kind</strong></li>
</ul>
<p><span class="citation" data-cites="ISO80000">[<a href="#ref-ISO80000" role="doc-biblioref">ISO 80000</a>]</span> also explicitly notes:</p>
<blockquote>
<p><strong>Measurement units of quantities of the same quantity
dimension may be designated by the same name and symbol even when the
quantities are not of the same kind</strong>. For example, joule per
kelvin and J/K are respectively the name and symbol of both a
measurement unit of heat capacity and a measurement unit of entropy,
which are generally not considered to be quantities of the same kind.
<strong>However, in some cases special measurement unit names are
restricted to be used with quantities of specific kind only</strong>.
For example, the measurement unit ‘second to the power minus one’ (1/s)
is called hertz (Hz) when used for frequencies and becquerel (Bq) when
used for activities of radionuclides. As another example, the joule (J)
is used as a unit of energy, but never as a unit of moment of force,
i.e. the newton metre (N · m).</p>
</blockquote>
<p>To summarize the above, <span class="citation" data-cites="ISO80000">[<a href="#ref-ISO80000" role="doc-biblioref">ISO
80000</a>]</span> explicitly states that frequency is measured in Hz and
activity is measured in Bq, which are quantities of different kinds. As
such, they should not be able to be compared, added, or subtracted. So,
the only library from the above that was correct was <span class="citation" data-cites="JSR-385">[<a href="#ref-JSR-385" role="doc-biblioref">JSR 385</a>]</span>. The rest of them are wrong to
allow such operations. Doing so may lead to vulnerable safety issues
when two unrelated quantities of the same dimension are accidentally
added or assigned to each other.</p>
<p>The reason for most of the libraries on the market to be wrong in
this field is the fact that their quantities are implemented only in
terms of the concept of dimension. However, we’ve just learned that a
dimension is not enough to express a quantity type.</p>
<p>The <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library
goes beyond that and properly models quantity kinds. We believe that it
is a significant feature that improves the safety of the library, and
that is why we also plan to propose quantity kinds for standardization
as mentioned in <span class="citation" data-cites="P2980_PRE">[<a href="#ref-P2980_PRE" role="doc-biblioref">P2980</a>]</span>.</p>
<h2 data-number="7.8" id="various-quantities-of-the-same-kind"><span class="header-section-number">7.8</span> Various quantities of the same
kind<a href="#various-quantities-of-the-same-kind" class="self-link"></a></h2>
<p>Proper modeling of distinct kinds for quantities of the same
dimension is often not enough from the safety point of view. Most of the
libraries allow us to write the following code in the type-safe way:</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>speed<span class="op">[</span>m<span class="op">/</span>s<span class="op">]&gt;</span> avg_speed<span class="op">(</span>quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">[</span>m<span class="op">]&gt;</span> l, quantity<span class="op">&lt;</span>isq<span class="op">::</span>time<span class="op">[</span>s<span class="op">]&gt;</span> t<span class="op">)</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> l <span class="op">/</span> t;</span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>However, they fail when we need to model an abstraction using more
than one quantity of the same kind:</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Box <span class="op">{</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>  quantity<span class="op">&lt;</span>isq<span class="op">::</span>area<span class="op">[</span>m2<span class="op">]&gt;</span> base_;</span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>  quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">[</span>m<span class="op">]&gt;</span> height_;</span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>  Box<span class="op">(</span>quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">[</span>m<span class="op">]&gt;</span> l, quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">[</span>m<span class="op">]&gt;</span> w, quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">[</span>m<span class="op">]&gt;</span> h<span class="op">)</span></span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> base_<span class="op">(</span>l <span class="op">*</span> w<span class="op">)</span>, height_<span class="op">(</span>h<span class="op">)</span></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">{}</span></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>This does not provide strongly typed interfaces anymore.</p>
<p>Again, it turns out that <span class="citation" data-cites="ISO80000">[<a href="#ref-ISO80000" role="doc-biblioref">ISO
80000</a>]</span> has an answer. This specification standardizes
hundreds of quantities, many of which are of the same kind. For example,
for quantities of the kind length, it provides the following:</p>
<p><img src="data:image/svg+xml;base64,PHN2ZyBhcmlhLXJvbGVkZXNjcmlwdGlvbj0iZmxvd2NoYXJ0LXYyIiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgdmlld0JveD0iLTggLTggMTA3Ny4xOTE0MDYyNSAzNDYiIHN0eWxlPSJtYXgtd2lkdGg6IDEwMCU7IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBpZD0iZ3JhcGgtZGl2IiBoZWlnaHQ9IjEwMCUiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48c3R5bGU+QGltcG9ydCB1cmwoImh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL2ZvbnQtYXdlc29tZS82LjQuMi9jc3MvYWxsLm1pbi5jc3MiKTsnPC9zdHlsZT48c3R5bGU+I2dyYXBoLWRpdntmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7ZmlsbDojMzMzO30jZ3JhcGgtZGl2IC5lcnJvci1pY29ue2ZpbGw6IzU1MjIyMjt9I2dyYXBoLWRpdiAuZXJyb3ItdGV4dHtmaWxsOiM1NTIyMjI7c3Ryb2tlOiM1NTIyMjI7fSNncmFwaC1kaXYgLmVkZ2UtdGhpY2tuZXNzLW5vcm1hbHtzdHJva2Utd2lkdGg6MnB4O30jZ3JhcGgtZGl2IC5lZGdlLXRoaWNrbmVzcy10aGlja3tzdHJva2Utd2lkdGg6My41cHg7fSNncmFwaC1kaXYgLmVkZ2UtcGF0dGVybi1zb2xpZHtzdHJva2UtZGFzaGFycmF5OjA7fSNncmFwaC1kaXYgLmVkZ2UtcGF0dGVybi1kYXNoZWR7c3Ryb2tlLWRhc2hhcnJheTozO30jZ3JhcGgtZGl2IC5lZGdlLXBhdHRlcm4tZG90dGVke3N0cm9rZS1kYXNoYXJyYXk6Mjt9I2dyYXBoLWRpdiAubWFya2Vye2ZpbGw6IzMzMzMzMztzdHJva2U6IzMzMzMzMzt9I2dyYXBoLWRpdiAubWFya2VyLmNyb3Nze3N0cm9rZTojMzMzMzMzO30jZ3JhcGgtZGl2IHN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7fSNncmFwaC1kaXYgLmxhYmVse2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojMzMzO30jZ3JhcGgtZGl2IC5jbHVzdGVyLWxhYmVsIHRleHR7ZmlsbDojMzMzO30jZ3JhcGgtZGl2IC5jbHVzdGVyLWxhYmVsIHNwYW4sI2dyYXBoLWRpdiBwe2NvbG9yOiMzMzM7fSNncmFwaC1kaXYgLmxhYmVsIHRleHQsI2dyYXBoLWRpdiBzcGFuLCNncmFwaC1kaXYgcHtmaWxsOiMzMzM7Y29sb3I6IzMzMzt9I2dyYXBoLWRpdiAubm9kZSByZWN0LCNncmFwaC1kaXYgLm5vZGUgY2lyY2xlLCNncmFwaC1kaXYgLm5vZGUgZWxsaXBzZSwjZ3JhcGgtZGl2IC5ub2RlIHBvbHlnb24sI2dyYXBoLWRpdiAubm9kZSBwYXRoe2ZpbGw6I0VDRUNGRjtzdHJva2U6IzkzNzBEQjtzdHJva2Utd2lkdGg6MXB4O30jZ3JhcGgtZGl2IC5mbG93Y2hhcnQtbGFiZWwgdGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7fSNncmFwaC1kaXYgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jZ3JhcGgtZGl2IC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I2dyYXBoLWRpdiAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNncmFwaC1kaXYgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojMzMzMzMzO3N0cm9rZS13aWR0aDoyLjBweDt9I2dyYXBoLWRpdiAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiMzMzMzMzM7ZmlsbDpub25lO30jZ3JhcGgtZGl2IC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O3RleHQtYWxpZ246Y2VudGVyO30jZ3JhcGgtZGl2IC5lZGdlTGFiZWwgcmVjdHtvcGFjaXR5OjAuNTtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7ZmlsbDojZThlOGU4O30jZ3JhcGgtZGl2IC5sYWJlbEJrZ3tiYWNrZ3JvdW5kLWNvbG9yOnJnYmEoMjMyLCAyMzIsIDIzMiwgMC41KTt9I2dyYXBoLWRpdiAuY2x1c3RlciByZWN0e2ZpbGw6I2ZmZmZkZTtzdHJva2U6I2FhYWEzMztzdHJva2Utd2lkdGg6MXB4O30jZ3JhcGgtZGl2IC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jZ3JhcGgtZGl2IC5jbHVzdGVyIHNwYW4sI2dyYXBoLWRpdiBwe2NvbG9yOiMzMzM7fSNncmFwaC1kaXYgZGl2Lm1lcm1haWRUb29sdGlwe3Bvc2l0aW9uOmFic29sdXRlO3RleHQtYWxpZ246Y2VudGVyO21heC13aWR0aDoyMDBweDtwYWRkaW5nOjJweDtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEycHg7YmFja2dyb3VuZDpoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKTtib3JkZXI6MXB4IHNvbGlkICNhYWFhMzM7Ym9yZGVyLXJhZGl1czoycHg7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjEwMDt9I2dyYXBoLWRpdiAuZmxvd2NoYXJ0VGl0bGVUZXh0e3RleHQtYW5jaG9yOm1pZGRsZTtmb250LXNpemU6MThweDtmaWxsOiMzMzM7fSNncmFwaC1kaXYgOnJvb3R7LS1tZXJtYWlkLWZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjt9PC9zdHlsZT48Zz48bWFya2VyIG9yaWVudD0iYXV0byIgbWFya2VySGVpZ2h0PSIxMiIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIHJlZlk9IjUiIHJlZlg9IjYiIHZpZXdCb3g9IjAgMCAxMCAxMCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIGlkPSJncmFwaC1kaXZfZmxvd2NoYXJ0LXBvaW50RW5kIj48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgZD0iTSAwIDAgTCAxMCA1IEwgMCAxMCB6Ij48L3BhdGg+PC9tYXJrZXI+PG1hcmtlciBvcmllbnQ9ImF1dG8iIG1hcmtlckhlaWdodD0iMTIiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiByZWZZPSI1IiByZWZYPSI0LjUiIHZpZXdCb3g9IjAgMCAxMCAxMCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIGlkPSJncmFwaC1kaXZfZmxvd2NoYXJ0LXBvaW50U3RhcnQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBkPSJNIDAgNSBMIDEwIDEwIEwgMTAgMCB6Ij48L3BhdGg+PC9tYXJrZXI+PG1hcmtlciBvcmllbnQ9ImF1dG8iIG1hcmtlckhlaWdodD0iMTEiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiByZWZZPSI1IiByZWZYPSIxMSIgdmlld0JveD0iMCAwIDEwIDEwIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgaWQ9ImdyYXBoLWRpdl9mbG93Y2hhcnQtY2lyY2xlRW5kIj48Y2lyY2xlIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiByPSI1IiBjeT0iNSIgY3g9IjUiPjwvY2lyY2xlPjwvbWFya2VyPjxtYXJrZXIgb3JpZW50PSJhdXRvIiBtYXJrZXJIZWlnaHQ9IjExIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgcmVmWT0iNSIgcmVmWD0iLTEiIHZpZXdCb3g9IjAgMCAxMCAxMCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIGlkPSJncmFwaC1kaXZfZmxvd2NoYXJ0LWNpcmNsZVN0YXJ0Ij48Y2lyY2xlIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiByPSI1IiBjeT0iNSIgY3g9IjUiPjwvY2lyY2xlPjwvbWFya2VyPjxtYXJrZXIgb3JpZW50PSJhdXRvIiBtYXJrZXJIZWlnaHQ9IjExIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgcmVmWT0iNS4yIiByZWZYPSIxMiIgdmlld0JveD0iMCAwIDExIDExIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgaWQ9ImdyYXBoLWRpdl9mbG93Y2hhcnQtY3Jvc3NFbmQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5Ij48L3BhdGg+PC9tYXJrZXI+PG1hcmtlciBvcmllbnQ9ImF1dG8iIG1hcmtlckhlaWdodD0iMTEiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiByZWZZPSI1LjIiIHJlZlg9Ii0xIiB2aWV3Qm94PSIwIDAgMTEgMTEiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiBpZD0iZ3JhcGgtZGl2X2Zsb3djaGFydC1jcm9zc1N0YXJ0Ij48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSI+PC9wYXRoPjwvbWFya2VyPjxnIGNsYXNzPSJyb290Ij48ZyBjbGFzcz0iY2x1c3RlcnMiPjwvZz48ZyBjbGFzcz0iZWRnZVBhdGhzIj48cGF0aCBzdHlsZT0iZmlsbDpub25lOyIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbGVuZ3RoIExFLXdpZHRoIiBpZD0iTC1sZW5ndGgtd2lkdGgtMCIgZD0iTTYxNi4wOTgsMjIuMDgxTDUzNC40OCwyOS4wNjhDNDUyLjg2MywzNi4wNTQsMjg5LjYyOSw1MC4wMjcsMjA4LjAxMiw2My4xOEMxMjYuMzk1LDc2LjMzMywxMjYuMzk1LDg4LjY2NywxMjYuMzk1LDk0LjgzM0wxMjYuMzk1LDEwMSI+PC9wYXRoPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7IiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1sZW5ndGggTEUtaGVpZ2h0IiBpZD0iTC1sZW5ndGgtaGVpZ2h0LTAiIGQ9Ik02MTYuMDk4LDIzLjc5TDU2OC45OTEsMzAuNDkyQzUyMS44ODQsMzcuMTkzLDQyNy42NzEsNTAuNTk3LDM4MC41NjQsNjMuNDY1QzMzMy40NTcsNzYuMzMzLDMzMy40NTcsODguNjY3LDMzMy40NTcsOTQuODMzTDMzMy40NTcsMTAxIj48L3BhdGg+PHBhdGggc3R5bGU9ImZpbGw6bm9uZTsiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLXdpZHRoIExFLXRoaWNrbmVzcyIgaWQ9Ikwtd2lkdGgtdGhpY2tuZXNzLTAiIGQ9Ik05Ni43NiwxNDBMODcuMzg5LDE0Ni4xNjdDNzguMDE3LDE1Mi4zMzMsNTkuMjc0LDE2NC42NjcsNDkuOTAzLDE3NUM0MC41MzEsMTg1LjMzMyw0MC41MzEsMTkzLjY2Nyw0MC41MzEsMTk3LjgzM0w0MC41MzEsMjAyIj48L3BhdGg+PHBhdGggc3R5bGU9ImZpbGw6bm9uZTsiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLXdpZHRoIExFLWRpYW1ldGVyIiBpZD0iTC13aWR0aC1kaWFtZXRlci0wIiBkPSJNMTQxLjg0MywxNDBMMTQ2LjcyOSwxNDYuMTY3QzE1MS42MTQsMTUyLjMzMywxNjEuMzg1LDE2NC42NjcsMTY2LjI3MSwxNzVDMTcxLjE1NiwxODUuMzMzLDE3MS4xNTYsMTkzLjY2NywxNzEuMTU2LDE5Ny44MzNMMTcxLjE1NiwyMDIiPjwvcGF0aD48cGF0aCBzdHlsZT0iZmlsbDpub25lOyIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtd2lkdGggTEUtcmFkaXVzIiBpZD0iTC13aWR0aC1yYWRpdXMtMCIgZD0iTTE4My4wMDMsMTQwTDIwMC45MDUsMTQ2LjE2N0MyMTguODA3LDE1Mi4zMzMsMjU0LjYxLDE2NC42NjcsMjcyLjUxMiwxNzVDMjkwLjQxNCwxODUuMzMzLDI5MC40MTQsMTkzLjY2NywyOTAuNDE0LDE5Ny44MzNMMjkwLjQxNCwyMDIiPjwvcGF0aD48cGF0aCBzdHlsZT0iZmlsbDpub25lOyIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbGVuZ3RoIExFLXBhdGhfbGVuZ3RoIiBpZD0iTC1sZW5ndGgtcGF0aF9sZW5ndGgtMCIgZD0iTTYxNi4wOTgsMzAuNzQ1TDYwMS4yMzQsMzYuMjg4QzU4Ni4zNzEsNDEuODMsNTU2LjY0NSw1Mi45MTUsNTQxLjc4MSw2NC42MjRDNTI2LjkxOCw3Ni4zMzMsNTI2LjkxOCw4OC42NjcsNTI2LjkxOCw5NC44MzNMNTI2LjkxOCwxMDEiPjwvcGF0aD48cGF0aCBzdHlsZT0iZmlsbDpub25lOyIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtcGF0aF9sZW5ndGggTEUtZGlzdGFuY2UiIGlkPSJMLXBhdGhfbGVuZ3RoLWRpc3RhbmNlLTAiIGQ9Ik01MjYuOTE4LDE0MEw1MjYuOTE4LDE0Ni4xNjdDNTI2LjkxOCwxNTIuMzMzLDUyNi45MTgsMTY0LjY2Nyw1MjYuOTE4LDE3NUM1MjYuOTE4LDE4NS4zMzMsNTI2LjkxOCwxOTMuNjY3LDUyNi45MTgsMTk3LjgzM0w1MjYuOTE4LDIwMiI+PC9wYXRoPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7IiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1kaXN0YW5jZSBMRS1yYWRpYWxfZGlzdGFuY2UiIGlkPSJMLWRpc3RhbmNlLXJhZGlhbF9kaXN0YW5jZS0wIiBkPSJNNTI2LjkxOCwyNDFMNTI2LjkxOCwyNDUuMTY3QzUyNi45MTgsMjQ5LjMzMyw1MjYuOTE4LDI1Ny42NjcsNTI2LjkxOCwyNjZDNTI2LjkxOCwyNzQuMzMzLDUyNi45MTgsMjgyLjY2Nyw1MjYuOTE4LDI4Ni44MzNMNTI2LjkxOCwyOTEiPjwvcGF0aD48cGF0aCBzdHlsZT0iZmlsbDpub25lOyIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbGVuZ3RoIExFLXdhdmVsZW5ndGgiIGlkPSJMLWxlbmd0aC13YXZlbGVuZ3RoLTAiIGQ9Ik02NTkuMzE4LDM5TDY2Mi4xMDksNDMuMTY3QzY2NC45MDEsNDcuMzMzLDY3MC40ODQsNTUuNjY3LDY3My4yNzUsNjZDNjc2LjA2Niw3Ni4zMzMsNjc2LjA2Niw4OC42NjcsNjc2LjA2Niw5NC44MzNMNjc2LjA2NiwxMDEiPjwvcGF0aD48cGF0aCBzdHlsZT0iZmlsbDpub25lOyIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbGVuZ3RoIExFLXBvc2l0aW9uX3ZlY3RvciIgaWQ9IkwtbGVuZ3RoLXBvc2l0aW9uX3ZlY3Rvci0wIiBkPSJNNjc2LjQxLDI2LjUxNUw3MDMuMjY4LDMyLjc2MkM3MzAuMTI2LDM5LjAxLDc4My44NDIsNTEuNTA1LDgxMC43MDEsNjEuOTE5QzgzNy41NTksNzIuMzMzLDgzNy41NTksODAuNjY3LDgzNy41NTksODQuODMzTDgzNy41NTksODkiPjwvcGF0aD48cGF0aCBzdHlsZT0iZmlsbDpub25lOyIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbGVuZ3RoIExFLWRpc3BsYWNlbWVudCIgaWQ9IkwtbGVuZ3RoLWRpc3BsYWNlbWVudC0wIiBkPSJNNjc2LjQxLDIzLjIzMkw3MzEuMzEzLDMwLjAyN0M3ODYuMjE1LDM2LjgyMSw4OTYuMDIsNTAuNDExLDk1MC45MjIsNjEuMzcyQzEwMDUuODI0LDcyLjMzMywxMDA1LjgyNCw4MC42NjcsMTAwNS44MjQsODQuODMzTDEwMDUuODI0LDg5Ij48L3BhdGg+PHBhdGggc3R5bGU9ImZpbGw6bm9uZTsiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLXJhZGl1cyBMRS1yYWRpdXNfb2ZfY3VydmF0dXJlIiBpZD0iTC1yYWRpdXMtcmFkaXVzX29mX2N1cnZhdHVyZS0wIiBkPSJNMjkwLjQxNCwyNDFMMjkwLjQxNCwyNDUuMTY3QzI5MC40MTQsMjQ5LjMzMywyOTAuNDE0LDI1Ny42NjcsMjkwLjQxNCwyNjZDMjkwLjQxNCwyNzQuMzMzLDI5MC40MTQsMjgyLjY2NywyOTAuNDE0LDI4Ni44MzNMMjkwLjQxNCwyOTEiPjwvcGF0aD48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIiBjbGFzcz0ibGFiZWwiPjxmb3JlaWduT2JqZWN0IGhlaWdodD0iMCIgd2lkdGg9IjAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiIGNsYXNzPSJsYWJlbCI+PGZvcmVpZ25PYmplY3QgaGVpZ2h0PSIwIiB3aWR0aD0iMCI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSIgY2xhc3M9ImxhYmVsIj48Zm9yZWlnbk9iamVjdCBoZWlnaHQ9IjAiIHdpZHRoPSIwIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIiBjbGFzcz0ibGFiZWwiPjxmb3JlaWduT2JqZWN0IGhlaWdodD0iMCIgd2lkdGg9IjAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiIGNsYXNzPSJsYWJlbCI+PGZvcmVpZ25PYmplY3QgaGVpZ2h0PSIwIiB3aWR0aD0iMCI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSIgY2xhc3M9ImxhYmVsIj48Zm9yZWlnbk9iamVjdCBoZWlnaHQ9IjAiIHdpZHRoPSIwIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIiBjbGFzcz0ibGFiZWwiPjxmb3JlaWduT2JqZWN0IGhlaWdodD0iMCIgd2lkdGg9IjAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiIGNsYXNzPSJsYWJlbCI+PGZvcmVpZ25PYmplY3QgaGVpZ2h0PSIwIiB3aWR0aD0iMCI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSIgY2xhc3M9ImxhYmVsIj48Zm9yZWlnbk9iamVjdCBoZWlnaHQ9IjAiIHdpZHRoPSIwIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIiBjbGFzcz0ibGFiZWwiPjxmb3JlaWduT2JqZWN0IGhlaWdodD0iMCIgd2lkdGg9IjAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiIGNsYXNzPSJsYWJlbCI+PGZvcmVpZ25PYmplY3QgaGVpZ2h0PSIwIiB3aWR0aD0iMCI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSIgY2xhc3M9ImxhYmVsIj48Zm9yZWlnbk9iamVjdCBoZWlnaHQ9IjAiIHdpZHRoPSIwIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZXMiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDY0Ni4yNTM5MDYyNSwgMTkuNSkiIGlkPSJmbG93Y2hhcnQtbGVuZ3RoLTY4ODIiIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiPjxyZWN0IGhlaWdodD0iMzkiIHdpZHRoPSI2MC4zMTI1IiB5PSItMTkuNSIgeD0iLTMwLjE1NjI1IiByeT0iMCIgcng9IjAiIHN0eWxlPSIiIGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiPjwvcmVjdD48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjIuNjU2MjUsIC0xMikiIHN0eWxlPSIiIGNsYXNzPSJsYWJlbCI+PHJlY3Q+PC9yZWN0Pjxmb3JlaWduT2JqZWN0IGhlaWdodD0iMjQiIHdpZHRoPSI0NS4zMTI1Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+bGVuZ3RoPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyNi4zOTQ1MzEyNSwgMTIwLjUpIiBpZD0iZmxvd2NoYXJ0LXdpZHRoLTY4ODMiIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiPjxyZWN0IGhlaWdodD0iMzkiIHdpZHRoPSIxMjguMzEyNSIgeT0iLTE5LjUiIHg9Ii02NC4xNTYyNSIgcnk9IjAiIHJ4PSIwIiBzdHlsZT0iIiBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIj48L3JlY3Q+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTU2LjY1NjI1LCAtMTIpIiBzdHlsZT0iIiBjbGFzcz0ibGFiZWwiPjxyZWN0PjwvcmVjdD48Zm9yZWlnbk9iamVjdCBoZWlnaHQ9IjI0IiB3aWR0aD0iMTEzLjMxMjUiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj53aWR0aCAoYnJlYWR0aCk8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzMzLjQ1NzAzMTI1LCAxMjAuNSkiIGlkPSJmbG93Y2hhcnQtaGVpZ2h0LTY4ODUiIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiPjxyZWN0IGhlaWdodD0iMzkiIHdpZHRoPSIxODUuODEyNSIgeT0iLTE5LjUiIHg9Ii05Mi45MDYyNSIgcnk9IjAiIHJ4PSIwIiBzdHlsZT0iIiBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIj48L3JlY3Q+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTg1LjQwNjI1LCAtMTIpIiBzdHlsZT0iIiBjbGFzcz0ibGFiZWwiPjxyZWN0PjwvcmVjdD48Zm9yZWlnbk9iamVjdCBoZWlnaHQ9IjI0IiB3aWR0aD0iMTcwLjgxMjUiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5oZWlnaHQgKGRlcHRoLCBhbHRpdHVkZSk8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDAuNTMxMjUsIDIyMS41KSIgaWQ9ImZsb3djaGFydC10aGlja25lc3MtNjg4NyIgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCI+PHJlY3QgaGVpZ2h0PSIzOSIgd2lkdGg9IjgxLjA2MjUiIHk9Ii0xOS41IiB4PSItNDAuNTMxMjUiIHJ5PSIwIiByeD0iMCIgc3R5bGU9IiIgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciI+PC9yZWN0PjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0zMy4wMzEyNSwgLTEyKSIgc3R5bGU9IiIgY2xhc3M9ImxhYmVsIj48cmVjdD48L3JlY3Q+PGZvcmVpZ25PYmplY3QgaGVpZ2h0PSIyNCIgd2lkdGg9IjY2LjA2MjUiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj50aGlja25lc3M8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTcxLjE1NjI1LCAyMjEuNSkiIGlkPSJmbG93Y2hhcnQtZGlhbWV0ZXItNjg4OSIgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCI+PHJlY3QgaGVpZ2h0PSIzOSIgd2lkdGg9IjgwLjE4NzUiIHk9Ii0xOS41IiB4PSItNDAuMDkzNzUiIHJ5PSIwIiByeD0iMCIgc3R5bGU9IiIgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciI+PC9yZWN0PjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0zMi41OTM3NSwgLTEyKSIgc3R5bGU9IiIgY2xhc3M9ImxhYmVsIj48cmVjdD48L3JlY3Q+PGZvcmVpZ25PYmplY3QgaGVpZ2h0PSIyNCIgd2lkdGg9IjY1LjE4NzUiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5kaWFtZXRlcjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyOTAuNDE0MDYyNSwgMjIxLjUpIiBpZD0iZmxvd2NoYXJ0LXJhZGl1cy02ODkxIiBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIj48cmVjdCBoZWlnaHQ9IjM5IiB3aWR0aD0iNTguMzI4MTI1IiB5PSItMTkuNSIgeD0iLTI5LjE2NDA2MjUiIHJ5PSIwIiByeD0iMCIgc3R5bGU9IiIgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciI+PC9yZWN0PjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMS42NjQwNjI1LCAtMTIpIiBzdHlsZT0iIiBjbGFzcz0ibGFiZWwiPjxyZWN0PjwvcmVjdD48Zm9yZWlnbk9iamVjdCBoZWlnaHQ9IjI0IiB3aWR0aD0iNDMuMzI4MTI1Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+cmFkaXVzPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDUyNi45MTc5Njg3NSwgMTIwLjUpIiBpZD0iZmxvd2NoYXJ0LXBhdGhfbGVuZ3RoLTY4OTMiIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiPjxyZWN0IGhlaWdodD0iMzkiIHdpZHRoPSIxMDEuMTA5Mzc1IiB5PSItMTkuNSIgeD0iLTUwLjU1NDY4NzUiIHJ5PSIwIiByeD0iMCIgc3R5bGU9IiIgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciI+PC9yZWN0PjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC00My4wNTQ2ODc1LCAtMTIpIiBzdHlsZT0iIiBjbGFzcz0ibGFiZWwiPjxyZWN0PjwvcmVjdD48Zm9yZWlnbk9iamVjdCBoZWlnaHQ9IjI0IiB3aWR0aD0iODYuMTA5Mzc1Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+cGF0aF9sZW5ndGg8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTI2LjkxNzk2ODc1LCAyMjEuNSkiIGlkPSJmbG93Y2hhcnQtZGlzdGFuY2UtNjg5NSIgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCI+PHJlY3QgaGVpZ2h0PSIzOSIgd2lkdGg9Ijc1LjA5Mzc1IiB5PSItMTkuNSIgeD0iLTM3LjU0Njg3NSIgcnk9IjAiIHJ4PSIwIiBzdHlsZT0iIiBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIj48L3JlY3Q+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTMwLjA0Njg3NSwgLTEyKSIgc3R5bGU9IiIgY2xhc3M9ImxhYmVsIj48cmVjdD48L3JlY3Q+PGZvcmVpZ25PYmplY3QgaGVpZ2h0PSIyNCIgd2lkdGg9IjYwLjA5Mzc1Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+ZGlzdGFuY2U8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTI2LjkxNzk2ODc1LCAzMTAuNSkiIGlkPSJmbG93Y2hhcnQtcmFkaWFsX2Rpc3RhbmNlLTY4OTciIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiPjxyZWN0IGhlaWdodD0iMzkiIHdpZHRoPSIxMjQuNzE4NzUiIHk9Ii0xOS41IiB4PSItNjIuMzU5Mzc1IiByeT0iMCIgcng9IjAiIHN0eWxlPSIiIGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiPjwvcmVjdD48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNTQuODU5Mzc1LCAtMTIpIiBzdHlsZT0iIiBjbGFzcz0ibGFiZWwiPjxyZWN0PjwvcmVjdD48Zm9yZWlnbk9iamVjdCBoZWlnaHQ9IjI0IiB3aWR0aD0iMTA5LjcxODc1Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+cmFkaWFsX2Rpc3RhbmNlPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDY3Ni4wNjY0MDYyNSwgMTIwLjUpIiBpZD0iZmxvd2NoYXJ0LXdhdmVsZW5ndGgtNjg5OSIgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCI+PHJlY3QgaGVpZ2h0PSIzOSIgd2lkdGg9Ijk3LjE4NzUiIHk9Ii0xOS41IiB4PSItNDguNTkzNzUiIHJ5PSIwIiByeD0iMCIgc3R5bGU9IiIgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciI+PC9yZWN0PjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC00MS4wOTM3NSwgLTEyKSIgc3R5bGU9IiIgY2xhc3M9ImxhYmVsIj48cmVjdD48L3JlY3Q+PGZvcmVpZ25PYmplY3QgaGVpZ2h0PSIyNCIgd2lkdGg9IjgyLjE4NzUiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj53YXZlbGVuZ3RoPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDgzNy41NTg1OTM3NSwgMTIwLjUpIiBpZD0iZmxvd2NoYXJ0LXBvc2l0aW9uX3ZlY3Rvci02OTAxIiBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIj48cmVjdCBoZWlnaHQ9IjYzIiB3aWR0aD0iMTI1Ljc5Njg3NSIgeT0iLTMxLjUiIHg9Ii02Mi44OTg0Mzc1IiByeT0iMCIgcng9IjAiIHN0eWxlPSIiIGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiPjwvcmVjdD48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNTUuMzk4NDM3NSwgLTI0KSIgc3R5bGU9IiIgY2xhc3M9ImxhYmVsIj48cmVjdD48L3JlY3Q+PGZvcmVpZ25PYmplY3QgaGVpZ2h0PSI0OCIgd2lkdGg9IjExMC43OTY4NzUiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5wb3NpdGlvbl92ZWN0b3I8YnIvPnt2ZWN0b3J9PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEwMDUuODI0MjE4NzUsIDEyMC41KSIgaWQ9ImZsb3djaGFydC1kaXNwbGFjZW1lbnQtNjkwMyIgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCI+PHJlY3QgaGVpZ2h0PSI2MyIgd2lkdGg9IjExMC43MzQzNzUiIHk9Ii0zMS41IiB4PSItNTUuMzY3MTg3NSIgcnk9IjAiIHJ4PSIwIiBzdHlsZT0iIiBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIj48L3JlY3Q+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ3Ljg2NzE4NzUsIC0yNCkiIHN0eWxlPSIiIGNsYXNzPSJsYWJlbCI+PHJlY3Q+PC9yZWN0Pjxmb3JlaWduT2JqZWN0IGhlaWdodD0iNDgiIHdpZHRoPSI5NS43MzQzNzUiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5kaXNwbGFjZW1lbnQ8YnIvPnt2ZWN0b3J9PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI5MC40MTQwNjI1LCAzMTAuNSkiIGlkPSJmbG93Y2hhcnQtcmFkaXVzX29mX2N1cnZhdHVyZS02OTA1IiBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIj48cmVjdCBoZWlnaHQ9IjM5IiB3aWR0aD0iMTU4Ljc2NTYyNSIgeT0iLTE5LjUiIHg9Ii03OS4zODI4MTI1IiByeT0iMCIgcng9IjAiIHN0eWxlPSIiIGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiPjwvcmVjdD48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNzEuODgyODEyNSwgLTEyKSIgc3R5bGU9IiIgY2xhc3M9ImxhYmVsIj48cmVjdD48L3JlY3Q+PGZvcmVpZ25PYmplY3QgaGVpZ2h0PSIyNCIgd2lkdGg9IjE0My43NjU2MjUiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5yYWRpdXNfb2ZfY3VydmF0dXJlPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg==" /></p>
<p>As we can see, various quantities of the same kind are not a flat
set. They form a hierarchy tree which influences</p>
<ul>
<li>conversion rules, and</li>
<li>the quantity type being the result of adding or subtracting
different quantities of the same kind.</li>
</ul>
<p>The <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library
is probably the first one on the market (in any programming language)
that models such abstractions.</p>
<h3 data-number="7.8.1" id="converting-between-quantities-of-the-same-kind"><span class="header-section-number">7.8.1</span> Converting between quantities
of the same kind<a href="#converting-between-quantities-of-the-same-kind" class="self-link"></a></h3>
<p>Quantity conversion rules can be defined based on the same hierarchy
of quantities of kind length.</p>
<ol type="1">
<li><p><strong>Implicit conversions</strong></p>
<ul>
<li>Every <code class="sourceCode default">width</code> is a
<code class="sourceCode default">length</code>.</li>
<li>Every <code class="sourceCode default">radius</code> is a
<code class="sourceCode default">width</code>.</li>
</ul>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>implicitly_convertible<span class="op">(</span>isq<span class="op">::</span>width, isq<span class="op">::</span>length<span class="op">))</span>;</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>implicitly_convertible<span class="op">(</span>isq<span class="op">::</span>radius, isq<span class="op">::</span>length<span class="op">))</span>;</span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>implicitly_convertible<span class="op">(</span>isq<span class="op">::</span>radius, isq<span class="op">::</span>width<span class="op">))</span>;</span></code></pre></div>
<p>In the <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library,
implicit conversions are allowed on copy-initialization:</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">(</span>quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&lt;</span>m<span class="op">&gt;&gt;</span> q<span class="op">)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>width<span class="op">&lt;</span>m<span class="op">&gt;&gt;</span> q1 <span class="op">=</span> <span class="dv">42</span> <span class="op">*</span> m;</span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&lt;</span>m<span class="op">&gt;&gt;</span> q2 <span class="op">=</span> q1;  <span class="co">// implicit quantity conversion</span></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>foo<span class="op">(</span>q1<span class="op">)</span>;                           <span class="co">// implicit quantity conversion</span></span></code></pre></div></li>
<li><p><strong>Explicit conversions</strong></p>
<ul>
<li>Not every <code class="sourceCode default">length</code> is a
<code class="sourceCode default">width</code>.</li>
<li>Not every <code class="sourceCode default">width</code> is a
<code class="sourceCode default">radius</code>.</li>
</ul>
<div class="sourceCode" id="cb40"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>implicitly_convertible<span class="op">(</span>isq<span class="op">::</span>length, isq<span class="op">::</span>width<span class="op">))</span>;</span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>implicitly_convertible<span class="op">(</span>isq<span class="op">::</span>length, isq<span class="op">::</span>radius<span class="op">))</span>;</span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>implicitly_convertible<span class="op">(</span>isq<span class="op">::</span>width, isq<span class="op">::</span>radius<span class="op">))</span>;</span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>explicitly_convertible<span class="op">(</span>isq<span class="op">::</span>length, isq<span class="op">::</span>width<span class="op">))</span>;</span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>explicitly_convertible<span class="op">(</span>isq<span class="op">::</span>length, isq<span class="op">::</span>radius<span class="op">))</span>;</span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>explicitly_convertible<span class="op">(</span>isq<span class="op">::</span>width, isq<span class="op">::</span>radius<span class="op">))</span>;</span></code></pre></div>
<p>In the <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library,
explicit conversions are forced by passing the quantity to a call
operator of a <code class="sourceCode default">quantity_spec</code>
type:</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&lt;</span>m<span class="op">&gt;&gt;</span> q1 <span class="op">=</span> <span class="dv">42</span> <span class="op">*</span> m;</span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>height<span class="op">&lt;</span>m<span class="op">&gt;&gt;</span> q2 <span class="op">=</span> isq<span class="op">::</span>height<span class="op">(</span>q1<span class="op">)</span>;  <span class="co">// explicit quantity conversion</span></span></code></pre></div></li>
<li><p><strong>Explicit casts</strong></p>
<ul>
<li><code class="sourceCode default">height</code> is never a
<code class="sourceCode default">width</code>, and vice versa.</li>
<li>Both <code class="sourceCode default">height</code> and
<code class="sourceCode default">width</code> are quantities of kind
<code class="sourceCode default">length</code>.</li>
</ul>
<div class="sourceCode" id="cb42"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>implicitly_convertible<span class="op">(</span>isq<span class="op">::</span>height, isq<span class="op">::</span>width<span class="op">))</span>;</span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>explicitly_convertible<span class="op">(</span>isq<span class="op">::</span>height, isq<span class="op">::</span>width<span class="op">))</span>;</span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>castable<span class="op">(</span>isq<span class="op">::</span>height, isq<span class="op">::</span>width<span class="op">))</span>;</span></code></pre></div>
<p>In the <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library,
explicit casts are forced with a dedicated
<code class="sourceCode default">quantity_cast</code> function:</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>width<span class="op">&lt;</span>m<span class="op">&gt;&gt;</span> q1 <span class="op">=</span> <span class="dv">42</span> <span class="op">*</span> m;</span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>height<span class="op">&lt;</span>m<span class="op">&gt;&gt;</span> q2 <span class="op">=</span> quantity_cast<span class="op">&lt;</span>isq<span class="op">::</span>height<span class="op">&gt;(</span>q1<span class="op">)</span>;  <span class="co">// explicit quantity cast</span></span></code></pre></div></li>
<li><p><strong>No conversion</strong></p>
<ul>
<li><code class="sourceCode default">time</code> has nothing in common
with <code class="sourceCode default">length</code>.</li>
</ul>
<div class="sourceCode" id="cb44"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>implicitly_convertible<span class="op">(</span>isq<span class="op">::</span>time, isq<span class="op">::</span>length<span class="op">))</span>;</span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>explicitly_convertible<span class="op">(</span>isq<span class="op">::</span>time, isq<span class="op">::</span>length<span class="op">))</span>;</span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>castable<span class="op">(</span>isq<span class="op">::</span>time, isq<span class="op">::</span>length<span class="op">))</span>;</span></code></pre></div>
<p>In the <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library,
even the explicit casts will not force such a conversion:</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">(</span>quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">[</span>m<span class="op">]&gt;)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb46"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a>foo<span class="op">(</span>quantity_cast<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&gt;(</span><span class="dv">42</span> <span class="op">*</span> s<span class="op">))</span>; <span class="co">// Compile-time error</span></span></code></pre></div></li>
</ol>
<p>With the above rules, one can write the following short application
to calculate a fuel consumption:</p>
<div class="sourceCode" id="cb47"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">struct</span> fuel_volume <span class="op">:</span> quantity_spec<span class="op">&lt;</span>isq<span class="op">::</span>volume<span class="op">&gt;</span> <span class="op">{}</span> fuel_volume;</span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">struct</span> fuel_consumption <span class="op">:</span> quantity_spec<span class="op">&lt;</span>fuel_volume <span class="op">/</span> isq<span class="op">::</span>distance<span class="op">&gt;</span> <span class="op">{}</span> fuel_consumption;</span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-4"><a href="#cb47-4" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> quantity fuel <span class="op">=</span> fuel_volume<span class="op">(</span><span class="fl">40.</span> <span class="op">*</span> l<span class="op">)</span>;</span>
<span id="cb47-5"><a href="#cb47-5" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> quantity distance <span class="op">=</span> isq<span class="op">::</span>distance<span class="op">(</span><span class="fl">550.</span> <span class="op">*</span> km<span class="op">)</span>;</span>
<span id="cb47-6"><a href="#cb47-6" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> quantity<span class="op">&lt;</span>fuel_consumption<span class="op">[</span>l <span class="op">/</span> <span class="op">(</span>mag<span class="op">&lt;</span><span class="dv">100</span><span class="op">&gt;</span> <span class="op">*</span> km<span class="op">)]&gt;</span> q <span class="op">=</span> fuel <span class="op">/</span> distance;</span>
<span id="cb47-7"><a href="#cb47-7" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> <span class="st">&quot;Fuel consumption: &quot;</span> <span class="op">&lt;&lt;</span> q <span class="op">&lt;&lt;</span> <span class="st">&quot;</span><span class="sc">\n</span><span class="st">&quot;</span>;</span></code></pre></div>
<p>The above code prints:</p>
<pre class="text"><code>Fuel consumption: 7.27273 × 10⁻² l/km</code></pre>
<p>Please note that, despite the dimensions of
<code class="sourceCode default">fuel_consumption</code> and
<code class="sourceCode default">isq::area</code> being the same (L²),
the constructor of a quantity <code class="sourceCode default">q</code>
below will fail to compile when we pass an argument being the quantity
of area:</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>fuel_consumption<span class="op">.</span>dimension <span class="op">==</span> isq<span class="op">::</span>area<span class="op">.</span>dimension<span class="op">)</span>;</span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> quantity<span class="op">&lt;</span>isq<span class="op">::</span>area<span class="op">[</span>m2<span class="op">]&gt;</span> football_field <span class="op">=</span> isq<span class="op">::</span>length<span class="op">(</span><span class="dv">105</span> <span class="op">*</span> m<span class="op">)</span> <span class="op">*</span> isq<span class="op">::</span>width<span class="op">(</span><span class="dv">68</span> <span class="op">*</span> m<span class="op">)</span>;</span>
<span id="cb48-4"><a href="#cb48-4" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> quantity<span class="op">&lt;</span>fuel_consumption<span class="op">[</span>l <span class="op">/</span> <span class="op">(</span>mag<span class="op">&lt;</span><span class="dv">100</span><span class="op">&gt;</span> <span class="op">*</span> km<span class="op">)]&gt;</span> q <span class="op">=</span> football_field;  <span class="co">// Compile-time error</span></span></code></pre></div>
<h3 data-number="7.8.2" id="comparing-adding-and-subtracting-quantities-of-the-same-kind"><span class="header-section-number">7.8.2</span> Comparing, adding, and
subtracting quantities of the same kind<a href="#comparing-adding-and-subtracting-quantities-of-the-same-kind" class="self-link"></a></h3>
<p><span class="citation" data-cites="ISO-GUIDE">[<a href="#ref-ISO-GUIDE" role="doc-biblioref">ISO/IEC Guide 99</a>]</span>
explicitly states that <code class="sourceCode default">width</code> and
<code class="sourceCode default">height</code> are quantities of the
same kind and as such they</p>
<ul>
<li>are mutually comparable, and</li>
<li>can be added and subtracted.</li>
</ul>
<p>If we take the above for granted, the only reasonable result of
<code class="sourceCode default">1 * width + 1 * height</code> is
<code class="sourceCode default">2 * length</code>, where the result of
<code class="sourceCode default">length</code> is known as a common
quantity type. A result of such an equation is always the first common
node in a hierarchy tree of the same kind. For example:</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>common_quantity_spec<span class="op">(</span>isq<span class="op">::</span>width, isq<span class="op">::</span>height<span class="op">)</span> <span class="op">==</span> isq<span class="op">::</span>length<span class="op">)</span>;</span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>common_quantity_spec<span class="op">(</span>isq<span class="op">::</span>thickness, isq<span class="op">::</span>radius<span class="op">)</span> <span class="op">==</span> isq<span class="op">::</span>width<span class="op">)</span>;</span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>common_quantity_spec<span class="op">(</span>isq<span class="op">::</span>distance, isq<span class="op">::</span>path_length<span class="op">)</span> <span class="op">==</span> isq<span class="op">::</span>path_length<span class="op">)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb50"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a>quantity q <span class="op">=</span> isq<span class="op">::</span>thickness<span class="op">(</span><span class="dv">1</span> <span class="op">*</span> m<span class="op">)</span> <span class="op">+</span> isq<span class="op">::</span>radius<span class="op">(</span><span class="dv">1</span> <span class="op">*</span> m<span class="op">)</span>;</span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>q<span class="op">.</span>quantity_spec <span class="op">==</span> isq<span class="op">::</span>width<span class="op">)</span>;</span></code></pre></div>
<p>One could argue that allowing to add or compare quantities of height
and width might be a safety issue, but we need to be consistent with the
requirements of <span class="citation" data-cites="ISO80000">[<a href="#ref-ISO80000" role="doc-biblioref">ISO 80000</a>]</span>.
Moreover, from our experience, disallowing such operations and requiring
an explicit cast to a common quantity in every single place makes the
code so cluttered with casts that it nearly renders the library
unusable.</p>
<p>Fortunately, the above-mentioned conversion rules make the code safe
by construction anyway. Let’s analyze the following example:</p>
<div class="sourceCode" id="cb51"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">struct</span> horizontal_length <span class="op">:</span> quantity_spec<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&gt;</span> <span class="op">{}</span> horizontal_length;</span>
<span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-3"><a href="#cb51-3" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> christmas <span class="op">{</span></span>
<span id="cb51-4"><a href="#cb51-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-5"><a href="#cb51-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> gift <span class="op">{</span></span>
<span id="cb51-6"><a href="#cb51-6" aria-hidden="true" tabindex="-1"></a>  quantity<span class="op">&lt;</span>horizontal_length<span class="op">[</span>m<span class="op">]&gt;</span> length;</span>
<span id="cb51-7"><a href="#cb51-7" aria-hidden="true" tabindex="-1"></a>  quantity<span class="op">&lt;</span>isq<span class="op">::</span>width<span class="op">[</span>m<span class="op">]&gt;</span> width;</span>
<span id="cb51-8"><a href="#cb51-8" aria-hidden="true" tabindex="-1"></a>  quantity<span class="op">&lt;</span>isq<span class="op">::</span>height<span class="op">[</span>m<span class="op">]&gt;</span> height;</span>
<span id="cb51-9"><a href="#cb51-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb51-10"><a href="#cb51-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-11"><a href="#cb51-11" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>array<span class="op">&lt;</span>quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">[</span>m<span class="op">]&gt;</span>, <span class="dv">2</span><span class="op">&gt;</span> gift_wrapping_paper_size<span class="op">(</span><span class="kw">const</span> gift<span class="op">&amp;</span> g<span class="op">)</span></span>
<span id="cb51-12"><a href="#cb51-12" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb51-13"><a href="#cb51-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> <span class="kw">auto</span> dim1 <span class="op">=</span> <span class="dv">2</span> <span class="op">*</span> g<span class="op">.</span>width <span class="op">+</span> <span class="dv">2</span> <span class="op">*</span> g<span class="op">.</span>height <span class="op">+</span> <span class="fl">0.5</span> <span class="op">*</span> g<span class="op">.</span>width;</span>
<span id="cb51-14"><a href="#cb51-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> <span class="kw">auto</span> dim2 <span class="op">=</span> g<span class="op">.</span>length <span class="op">+</span> <span class="dv">2</span> <span class="op">*</span> <span class="fl">0.75</span> <span class="op">*</span> g<span class="op">.</span>height;</span>
<span id="cb51-15"><a href="#cb51-15" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">{</span> dim1, dim2 <span class="op">}</span>;</span>
<span id="cb51-16"><a href="#cb51-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb51-17"><a href="#cb51-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-18"><a href="#cb51-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>  <span class="co">// namespace christmas</span></span>
<span id="cb51-19"><a href="#cb51-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-20"><a href="#cb51-20" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb51-21"><a href="#cb51-21" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb51-22"><a href="#cb51-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> christmas<span class="op">::</span>gift lego <span class="op">=</span> <span class="op">{</span> horizontal_length<span class="op">(</span><span class="dv">40</span> <span class="op">*</span> cm<span class="op">)</span>, isq<span class="op">::</span>width<span class="op">(</span><span class="dv">30</span> <span class="op">*</span> cm<span class="op">)</span>, isq<span class="op">::</span>height<span class="op">(</span><span class="dv">15</span> <span class="op">*</span> cm<span class="op">)</span> <span class="op">}</span>;</span>
<span id="cb51-23"><a href="#cb51-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> paper <span class="op">=</span> christmas<span class="op">::</span>gift_wrapping_paper_size<span class="op">(</span>lego<span class="op">)</span>;</span>
<span id="cb51-24"><a href="#cb51-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-25"><a href="#cb51-25" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> <span class="st">&quot;Paper needed to pack a lego box:</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb51-26"><a href="#cb51-26" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> <span class="st">&quot;- &quot;</span> <span class="op">&lt;&lt;</span> paper<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">&lt;&lt;</span> <span class="st">&quot; X &quot;</span> <span class="op">&lt;&lt;</span> paper<span class="op">[</span><span class="dv">1</span><span class="op">]</span> <span class="op">&lt;&lt;</span> <span class="st">&quot;</span><span class="sc">\n</span><span class="st">&quot;</span>;  <span class="co">// - 1.05 m X 0.625 m</span></span>
<span id="cb51-27"><a href="#cb51-27" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> <span class="st">&quot;- area = &quot;</span> <span class="op">&lt;&lt;</span> paper<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">*</span> paper<span class="op">[</span><span class="dv">1</span><span class="op">]</span> <span class="op">&lt;&lt;</span> <span class="st">&quot;</span><span class="sc">\n</span><span class="st">&quot;</span>;     <span class="co">// - area = 0.65625 m²</span></span>
<span id="cb51-28"><a href="#cb51-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In the beginning, we introduce a custom quantity
<code class="sourceCode default">horizontal_length</code> of a kind
length, which then, together with
<code class="sourceCode default">isq::width</code> and
<code class="sourceCode default">isq::height</code>, are used to define
the dimensions of a Christmas gift. Next, we provide a function that
calculates the dimensions of a gift wrapping paper with some wraparound.
The result of both those expressions is a quantity of
<code class="sourceCode default">isq::length</code>, as this is the
closest common quantity for the arguments used in this quantity
equation.</p>
<p>Regarding safety, it is important to mention here, that thanks to the
conversion rules provided above, it would be impossible to accidentally
do the following:</p>
<div class="sourceCode" id="cb52"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">(</span>quantity<span class="op">&lt;</span>horizontal_length<span class="op">[</span>m<span class="op">]&gt;</span> q<span class="op">)</span>;</span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-3"><a href="#cb52-3" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>width<span class="op">[</span>m<span class="op">]&gt;</span> q1 <span class="op">=</span> dim1;  <span class="co">// Compile-time error</span></span>
<span id="cb52-4"><a href="#cb52-4" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>height<span class="op">[</span>m<span class="op">]&gt;</span> q2<span class="op">{</span>dim1<span class="op">}</span>;  <span class="co">// Compile-time error</span></span>
<span id="cb52-5"><a href="#cb52-5" aria-hidden="true" tabindex="-1"></a>foo<span class="op">(</span>dim1<span class="op">)</span>;                          <span class="co">// Compile-time error</span></span></code></pre></div>
<p>The reason of compilation errors above is the fact that
<code class="sourceCode default">isq::length</code> is not implicitly
convertible to the quantities defined based on it. To make the above
code compile, an explicit conversion of a quantity type is needed:</p>
<div class="sourceCode" id="cb53"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">(</span>quantity<span class="op">&lt;</span>horizontal_length<span class="op">[</span>m<span class="op">]&gt;</span> q<span class="op">)</span>;</span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>width<span class="op">[</span>m<span class="op">]&gt;</span> q1 <span class="op">=</span> isq<span class="op">::</span>width<span class="op">(</span>dim1<span class="op">)</span>;</span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>height<span class="op">[</span>m<span class="op">]&gt;</span> q2<span class="op">{</span>isq<span class="op">::</span>height<span class="op">(</span>dim1<span class="op">)}</span>;</span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a>foo<span class="op">(</span>horizontal_length<span class="op">(</span>dim1<span class="op">))</span>;</span></code></pre></div>
<p>To summarize, rules for addition, subtraction, and comparison of
quantities improve the library usability, while the conversion rules
enhance the safety of the library compared to the libraries that do not
model quantity kinds.</p>
<h3 data-number="7.8.3" id="modeling-a-quantity-kind"><span class="header-section-number">7.8.3</span> Modeling a quantity kind<a href="#modeling-a-quantity-kind" class="self-link"></a></h3>
<p>In the physical units library, we also need an abstraction describing
an entire family of quantities of the same kind. Such quantities have
not only the same dimension but also can be expressed in the same
units.</p>
<p>To annotate a quantity to represent its kind we introduced the
<code class="sourceCode default">kind_of&lt;&gt;</code> specifier. For
example, to express any quantity of length, we need to type
<code class="sourceCode default">kind_of&lt;isq::length&gt;</code>. Such
an entity behaves as any quantity of its kind. This means that it is
implicitly convertible to any quantity in a hierarchy tree.</p>
<div class="sourceCode" id="cb54"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>implicitly_convertible<span class="op">(</span>isq<span class="op">::</span>length, isq<span class="op">::</span>height<span class="op">))</span>;</span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>implicitly_convertible<span class="op">(</span>kind_of<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&gt;</span>, isq<span class="op">::</span>height<span class="op">))</span>;</span></code></pre></div>
<p>Additionally, the result of operations on quantity kinds is also a
quantity kind:</p>
<div class="sourceCode" id="cb55"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>same_type<span class="op">&lt;</span>kind_of<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&gt;</span> <span class="op">/</span> kind_of<span class="op">&lt;</span>isq<span class="op">::</span>time<span class="op">&gt;</span>, kind_of<span class="op">&lt;</span>isq<span class="op">::</span>length <span class="op">/</span> isq<span class="op">::</span>time<span class="op">&gt;&gt;)</span>;</span></code></pre></div>
<p>However, if at least one equation’s operand is not a kind, the result
becomes a “strong” quantity where all the kinds are converted to the
hierarchy tree’s root quantities:</p>
<div class="sourceCode" id="cb56"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>same_type<span class="op">&lt;</span>kind_of<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&gt;</span> <span class="op">/</span> isq<span class="op">::</span>time, kind_of<span class="op">&lt;</span>isq<span class="op">::</span>length <span class="op">/</span> isq<span class="op">::</span>time<span class="op">&gt;&gt;)</span>;</span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>same_type<span class="op">&lt;</span>kind_of<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&gt;</span> <span class="op">/</span> isq<span class="op">::</span>time, isq<span class="op">::</span>length <span class="op">/</span> isq<span class="op">::</span>time<span class="op">&gt;)</span>;</span></code></pre></div>
<h3 data-number="7.8.4" id="restricting-units-to-specific-quantity-kinds"><span class="header-section-number">7.8.4</span> Restricting units to specific
quantity kinds<a href="#restricting-units-to-specific-quantity-kinds" class="self-link"></a></h3>
<p>By default, units can be used to measure any kind of quantity with
the same dimension. However, as we have mentioned above, some units
(e.g., Hz, Bq) are constrained to be used only with a specific kind.
Also, base units of the SI are meant to measure all of the quantities of
their kinds. To model this, in the <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library, we do the
following:</p>
<div class="sourceCode" id="cb57"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a><span class="co">// base units</span></span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">struct</span> metre <span class="op">:</span> named_unit<span class="op">&lt;</span><span class="st">&quot;m&quot;</span>, kind_of<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&gt;&gt;</span> <span class="op">{}</span> metre;</span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">struct</span> second <span class="op">:</span> named_unit<span class="op">&lt;</span><span class="st">&quot;s&quot;</span>, kind_of<span class="op">&lt;</span>isq<span class="op">::</span>time<span class="op">&gt;&gt;</span> <span class="op">{}</span> second;</span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a><span class="co">// derived units</span></span>
<span id="cb57-6"><a href="#cb57-6" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">struct</span> hertz <span class="op">:</span> named_unit<span class="op">&lt;</span><span class="st">&quot;Hz&quot;</span>, <span class="dv">1</span> <span class="op">/</span> second, kind_of<span class="op">&lt;</span>isq<span class="op">::</span>frequency<span class="op">&gt;&gt;</span> <span class="op">{}</span> hertz;</span>
<span id="cb57-7"><a href="#cb57-7" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">struct</span> becquerel <span class="op">:</span> named_unit<span class="op">&lt;</span><span class="st">&quot;Bq&quot;</span>, <span class="dv">1</span> <span class="op">/</span> second, kind_of<span class="op">&lt;</span>isq<span class="op">::</span>activity<span class="op">&gt;&gt;</span> <span class="op">{}</span> becquerel;</span>
<span id="cb57-8"><a href="#cb57-8" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">struct</span> baud <span class="op">:</span> named_unit<span class="op">&lt;</span><span class="st">&quot;Bd&quot;</span>, <span class="dv">1</span> <span class="op">/</span> si<span class="op">::</span>second, kind_of<span class="op">&lt;</span>iec80000<span class="op">::</span>modulation_rate<span class="op">&gt;&gt;</span> <span class="op">{}</span> baud;</span></code></pre></div>
<p>This means that every time we type
<code class="sourceCode default">42 * m</code>, we create a quantity of
a kind length with the length dimension. Such a quantity can be added,
subtracted, or compared to any other quantity of the same kind.
Moreover, it is implicitly convertible to any quantity of its kind.
Again, this could be considered a safety issue as one could type:</p>
<div class="sourceCode" id="cb58"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> christmas<span class="op">::</span>gift lego <span class="op">=</span> <span class="op">{</span> <span class="dv">40</span> <span class="op">*</span> cm, <span class="dv">30</span> <span class="op">*</span> cm, <span class="dv">15</span> <span class="op">*</span> cm <span class="op">}</span>;</span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> paper <span class="op">=</span> christmas<span class="op">::</span>gift_wrapping_paper_size<span class="op">(</span>lego<span class="op">)</span>;</span></code></pre></div>
<p>The above code compiles fine without the need to force specific
quantity types during construction. This is another tradeoff we have to
do here in order to improve the usability. Otherwise, we would need to
type the following every single time we want to initialize an array or
aggregate:</p>
<div class="sourceCode" id="cb59"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> quantity<span class="op">&lt;</span>isq<span class="op">::</span>position_vector<span class="op">[</span>m<span class="op">]</span>, <span class="dt">int</span><span class="op">&gt;</span> measurements<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> isq<span class="op">::</span>position_vector<span class="op">(</span><span class="dv">30&#39;160</span> <span class="op">*</span> m<span class="op">)</span>,</span>
<span id="cb59-2"><a href="#cb59-2" aria-hidden="true" tabindex="-1"></a>                                                                isq<span class="op">::</span>position_vector<span class="op">(</span><span class="dv">30&#39;365</span> <span class="op">*</span> m<span class="op">)</span>,</span>
<span id="cb59-3"><a href="#cb59-3" aria-hidden="true" tabindex="-1"></a>                                                                isq<span class="op">::</span>position_vector<span class="op">(</span><span class="dv">30&#39;890</span> <span class="op">*</span> m<span class="op">)</span>,</span>
<span id="cb59-4"><a href="#cb59-4" aria-hidden="true" tabindex="-1"></a>                                                                isq<span class="op">::</span>position_vector<span class="op">(</span><span class="dv">31&#39;050</span> <span class="op">*</span> m<span class="op">)</span>,</span>
<span id="cb59-5"><a href="#cb59-5" aria-hidden="true" tabindex="-1"></a>                                                                isq<span class="op">::</span>position_vector<span class="op">(</span><span class="dv">31&#39;785</span> <span class="op">*</span> m<span class="op">)</span>,</span>
<span id="cb59-6"><a href="#cb59-6" aria-hidden="true" tabindex="-1"></a>                                                                isq<span class="op">::</span>position_vector<span class="op">(</span><span class="dv">32&#39;215</span> <span class="op">*</span> m<span class="op">)</span>,</span>
<span id="cb59-7"><a href="#cb59-7" aria-hidden="true" tabindex="-1"></a>                                                                isq<span class="op">::</span>position_vector<span class="op">(</span><span class="dv">33&#39;130</span> <span class="op">*</span> m<span class="op">)</span>,</span>
<span id="cb59-8"><a href="#cb59-8" aria-hidden="true" tabindex="-1"></a>                                                                isq<span class="op">::</span>position_vector<span class="op">(</span><span class="dv">34&#39;510</span> <span class="op">*</span> m<span class="op">)</span>,</span>
<span id="cb59-9"><a href="#cb59-9" aria-hidden="true" tabindex="-1"></a>                                                                isq<span class="op">::</span>position_vector<span class="op">(</span><span class="dv">36&#39;010</span> <span class="op">*</span> m<span class="op">)</span>,</span>
<span id="cb59-10"><a href="#cb59-10" aria-hidden="true" tabindex="-1"></a>                                                                isq<span class="op">::</span>position_vector<span class="op">(</span><span class="dv">37&#39;265</span> <span class="op">*</span> m<span class="op">)</span> <span class="op">}</span>;</span></code></pre></div>
<p>As we can see above, it would be really inconvenient. With the
current rules, we type:</p>
<div class="sourceCode" id="cb60"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> quantity<span class="op">&lt;</span>isq<span class="op">::</span>position_vector<span class="op">[</span>m<span class="op">]</span>, <span class="dt">int</span><span class="op">&gt;</span> measurements<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="dv">30&#39;160</span> <span class="op">*</span> m, <span class="dv">30&#39;365</span> <span class="op">*</span> m, <span class="dv">30&#39;890</span> <span class="op">*</span> m, <span class="dv">31&#39;050</span> <span class="op">*</span> m,</span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a>                                                                <span class="dv">31&#39;785</span> <span class="op">*</span> m, <span class="dv">32&#39;215</span> <span class="op">*</span> m, <span class="dv">33&#39;130</span> <span class="op">*</span> m, <span class="dv">34&#39;510</span> <span class="op">*</span> m,</span>
<span id="cb60-3"><a href="#cb60-3" aria-hidden="true" tabindex="-1"></a>                                                                <span class="dv">36&#39;010</span> <span class="op">*</span> m, <span class="dv">37&#39;265</span> <span class="op">*</span> m <span class="op">}</span>;</span></code></pre></div>
<p>which is more user-friendly.</p>
<p>Having such two options also gives users a choice. When we use
different quantities of the same kind in a project (e.g., radius,
wavelength, altitude), we should probably reach for strongly-typed
quantities to bring additional safety for those cases. Otherwise, we can
just use the simple mode for the remaining quantities. We can easily mix
simple and strongly-typed quantities in our projects, and the library
will do its best to protect us based on the information provided.</p>
<h2 data-number="7.9" id="non-negative-quantities"><span class="header-section-number">7.9</span> Non-negative quantities<a href="#non-negative-quantities" class="self-link"></a></h2>
<p>Some quantities are defined by ISO/IEC 80000 as explicitly
non-negative. Others are implicitly non-negative from their definition.
For example, those specified as magnitudes of a vector, like speed,
defined as the magnitude of velocity.</p>
<p>It is possible to have negative values of quantities defined as
non-negative. For example,
<code class="sourceCode default">-1 * speed[m/s]</code> could represent
a change in average speed between two events. It is also possible to
require non-negative values of quantities not defined as non-negative.
For example, when height is the measure of an object, a negative value
is physically meaningless.</p>
<p><code class="sourceCode default">quantity</code> is parametrized on
the representation type. So it is possible to specify one that prevents
negative values, e.g., a contract-checked type. This means that
<code class="sourceCode default">-1 * speed[m/s]</code> works by default
(the representation type is
<code class="sourceCode default">int</code>). And also that <code class="sourceCode default">height(mylib::non_negative(obj.top - obj.bottom));</code>
will catch logic errors in the formula.</p>
<!-- Lots of exciting discussion at https://github.com/mpusz/mp-units/issues/468 -->
<h2 data-number="7.10" id="vector-and-tensor-quantities"><span class="header-section-number">7.10</span> Vector and tensor quantities<a href="#vector-and-tensor-quantities" class="self-link"></a></h2>
<p>While talking about physical quantities and units libraries, everyone
expects that the library will protect (preferably at compile-time) from
accidentally replacing multiplication with division operations or vice
versa. Everyone knows and expects that the multiplication of length and
time should not result in speed. It does not mean that such a quantity
equation is invalid. It just results in a quantity of a different
type.</p>
<p>If we expect the above protection for scalar quantities, we should
also strive to provide similar guarantees for vector and tensor
quantities. First, the multiplication or division of two vectors or
tensors is not even mathematically defined. Such operations should be
impossible on quantities using vector or tensor representation
types.</p>
<p>While multiplication and division are with scalars, the dot and cross
products are for vector quantities. The result of the first one is a
scalar. The second one results in a vector perpendicular to both vectors
passed as arguments. A good physical quantities and units library should
protect the user from making such an error of accidentally replacing
those operations.</p>
<p>Vector and tensor quantities can be implemented in two ways:</p>
<ol type="1">
<li><p>Encapsulating multiple quantities into a homogeneous vector or
tensor representation type</p>
<p>This solution is the most common in the C++ market. It requires the
quantities library to provide only basic arithmetic operations
(addition, subtraction, multiplication, and division) which are being
used to calculate the result of linear algebra math. However, this
solution can’t provide any compile-time safety described above, and will
also crash when someone passes a proper vector and tensor representation
type to a quantity, expecting it to work.</p></li>
<li><p>Encapsulating a vector or tensor as a representation type of a
quantity</p>
<p>This provides all the required type safety, but requires the library
to implement more operations on quantities and properly constrain them
so they are selectively enabled when needed. Besides <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span>, the only library that
supports such an approach is <span class="citation" data-cites="PINT">[<a href="#ref-PINT" role="doc-biblioref">Pint</a>]</span>. Such a solution requires the
following operations to be exposed for quantity types (note that
character refers to the algebraic structure of either scalar, vector and
tensor):</p>
<ul>
<li><code class="sourceCode default">a + b</code> - addition where both
arguments should be of the same quantity kind and character</li>
<li><code class="sourceCode default">a - b</code> - subtraction where
both arguments should be of the same quantity kind and character</li>
<li><code class="sourceCode default">a % b</code> - modulo where both
arguments should be of the same quantity kind and character</li>
<li><code class="sourceCode default">a * b</code> - multiplication where
one of the arguments has to be a scalar</li>
<li><code class="sourceCode default">a / b</code> - division where the
divisor has to be scalar</li>
<li><code class="sourceCode default">a ⋅ b</code> - dot product of two
vectors</li>
<li><code class="sourceCode default">a × b</code> - cross product of two
vectors</li>
<li><code class="sourceCode default">|a|</code> - magnitude of a
vector</li>
<li><code class="sourceCode default">a ⊗ b</code> - tensor product of
two vectors or tensors</li>
<li><code class="sourceCode default">a ⋅ b</code> - inner product of two
tensors</li>
<li><code class="sourceCode default">a ⋅ b</code> - inner product of
tensor and vector</li>
<li><code class="sourceCode default">a : b</code> - scalar product of
two tensors</li>
</ul></li>
</ol>
<p>Additionally, the <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library
knows the expected quantity character, which is provided (implicitly or
explicitly) in the definition of each quantity type. Thanks to that, it
prevents the user, for example, from providing a scalar representation
type for force or a vector representation for power quantities.</p>
<div class="sourceCode" id="cb61"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a>QuantityOf<span class="op">&lt;</span>isq<span class="op">::</span>velocity<span class="op">&gt;</span> q1 <span class="op">=</span> <span class="dv">60</span> <span class="op">*</span> km <span class="op">/</span> h;                             <span class="co">// Compile-time error</span></span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a>QuantityOf<span class="op">&lt;</span>isq<span class="op">::</span>velocity<span class="op">&gt;</span> q2 <span class="op">=</span> la_vector<span class="op">{</span><span class="dv">0</span>, <span class="dv">0</span>, <span class="op">-</span><span class="dv">60</span><span class="op">}</span> <span class="op">*</span> km <span class="op">/</span> h;           <span class="co">// OK</span></span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a>QuantityOf<span class="op">&lt;</span>isq<span class="op">::</span>force<span class="op">&gt;</span> q3 <span class="op">=</span> <span class="dv">80</span> <span class="op">*</span> kg <span class="op">*</span> <span class="op">(</span><span class="dv">10</span> <span class="op">*</span> m <span class="op">/</span> s2<span class="op">)</span>;                    <span class="co">// Compile-time error</span></span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a>QuantityOf<span class="op">&lt;</span>isq<span class="op">::</span>force<span class="op">&gt;</span> q4 <span class="op">=</span> <span class="dv">80</span> <span class="op">*</span> kg <span class="op">*</span> <span class="op">(</span>la_vector<span class="op">{</span><span class="dv">0</span>, <span class="dv">0</span>, <span class="op">-</span><span class="dv">10</span><span class="op">}</span> <span class="op">*</span> m <span class="op">/</span> s2<span class="op">)</span>;  <span class="co">// OK</span></span>
<span id="cb61-5"><a href="#cb61-5" aria-hidden="true" tabindex="-1"></a>QuantityOf<span class="op">&lt;</span>isq<span class="op">::</span>power<span class="op">&gt;</span> q5 <span class="op">=</span> q2 <span class="op">*</span> q4;                                    <span class="co">// Compile-time error</span></span>
<span id="cb61-6"><a href="#cb61-6" aria-hidden="true" tabindex="-1"></a>QuantityOf<span class="op">&lt;</span>isq<span class="op">::</span>power<span class="op">&gt;</span> q5 <span class="op">=</span> dot<span class="op">(</span>q2, q4<span class="op">)</span>;                                <span class="co">// OK</span></span></code></pre></div>
<p><em>Note: <code class="sourceCode default">q1</code> and
<code class="sourceCode default">q3</code> can be permitted to compile
by explicitly specializing the
<code class="sourceCode default">is_vector&lt;T&gt;</code> trait for the
representation type.</em></p>
<p>As we can see above, such features additionally improves the
compile-time safety of the library by ensuring that quantities are
created with proper quantity equations and are using correct
representation types.</p>
<h1 data-number="8" id="safety-pitfalls"><span class="header-section-number">8</span> Safety pitfalls<a href="#safety-pitfalls" class="self-link"></a></h1>
<h2 data-number="8.1" id="integer-division"><span class="header-section-number">8.1</span> Integer division<a href="#integer-division" class="self-link"></a></h2>
<p>The physical units library can’t do any runtime branching logic for
the division operator. All logic has to be done at compile-time when the
actual values are not known, and the quantity types can’t change at
runtime.</p>
<p>If we expect
<code class="sourceCode default">120 * km / (2 * h)</code> to return
<code class="sourceCode default">60 km / h</code>, we have to agree with
the fact that <code class="sourceCode default">5 * km / (24 * h)</code>
returns <code class="sourceCode default">0 km/h</code>. We can’t do a
range check at runtime to dynamically adjust scales and types based on
the values of provided function arguments.</p>
<p>The same applies to:</p>
<div class="sourceCode" id="cb62"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span><span class="dv">5</span> <span class="op">*</span> h <span class="op">/</span> <span class="op">(</span><span class="dv">120</span> <span class="op">*</span> min<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span> <span class="op">*</span> one<span class="op">)</span>;</span></code></pre></div>
<p>This is why floating-point representation types are recommended as a
default to store the numerical value of a quantity. Some popular
physical units libraries even <a href="https://aurora-opensource.github.io/au/main/troubleshooting/#integer-division-forbidden">forbid
integer division at all</a>.</p>
<p>The problem is similar to the one described in the section about
accidental truncation of values through conversion. While the consequent
use of floating-point representation types may be a good idea, it is not
always possible. Especially in close-to-the-metal applications and small
embedded systems, the use of floating-point types is sometimes not an
option, either for performance reasons or lack of hardware support.
Having different operators for safe floating-point operations and unsafe
integer operations would hurt generic programming. As such, users should
instead use safer representation types.</p>
<h2 data-number="8.2" id="lack-of-safe-numeric-types"><span class="header-section-number">8.2</span> Lack of safe numeric types<a href="#lack-of-safe-numeric-types" class="self-link"></a></h2>
<p>Integers can overflow on arithmetics. This has already caused some
expensive failures in engineering <span class="citation" data-cites="ARIANE">[<a href="#ref-ARIANE" role="doc-biblioref">Ariane
flight V88</a>]</span>.</p>
<p>Integers can also be truncated during assignment to a narrower
type.</p>
<p>Floating-point types may lose precision during assignment to a
narrower type. Conversion from
<code class="sourceCode default">std::int64_t</code> to
<code class="sourceCode default">double</code> may also lose
precision.</p>
<p>If we had safe numeric types in the C++ standard library, they could
easily be used as a <code class="sourceCode default">quantity</code>
representation type in the physical quantities and units library, which
would address these safety concerns.</p>
<h2 data-number="8.3" id="potential-surprises-during-units-composition"><span class="header-section-number">8.3</span> Potential surprises during
units composition<a href="#potential-surprises-during-units-composition" class="self-link"></a></h2>
<p>One of the most essential requirements for a good physical quantities
and units library is to implement units in such a way that they compose.
With that, one can easily create any derived unit using a simple unit
equation on other base or derived units. For example:</p>
<div class="sourceCode" id="cb63"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> Unit <span class="kw">auto</span> kmph <span class="op">=</span> km <span class="op">/</span> h;</span></code></pre></div>
<p>We can also easily obtain a quantity with:</p>
<div class="sourceCode" id="cb64"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a>quantity q <span class="op">=</span> <span class="dv">60</span> <span class="op">*</span> km <span class="op">/</span> h;</span></code></pre></div>
<p>Such a solution is an industry standard and is implemented not only
in <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span>, but also is available for
many years now in both <span class="citation" data-cites="BOOST-UNITS">[<a href="#ref-BOOST-UNITS" role="doc-biblioref">Boost.Units</a>]</span> and <span class="citation" data-cites="PINT">[<a href="#ref-PINT" role="doc-biblioref">Pint</a>]</span>.</p>
<p>We believe that is the correct thing to do. However, we want to make
it straight in this paper that some potential issues are associated with
such a syntax. Inexperienced users are often surprised by the results of
the following expression:</p>
<div class="sourceCode" id="cb65"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb65-1"><a href="#cb65-1" aria-hidden="true" tabindex="-1"></a>quantity q <span class="op">=</span> <span class="dv">60</span> <span class="op">*</span> km <span class="op">/</span> <span class="dv">2</span> <span class="op">*</span> h;</span></code></pre></div>
<p>This looks like like <code class="sourceCode default">30 km/h</code>,
right? But it is not. Thanks to the operators’ associativity, it results
in <code class="sourceCode default">30 km⋅h</code>. In case we want to
divide <code class="sourceCode default">60 km</code> by
<code class="sourceCode default">2 h</code>, parentheses are needed:</p>
<div class="sourceCode" id="cb66"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb66-1"><a href="#cb66-1" aria-hidden="true" tabindex="-1"></a>quantity q <span class="op">=</span> <span class="dv">60</span> <span class="op">*</span> km <span class="op">/</span> <span class="op">(</span><span class="dv">2</span> <span class="op">*</span> h<span class="op">)</span>;</span></code></pre></div>
<p>Another surprising issue may result from the following code:</p>
<div class="sourceCode" id="cb67"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb67-1"><a href="#cb67-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> make_length<span class="op">(</span>T v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> v <span class="op">*</span> si<span class="op">::</span>metre; <span class="op">}</span></span>
<span id="cb67-3"><a href="#cb67-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb67-4"><a href="#cb67-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> v <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb67-5"><a href="#cb67-5" aria-hidden="true" tabindex="-1"></a>quantity q <span class="op">=</span> make_length<span class="op">(</span>v<span class="op">)</span>;</span></code></pre></div>
<p>This might look like a good idea, but let’s consider what would
happen if the user provided a quantity as input:</p>
<div class="sourceCode" id="cb68"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb68-1"><a href="#cb68-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> v <span class="op">=</span> <span class="dv">42</span> <span class="op">*</span> m;</span>
<span id="cb68-2"><a href="#cb68-2" aria-hidden="true" tabindex="-1"></a>quantity q <span class="op">=</span> make_length<span class="op">(</span>v<span class="op">)</span>;</span></code></pre></div>
<p>The above function call will result in a quantity of area instead of
the expected quantity of length.</p>
<p>The issues mentioned above could be turned into compilation errors by
disallowing multiplying or dividing a quantity by an unit. The <span class="citation" data-cites="MP-UNITS">[<a href="#ref-MP-UNITS" role="doc-biblioref">mp-units</a>]</span> library initially provided
such an approach, but with time, we decided this to not be
user-friendly. Forcing the user to put the parenthesis around all
derived units in quantity equations like the one below, was too verbose
and confusing:</p>
<div class="sourceCode" id="cb69"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb69-1"><a href="#cb69-1" aria-hidden="true" tabindex="-1"></a>quantity q <span class="op">=</span> <span class="dv">60</span> <span class="op">*</span> <span class="op">(</span>km <span class="op">/</span> h<span class="op">)</span>;</span></code></pre></div>
<p>It is important to notice that the problems mentioned above will
always surface with a compile-time error at some point in the user’s
code when they assign the resulting quantity to one with an explicitly
provided quantity type.</p>
<p>Below, we provide a few examples that correctly detect such issues at
compile-time:</p>
<div class="sourceCode" id="cb70"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb70-1"><a href="#cb70-1" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>si<span class="op">::</span>kilo<span class="op">&lt;</span>si<span class="op">::</span>metre<span class="op">&gt;</span> <span class="op">/</span> non_si<span class="op">::</span>hour, <span class="dt">int</span><span class="op">&gt;</span> q1 <span class="op">=</span> <span class="dv">60</span> <span class="op">*</span> km <span class="op">/</span> <span class="dv">2</span> <span class="op">*</span> h;             <span class="co">// Compile-time error</span></span>
<span id="cb70-2"><a href="#cb70-2" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>speed<span class="op">[</span>si<span class="op">::</span>kilo<span class="op">&lt;</span>si<span class="op">::</span>metre<span class="op">&gt;</span> <span class="op">/</span> non_si<span class="op">::</span>hour<span class="op">]</span>, <span class="dt">int</span><span class="op">&gt;</span> q2 <span class="op">=</span> <span class="dv">60</span> <span class="op">*</span> km <span class="op">/</span> <span class="dv">2</span> <span class="op">*</span> h; <span class="co">// Compile-time error</span></span>
<span id="cb70-3"><a href="#cb70-3" aria-hidden="true" tabindex="-1"></a>QuantityOf<span class="op">&lt;</span>isq<span class="op">::</span>speed<span class="op">&gt;</span> <span class="kw">auto</span> q3 <span class="op">=</span> <span class="dv">60</span> <span class="op">*</span> km <span class="op">/</span> <span class="dv">2</span> <span class="op">*</span> h;                                   <span class="co">// Compile-time error</span></span></code></pre></div>
<div class="sourceCode" id="cb71"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb71-1"><a href="#cb71-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb71-2"><a href="#cb71-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> make_length<span class="op">(</span>T v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> v <span class="op">*</span> si<span class="op">::</span>metre; <span class="op">}</span></span>
<span id="cb71-3"><a href="#cb71-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-4"><a href="#cb71-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> v <span class="op">=</span> <span class="dv">42</span> <span class="op">*</span> m;</span>
<span id="cb71-5"><a href="#cb71-5" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>si<span class="op">::</span>metre, <span class="dt">int</span><span class="op">&gt;</span> q1 <span class="op">=</span> make_length<span class="op">(</span>v<span class="op">)</span>;           <span class="co">// Compile-time error</span></span>
<span id="cb71-6"><a href="#cb71-6" aria-hidden="true" tabindex="-1"></a>quantity<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">[</span>si<span class="op">::</span>metre<span class="op">]&gt;</span> q2 <span class="op">=</span> make_length<span class="op">(</span>v<span class="op">)</span>;   <span class="co">// Compile-time error</span></span>
<span id="cb71-7"><a href="#cb71-7" aria-hidden="true" tabindex="-1"></a>QuantityOf<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&gt;</span> q3 <span class="op">=</span> make_length<span class="op">(</span>v<span class="op">)</span>;            <span class="co">// Compile-time error</span></span></code></pre></div>
<div class="sourceCode" id="cb72"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb72-1"><a href="#cb72-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb72-2"><a href="#cb72-2" aria-hidden="true" tabindex="-1"></a>QuantityOf<span class="op">&lt;</span>isq<span class="op">::</span>length<span class="op">&gt;</span> <span class="kw">auto</span> make_length<span class="op">(</span>T v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> v <span class="op">*</span> si<span class="op">::</span>metre; <span class="op">}</span></span>
<span id="cb72-3"><a href="#cb72-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb72-4"><a href="#cb72-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> v <span class="op">=</span> <span class="dv">42</span> <span class="op">*</span> m;</span>
<span id="cb72-5"><a href="#cb72-5" aria-hidden="true" tabindex="-1"></a>quantity q <span class="op">=</span> make_length<span class="op">(</span>v<span class="op">)</span>;  <span class="co">// Compile-time error</span></span></code></pre></div>
<div class="sourceCode" id="cb73"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb73-1"><a href="#cb73-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>Representation T<span class="op">&gt;</span></span>
<span id="cb73-2"><a href="#cb73-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> make_length<span class="op">(</span>T v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> v <span class="op">*</span> si<span class="op">::</span>metre; <span class="op">}</span></span>
<span id="cb73-3"><a href="#cb73-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb73-4"><a href="#cb73-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> v <span class="op">=</span> <span class="dv">42</span> <span class="op">*</span> m;</span>
<span id="cb73-5"><a href="#cb73-5" aria-hidden="true" tabindex="-1"></a>quantity q <span class="op">=</span> make_length<span class="op">(</span>v<span class="op">)</span>;  <span class="co">// Compile-time error</span></span></code></pre></div>
<h2 data-number="8.4" id="structural-types"><span class="header-section-number">8.4</span> Structural types<a href="#structural-types" class="self-link"></a></h2>
<p>The <code class="sourceCode default">quantity</code> and
<code class="sourceCode default">quantity_point</code> class templates
are structural types to allow them to be passed as template arguments.
For example, we can write the following:</p>
<div class="sourceCode" id="cb74"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb74-1"><a href="#cb74-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">struct</span> amsterdam_sea_level <span class="op">:</span> absolute_point_origin<span class="op">&lt;</span>isq<span class="op">::</span>altitude<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb74-2"><a href="#cb74-2" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> amsterdam_sea_level;</span>
<span id="cb74-3"><a href="#cb74-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb74-4"><a href="#cb74-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">struct</span> mediterranean_sea_level <span class="op">:</span> relative_point_origin<span class="op">&lt;</span>amsterdam_sea_level <span class="op">+</span> isq<span class="op">::</span>altitude<span class="op">(-</span><span class="dv">27</span> <span class="op">*</span> cm<span class="op">)&gt;</span> <span class="op">{</span></span>
<span id="cb74-5"><a href="#cb74-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> mediterranean_sea_level;</span>
<span id="cb74-6"><a href="#cb74-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb74-7"><a href="#cb74-7" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> altitude_DE <span class="op">=</span> quantity_point<span class="op">&lt;</span>isq<span class="op">::</span>altitude<span class="op">[</span>m<span class="op">]</span>, amsterdam_sea_level<span class="op">&gt;</span>;</span>
<span id="cb74-8"><a href="#cb74-8" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> altitude_CH <span class="op">=</span> quantity_point<span class="op">&lt;</span>isq<span class="op">::</span>altitude<span class="op">[</span>m<span class="op">]</span>, mediterranean_sea_level<span class="op">&gt;</span>;</span></code></pre></div>
<p>Unfortunately, current language rules require that all member data of
a structural type are public. This could be considered a safety issue.
We try really hard to provide unit-safe interfaces, but at the same time
expose the public “naked” data member that can be freely read or
manipulated by anyone.</p>
<p>Hopefully, this requirement on structural types will be relaxed
before the library gets standardized.</p>
<h1 data-number="9" id="acknowledgements"><span class="header-section-number">9</span> Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<p>Special thanks and recognition goes to <a href="http://www.epam.com">Epam Systems</a> for supporting Mateusz’s
membership in the ISO C++ Committee and the production of this
proposal.</p>
<p>We would also like to thank Peter Sommerlad for providing valuable
feedback that helped us shape the final version of this document.</p>
<!-- markdownlint-disable -->
<h1 data-number="10" id="bibliography"><span class="header-section-number">10</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-ARIANE" class="csl-entry" role="doc-biblioentry">
[Ariane flight V88] Ariane flight V88. <a href="https://en.wikipedia.org/wiki/Ariane_flight_V88"><div class="csl-block">https://en.wikipedia.org/wiki/Ariane_flight_V88</div></a>
</div>
<div id="ref-BOOST-UNITS" class="csl-entry" role="doc-biblioentry">
[Boost.Units] Matthias C. Schabel and Steven Watanabe. Boost.Units. <a href="https://www.boost.org/doc/libs/1_83_0/doc/html/boost_units.html"><div class="csl-block">https://www.boost.org/doc/libs/1_83_0/doc/html/boost_units.html</div></a>
</div>
<div id="ref-CLARENCE" class="csl-entry" role="doc-biblioentry">
[Clarence] Steve Chawkins. Mismeasure for Measure. <a href="https://www.latimes.com/archives/la-xpm-2001-feb-09-me-23253-story.html"><div class="csl-block">https://www.latimes.com/archives/la-xpm-2001-feb-09-me-23253-story.html</div></a>
</div>
<div id="ref-COLUMBUS" class="csl-entry" role="doc-biblioentry">
[Columbus] Christopher Columbus. <a href="https://en.wikipedia.org/wiki/Christopher_Columbus"><div class="csl-block">https://en.wikipedia.org/wiki/Christopher_Columbus</div></a>
</div>
<div id="ref-DISNEY" class="csl-entry" role="doc-biblioentry">
[Disney] Cause of the Space Mountain Incident Determined at Tokyo
Disneyland Park. <a href="https://web.archive.org/web/20040209033827/http://www.olc.co.jp/news/20040121_01en.html"><div class="csl-block">https://web.archive.org/web/20040209033827/http://www.olc.co.jp/news/20040121_01en.html</div></a>
</div>
<div id="ref-FLIGHT_6316" class="csl-entry" role="doc-biblioentry">
[Flight 6316] Korean Air Flight 6316 MD-11, Shanghai, China - April 15,
1999. <a href="https://web.archive.org/web/20210917190721/https://www.ntsb.gov/news/press-releases/Pages/Korean_Air_Flight_6316_MD-11_Shanghai_China_-_April_15_1999.aspx"><div class="csl-block">https://web.archive.org/web/20210917190721/https://www.ntsb.gov/news/press-releases/Pages/Korean_Air_Flight_6316_MD-11_Shanghai_China_-_April_15_1999.aspx</div></a>
</div>
<div id="ref-GIMLI_GLIDER" class="csl-entry" role="doc-biblioentry">
[Gimli Glider] Gimli Glider. <a href="https://en.wikipedia.org/wiki/Gimli_Glider"><div class="csl-block">https://en.wikipedia.org/wiki/Gimli_Glider</div></a>
</div>
<div id="ref-HOCHRHEINBRÜCKE" class="csl-entry" role="doc-biblioentry">
[Hochrheinbrücke] An embarrassing discovery during the construction of a
bridge. <a href="https://www.normaalamsterdamspeil.nl/wp-content/uploads/2015/03/website_bridge.pdf"><div class="csl-block">https://www.normaalamsterdamspeil.nl/wp-content/uploads/2015/03/website_bridge.pdf</div></a>
</div>
<div id="ref-ISO80000" class="csl-entry" role="doc-biblioentry">
[ISO 80000] ISO80000: Quantities and units. <a href="https://www.iso.org/standard/76921.html"><div class="csl-block">https://www.iso.org/standard/76921.html</div></a>
</div>
<div id="ref-ISO-GUIDE" class="csl-entry" role="doc-biblioentry">
[ISO/IEC Guide 99] ISO/IEC Guide 99: International vocabulary of
metrology — Basic and general concepts and associated terms (VIM). <a href="https://www.iso.org/obp/ui#iso:std:iso-iec:guide:99"><div class="csl-block">https://www.iso.org/obp/ui#iso:std:iso-iec:guide:99</div></a>
</div>
<div id="ref-BIPM-VIM" class="csl-entry" role="doc-biblioentry">
[JCGM 200:2012] International vocabulary of metrology - Basic and
general concepts and associated terms (VIM) (JCGM 200:2012, 3rd
edition). <a href="https://jcgm.bipm.org/vim/en"><div class="csl-block">https://jcgm.bipm.org/vim/en</div></a>
</div>
<div id="ref-JSR-385" class="csl-entry" role="doc-biblioentry">
[JSR 385] Units of Measurement. <a href="https://unitsofmeasurement.github.io/indriya"><div class="csl-block">https://unitsofmeasurement.github.io/indriya</div></a>
</div>
<div id="ref-MARS_ORBITER" class="csl-entry" role="doc-biblioentry">
[Mars Orbiter] Mars Climate Orbiter. <a href="https://en.wikipedia.org/wiki/Mars_Climate_Orbiter"><div class="csl-block">https://en.wikipedia.org/wiki/Mars_Climate_Orbiter</div></a>
</div>
<div id="ref-MEDICATION_DOSE_ERRORS" class="csl-entry" role="doc-biblioentry">
[Medication dose errors] Alma Mulac, Ellen Hagesaether, and Anne Gerd
Granas. Medication dose calculation errors and other numeracy mishaps in
hospitals: Analysis of the nature and enablers of incident reports. <a href="https://onlinelibrary.wiley.com/doi/10.1111/jan.15072"><div class="csl-block">https://onlinelibrary.wiley.com/doi/10.1111/jan.15072</div></a>
</div>
<div id="ref-MP-UNITS" class="csl-entry" role="doc-biblioentry">
[mp-units] mp-units - A Physical Quantities and Units library for C++.
<a href="https://mpusz.github.io/mp-units"><div class="csl-block">https://mpusz.github.io/mp-units</div></a>
</div>
<div id="ref-NIC-UNITS" class="csl-entry" role="doc-biblioentry">
[nholthaus/units] UNITS. <a href="https://github.com/nholthaus/units"><div class="csl-block">https://github.com/nholthaus/units</div></a>
</div>
<div id="ref-P2980_PRE" class="csl-entry" role="doc-biblioentry">
[P2980] Mateusz Pusz, Dominik Berner, Johel Ernesto Guerrero Peña, Chip
Hogg, Nicolas Holthaus, Roth Michaels, and Vincent Reverdy. A
motivation, scope, and plan for a physical quantities and units library.
<a href="https://wg21.link/p2980"><div class="csl-block">https://wg21.link/p2980</div></a>
</div>
<div id="ref-PINT" class="csl-entry" role="doc-biblioentry">
[Pint] Pint: makes units easy. <a href="https://pint.readthedocs.io/en/stable/index.html"><div class="csl-block">https://pint.readthedocs.io/en/stable/index.html</div></a>
</div>
<div id="ref-STONEHENGE" class="csl-entry" role="doc-biblioentry">
[Stonehenge] Tim Robey. Tiny stones, giant laughs: the story behind
Spinal Tap’s Stonehenge. <a href="https://www.telegraph.co.uk/films/2020/05/01/tiny-stones-giant-laughs-story-behind-spinal-taps-stonehenge"><div class="csl-block">https://www.telegraph.co.uk/films/2020/05/01/tiny-stones-giant-laughs-story-behind-spinal-taps-stonehenge</div></a>
</div>
<div id="ref-VASA" class="csl-entry" role="doc-biblioentry">
[Vasa] Rhitu Chatterjee and Lisa Mullins. New Clues Emerge in
Centuries-Old Swedish Shipwreck. <a href="https://theworld.org/stories/2012-02-23/new-clues-emerge-centuries-old-swedish-shipwreck"><div class="csl-block">https://theworld.org/stories/2012-02-23/new-clues-emerge-centuries-old-swedish-shipwreck</div></a>
</div>
<div id="ref-WILD_RICE" class="csl-entry" role="doc-biblioentry">
[Wild Rice] Manufacturers, exporters think metric. <a href="https://www.bizjournals.com/eastbay/stories/2001/07/09/focus3.html"><div class="csl-block">https://www.bizjournals.com/eastbay/stories/2001/07/09/focus3.html</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
