<!DOCTYPE html>
<!-- saved from url=(0101)https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#systems-support -->
<html lang="en" class="gr__mpusz_github_io"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>P1935R1: A C++ Approach to Physical Units</title>
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in §N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

/******************************************************************************/
/*                                   Body                                     */
/******************************************************************************/

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;               /* limit line length to 50em for readability   */
		margin: 0 auto;                /* center text within page                     */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag     */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		/* Colors */
		color: black;
		background: white top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		color: white;
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		border-color: #c00;
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 2;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
			color: black;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			background: white;
			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;
			background: white;
		}
		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		#toc-nav > a:hover,
		#toc-nav > a:focus {
			background: #f8f8f8;
		}
		#toc-nav > a:not(:hover):not(:focus) {
			color: #707070;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}

		#toc-toggle-inline {
			vertical-align: 0.05em;
			font-size: 80%;
			color: gray;
			color: hsla(203,20%,40%,.7);
			border-style: none;
			background: transparent;
			position: relative;
		}
		#toc-toggle-inline:hover:not(:active),
		#toc-toggle-inline:focus:not(:active) {
			text-shadow: 1px 1px silver;
			top: -1px;
			left: -1px;
		}

		#toc-nav :active {
			color: #C00;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;    /* Inherit the font family. */
		line-height: 1.2;        /* Keep wrapped headings compact */
		hyphens: manual;         /* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		background: transparent;
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#subtitle {
		/* #subtitle is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	 border-left: 0.5em solid #DEF;
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	  padding: .5em;
	  border: thin solid #ddd; border-radius: .5em;
	  margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	  margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	  margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	 margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	 margin-left: -2em;
	}
	dl.switch {
	 padding-left: 2em;
	}
	dl.switch > dt {
	 text-indent: -1.5em;
	 margin-top: 1em;
	}
	dl.switch > dt + dt {
	 margin-top: 0;
	}
	dl.switch > dt::before {
	 content: '\21AA';
	 padding: 0 0.5em 0 0;
	 display: inline-block;
	 width: 1em;
	 text-align: right;
	 line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: medium;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del { color: red;  text-decoration: line-through; }
	ins { color: #080; text-decoration: underline;    }

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		page-break-inside: avoid;
		hyphens: none;
		text-transform: none;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

  /* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		text-decoration: none;
		border-bottom: 1px solid #707070;
		/* Need a bit of extending for it to look okay */
		padding: 0 1px 0;
		margin: 0 -1px 0;
	}
	a:visited {
		border-bottom-color: #BBB;
	}

	/* Use distinguishing colors when user is interacting with the link */
	a[href]:focus,
	a[href]:hover {
		background: #f8f8f8;
		background: rgba(75%, 75%, 75%, .25);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	a[href]:active {
		color: #C00;
		border-color: #C00;
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	/* For autogen numbers, add
	   .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,    .sidefigure img,    figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote {
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	.issue,
	.note,
	.example,
	.advisement,
	.assertion,
	blockquote {
		margin: 1em auto;
	}
	.note  > p:first-child,
	.issue > p:first-child,
	blockquote > :first-child {
		margin-top: 0;
	}
	blockquote > :last-child {
		margin-bottom: 0;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #E05252;
		background: #FBE9E9;
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		text-transform: uppercase;
		color: #AE1E1E;
		padding-right: 1em;
		text-transform: uppercase;
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	   or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #E0CB52;
		background: #FCFAEE;
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		text-transform: uppercase;
		color: #827017;
		min-width: 7.5em;
		display: block;
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	   or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52E052;
		background: #E9FBE9;
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary::before,
	details.note > summary > .marker {
		text-transform: uppercase;
		display: block;
		color: hsl(120, 70%, 30%);
	}
	/* Add .note::before { content: "Note"; } for autogen label,
	   or use class="marker" to mark up the label in source. */

	details.note > summary {
		display: block;
		color: hsl(120, 70%, 30%);
	}
	details.note[open] > summary {
		border-bottom: 1px silver solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		background: #EEE;
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-style: none solid;
		background: #FFEECC;
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement > .marker {
		color: #B35F00;
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: #fdd;
		color: red;
		font-weight: bold;
		padding: .75em 1em;
		border: thick red;
		border-style: solid;
		border-radius: 1em;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

@media not print {
	details.annoying-warning[open] {
		position: fixed;
		left: 1em;
		right: 1em;
		bottom: 1em;
		z-index: 1000;
	}
}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #DEF;
		margin: 1.2em 0;
		border-left: 0.5em solid #8CCBF2;
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def           td.footnote {
		padding-top: 0.6em;
	}
	table.def           td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		 <table class="data"> highlights structural relationships in a table
		 when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		 Use class="complex data" for particularly complicated tables --
		 (This will draw more lines: busier, but clearer.)

		 Use class="long" on table cells with paragraph-like contents
		 (This will adjust text alignment accordingly.)
		 Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
	 vertical-align: baseline;
	 text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding-top: 0.1rem;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Reverse color scheme */
		color: black;
		border-color: #3980B5;
		border-bottom-width: 3px !important;
		margin-bottom: 0px !important;
	}
	.toc a:visited {
		border-color: #054572;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
		line-height: 1.1rem; /* consistent spacing */
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li             { font-weight: bold;   }
	.toc > li li          { font-weight: normal; }
	.toc > li li li       { font-size:   95%;    }
	.toc > li li li li    { font-size:   90%;    }
	.toc > li li li li .secno { font-size: 85%; }
	.toc > li li li li li { font-size:   85%;    }
	.toc > li li li li li .secno { font-size: 100%; }

	/* @supports not (display:grid) { */
		.toc > li             { margin: 1.5rem 0;    }
		.toc > li li          { margin: 0.3rem 0;    }
		.toc > li li li       { margin-left: 2rem;   }

		/* Section numbers in a column of their own */
		.toc .secno {
			float: left;
			width: 4rem;
			white-space: nowrap;
		}

		.toc li {
			clear: both;
		}

		:not(li) > .toc              { margin-left:  5rem; }
		.toc .secno                  { margin-left: -5rem; }
		.toc > li li li .secno       { margin-left: -7rem; }
		.toc > li li li li .secno    { margin-left: -9rem; }
		.toc > li li li li li .secno { margin-left: -11rem; }

		/* Tighten up indentation in narrow ToCs */
		@media (max-width: 30em) {
			:not(li) > .toc              { margin-left:  4rem; }
			.toc .secno                  { margin-left: -4rem; }
			.toc > li li li              { margin-left:  1rem; }
			.toc > li li li .secno       { margin-left: -5rem; }
			.toc > li li li li .secno    { margin-left: -6rem; }
			.toc > li li li li li .secno { margin-left: -7rem; }
		}
	/* } */

	@supports (display:grid) and (display:contents) {
		/* Use #toc over .toc to override non-@supports rules. */
		#toc {
			display: grid;
			align-content: start;
			grid-template-columns: auto 1fr;
			grid-column-gap: 1rem;
			column-gap: 1rem;
			grid-row-gap: .6rem;
			row-gap: .6rem;
		}
		#toc h2 {
			grid-column: 1 / -1;
			margin-bottom: 0;
		}
		#toc ol,
		#toc li,
		#toc a {
			display: contents;
			/* Switch <a> to subgrid when supported */
		}
		#toc span {
			margin: 0;
		}
		#toc > .toc > li > a > span {
			/* The spans of the top-level list,
			   comprising the first items of each top-level section. */
			margin-top: 1.1rem;
		}
		#toc#toc .secno { /* Ugh, need more specificity to override base.css */
			grid-column: 1;
			width: auto;
			margin-left: 0;
		}
		#toc .content {
			grid-column: 2;
			width: auto;
			margin-right: 1rem;
		}
		#toc .content:hover {
			background: rgba(75%, 75%, 75%, .25);
			border-bottom: 3px solid #054572;
			margin-bottom: -3px;
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index       { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li    { margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em }
	ul.index dl    { margin-top: 0; }
	ul.index dt    { margin: .2em 0 .2em 20px;}
	ul.index dd    { margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		background: #f7f8f9;
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}

/******************************************************************************/
/*                                    Legacy                                  */
/******************************************************************************/

	/* This rule is inherited from past style sheets. No idea what it's for. */
	.hide { display: none }



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-left: calc(13px + 26.5rem - 50vw);
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-left: calc(40em - 50vw) !important;
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-left: 0 !important;
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			 * http://lea.verou.me/2012/04/background-attachment-local/
			 *
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
			            top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
			            top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style type="text/css">
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }

    del { background: #fcc; color: #000; text-decoration: line-through; }
    ins { background: #cfc; color: #000; }
    blockquote .highlight:not(.idl) { background: initial; margin: initial; padding: 0.5em }
    blockquote ul { background: inherit; }
    blockquote code.highlight:not(.idl) { padding: initial; }
    blockquote c-[a] { color: inherit; } /* Keyword.Declaration */
    blockquote c-[b] { color: inherit; } /* Keyword.Type */
    blockquote c-[c] { color: inherit; } /* Comment */
    blockquote c-[d] { color: inherit; } /* Comment.Multiline */
    blockquote c-[e] { color: inherit; } /* Name.Attribute */
    blockquote c-[f] { color: inherit; } /* Name.Tag */
    blockquote c-[g] { color: inherit; } /* Name.Variable */
    blockquote c-[k] { color: inherit; } /* Keyword */
    blockquote c-[l] { color: inherit; } /* Literal */
    blockquote c-[m] { color: inherit; } /* Literal.Number */
    blockquote c-[n] { color: inherit; } /* Name */
    blockquote c-[o] { color: inherit; } /* Operator */
    blockquote c-[p] { color: inherit; } /* Punctuation */
    blockquote c-[s] { color: inherit; } /* Literal.String */
    blockquote c-[t] { color: inherit; } /* Literal.String.Single */
    blockquote c-[u] { color: inherit; } /* Literal.String.Double */
    blockquote c-[cp] { color: inherit; } /* Comment.Preproc */
    blockquote c-[c1] { color: inherit; } /* Comment.Single */
    blockquote c-[cs] { color: inherit; } /* Comment.Special */
    blockquote c-[kc] { color: inherit; } /* Keyword.Constant */
    blockquote c-[kn] { color: inherit; } /* Keyword.Namespace */
    blockquote c-[kp] { color: inherit; } /* Keyword.Pseudo */
    blockquote c-[kr] { color: inherit; } /* Keyword.Reserved */
    blockquote c-[ld] { color: inherit; } /* Literal.Date */
    blockquote c-[nc] { color: inherit; } /* Name.Class */
    blockquote c-[no] { color: inherit; } /* Name.Constant */
    blockquote c-[nd] { color: inherit; } /* Name.Decorator */
    blockquote c-[ni] { color: inherit; } /* Name.Entity */
    blockquote c-[ne] { color: inherit; } /* Name.Exception */
    blockquote c-[nf] { color: inherit; } /* Name.Function */
    blockquote c-[nl] { color: inherit; } /* Name.Label */
    blockquote c-[nn] { color: inherit; } /* Name.Namespace */
    blockquote c-[py] { color: inherit; } /* Name.Property */
    blockquote c-[ow] { color: inherit; } /* Operator.Word */
    blockquote c-[mb] { color: inherit; } /* Literal.Number.Bin */
    blockquote c-[mf] { color: inherit; } /* Literal.Number.Float */
    blockquote c-[mh] { color: inherit; } /* Literal.Number.Hex */
    blockquote c-[mi] { color: inherit; } /* Literal.Number.Integer */
    blockquote c-[mo] { color: inherit; } /* Literal.Number.Oct */
    blockquote c-[sb] { color: inherit; } /* Literal.String.Backtick */
    blockquote c-[sc] { color: inherit; } /* Literal.String.Char */
    blockquote c-[sd] { color: inherit; } /* Literal.String.Doc */
    blockquote c-[se] { color: inherit; } /* Literal.String.Escape */
    blockquote c-[sh] { color: inherit; } /* Literal.String.Heredoc */
    blockquote c-[si] { color: inherit; } /* Literal.String.Interpol */
    blockquote c-[sx] { color: inherit; } /* Literal.String.Other */
    blockquote c-[sr] { color: inherit; } /* Literal.String.Regex */
    blockquote c-[ss] { color: inherit; } /* Literal.String.Symbol */
    blockquote c-[vc] { color: inherit; } /* Name.Variable.Class */
    blockquote c-[vg] { color: inherit; } /* Name.Variable.Global */
    blockquote c-[vi] { color: inherit; } /* Name.Variable.Instance */
    blockquote c-[il] { color: inherit; } /* Literal.Number.Integer.Long */
  </style>
  <meta content="Bikeshed version 2dbd5e1f0bb11704a5d90167ddaef9475f9c26b3" name="generator">
  <link href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="b731024c706236b9058e325da380dff0a86fda44" name="document-revision">
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-selflinks */

.heading, .issue, .note, .example, li, dt {
    position: relative;
}
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;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: gray;
    color: white;
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: black;
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }</style>
<style>/* style-counters */

body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: #005a9c;
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}</style>
<style>/* style-dfn-panel */

.dfn-panel {
    position: absolute;
    z-index: 35;
    height: auto;
    width: -webkit-fit-content;
    width: fit-content;
    max-width: 300px;
    max-height: 500px;
    overflow: auto;
    padding: 0.5em 0.75em;
    font: small Helvetica Neue, sans-serif, Droid Sans Fallback;
    background: #DDDDDD;
    color: black;
    border: outset 0.2em;
}
.dfn-panel:not(.on) { display: none; }
.dfn-panel * { margin: 0; padding: 0; text-indent: 0; }
.dfn-panel > b { display: block; }
.dfn-panel a { color: black; }
.dfn-panel a:not(:hover) { text-decoration: none !important; border-bottom: none !important; }
.dfn-panel > b + b { margin-top: 0.25em; }
.dfn-panel ul { padding: 0; }
.dfn-panel li { list-style: inside; }
.dfn-panel.activated {
    display: inline-block;
    position: fixed;
    left: .5em;
    bottom: 2em;
    margin: 0 auto;
    max-width: calc(100vw - 1.5em - .4em - .5em);
    max-height: 30vh;
}

.dfn-paneled { cursor: pointer; }
</style>
<style>/* style-syntax-highlighting */

.highlight:not(.idl) { background: hsl(24, 20%, 95%); }
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */
</style>
 </head><body class="h-entry toc-sidebar" data-gr-c-s-loaded="true"><p id="toc-nav"><a id="toc-jump" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#toc"><span aria-hidden="true">↑</span> <span>Jump to Table of Contents</span></a><a id="toc-toggle" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#toc"><span aria-hidden="true">←</span> <span>Collapse Sidebar</span></a></p>
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P1935R1<br>A C++ Approach to Physical Units</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2019-11-07">2019-11-07</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     </dt><dd><a class="u-url" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html">https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html</a>
     </dd><dt>Author:
     </dt><dd>
      </dd><dd class="editor p-author h-card vcard"><a class="p-name fn u-url url" href="http://www.train-it.eu/">Mateusz Pusz</a> (<a class="p-org org" href="http://www.epam.com/">Epam Systems</a>) <a class="u-email email" href="mailto:mateusz.pusz@gmail.com">mateusz.pusz@gmail.com</a>
     </dd><dt>Audience:
     </dt><dd>LEWG, SG6, SG16, SG18
     </dd><dt>Project:
     </dt><dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     </dd><dt>Source:
     </dt><dd><a href="https://github.com/mpusz/wg21_papers/blob/master/src/1935_a_cpp_approach_to_physical_units.bs">github.com/mpusz/wg21_papers/blob/master/src/1935_a_cpp_approach_to_physical_units.bs</a>
    </dd></dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>This document starts the discussion about the Physical Units support for the

          C++ Standard Library. The reader will find here the rationale for such a library.
          After that comes the review and comparison of current solutions on the market
          followed by the analysis of the problems related to their usage and user
          experience. The rest of the document describes solutions and techniques that
          can be used to mitigate those issues. All of them were implemented and tested
          by the author in the mp-units library.</p>
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#revision-history"><span class="secno">1</span> <span class="content">Revision History</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#r0r1"><span class="secno">1.1</span> <span class="content">r0 ➡ r1</span></a>
     </li></ol>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#introduction"><span class="secno">2</span> <span class="content">Introduction</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#overview"><span class="secno">2.1</span> <span class="content">Overview</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#lack-of-strong-types"><span class="secno">2.2</span> <span class="content">Lack of strong types</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#magic-numbers"><span class="secno">2.3</span> <span class="content">The proliferation of magic numbers</span></a>
     </li></ol>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#motivation-and-scope"><span class="secno">3</span> <span class="content">Motivation and Scope</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#motivation"><span class="secno">3.1</span> <span class="content">Motivation</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#goal"><span class="secno">3.2</span> <span class="content">The Goal</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#scope"><span class="secno">3.3</span> <span class="content">Scope</span></a>
     </li></ol>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#terms-and_definitions"><span class="secno">4</span> <span class="content">Terms and definitions</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#iso-definitions"><span class="secno">4.1</span> <span class="content">ISO 80000-1:2009(E) definitions</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#other-definitions"><span class="secno">4.2</span> <span class="content">Other definitions</span></a>
     </li></ol>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#prior-work"><span class="secno">5</span> <span class="content">Prior Work</span></a>
     <ol class="toc">
      <li>
       <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#boost.units"><span class="secno">5.1</span> <span class="content">Boost.Units</span></a>
       <ol class="toc">
        <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#boost.units.usage.example"><span class="secno">5.1.1</span> <span class="content">Usage example</span></a>
        </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#boost.units.design"><span class="secno">5.1.2</span> <span class="content">Design</span></a>
       </li></ol>
      </li><li>
       <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#cppnow17-units"><span class="secno">5.2</span> <span class="content">cppnow17-units</span></a>
       <ol class="toc">
        <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#cppnow17-units.design"><span class="secno">5.2.1</span> <span class="content">Design</span></a>
       </li></ol>
      </li><li>
       <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#PhysUnits-CT-Cpp11"><span class="secno">5.3</span> <span class="content">PhysUnits-CT-Cpp11</span></a>
       <ol class="toc">
        <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#PhysUnits-CT-Cpp11.usage.example"><span class="secno">5.3.1</span> <span class="content">Usage example</span></a>
        </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#PhysUnits-CT-Cpp11.design"><span class="secno">5.3.2</span> <span class="content">Design</span></a>
       </li></ol>
      </li><li>
       <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nic-units"><span class="secno">5.4</span> <span class="content">Nic Holthaus units</span></a>
       <ol class="toc">
        <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nic-units.usage.example"><span class="secno">5.4.1</span> <span class="content">Usage example</span></a>
        </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nic-units.design"><span class="secno">5.4.2</span> <span class="content">Design</span></a>
       </li></ol>
      </li><li>
       <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#benri"><span class="secno">5.5</span> <span class="content">benri</span></a>
       <ol class="toc">
        <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#benri.usage.example"><span class="secno">5.5.1</span> <span class="content">Usage example</span></a>
        </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#benri.design"><span class="secno">5.5.2</span> <span class="content">Design</span></a>
       </li></ol>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#other"><span class="secno">5.6</span> <span class="content">Other</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#comparison"><span class="secno">5.7</span> <span class="content">Comparison</span></a>
     </li></ol>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#concerns"><span class="secno">6</span> <span class="content">Fundamental concerns with current solutions</span></a>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#user-experience"><span class="secno">7</span> <span class="content">Improving user experience</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#type-aliasing-issues"><span class="secno">7.1</span> <span class="content">Type aliasing issues</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#downcasting"><span class="secno">7.2</span> <span class="content">Downcasting facility</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#template-instantiation-issues"><span class="secno">7.3</span> <span class="content">Template instantiation issues</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#better-errors-with-concepts"><span class="secno">7.4</span> <span class="content">Better errors with C++20 concepts</span></a>
     </li></ol>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#limiting-intermediate-value-conversions"><span class="secno">8</span> <span class="content">Limiting intermediate quantity value conversions</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#arguments-type-deduction"><span class="secno">8.1</span> <span class="content">Template arguments type deduction</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#generic-programming-with-concepts"><span class="secno">8.2</span> <span class="content">Generic programming with concepts</span></a>
     </li></ol>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ratio-on-steroids"><span class="secno">9</span> <span class="content"><code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-></code> on steroids</span></a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#extensibility"><span class="secno">10</span> <span class="content">Extensibility</span></a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#easy-to-use-hard-to-abuse"><span class="secno">11</span> <span class="content">Easy to use and hard to abuse</span></a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#design-principles"><span class="secno">12</span> <span class="content">Design principles</span></a>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#open-questions"><span class="secno">13</span> <span class="content">Open questions</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#prefixes-and-units"><span class="secno">13.1</span> <span class="content">How to represent SI prefixes and derived units?</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nttp-usage"><span class="secno">13.2</span> <span class="content">NTTP usage</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#relative-vs-absolute"><span class="secno">13.3</span> <span class="content">Relative vs absolute quantity</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#systems-support"><span class="secno">13.4</span> <span class="content">Should we support <span>systems</span> as a separate type?</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#duration-interoperability"><span class="secno">13.5</span> <span class="content">Interoperability with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code></span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#integral-udl"><span class="secno">13.6</span> <span class="content">Should we provide integral UDLs?</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-in-quantity"><span class="secno">13.7</span> <span class="content"><code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">dim_length</c-><c- p="">,</c-> <c- n="">metre</c-><c- o="">&gt;</c-></code> or <code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">metre</c-><c- o="">&gt;</c-></code>?</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#seconds-int"><span class="secno">13.8</span> <span class="content">Should we provide <code class="highlight"><c- n="">seconds</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-></code> or stay with <code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">second</c-><c- p="">,</c-> <c- b="">int</c-><c- o="">&gt;</c-></code>?</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimensionless-quantities"><span class="secno">13.9</span> <span class="content">Should we provide support for <span>dimensionless quantities</span>?</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#number"><span class="secno">13.10</span> <span class="content">Number concept</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unicode"><span class="secno">13.11</span> <span class="content">What about Unicode?</span></a>
     </li></ol>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#impact"><span class="secno">14</span> <span class="content">Impact on the Standard</span></a>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#implementation"><span class="secno">15</span> <span class="content">Implementation Experience</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#mp-units.usage.example"><span class="secno">15.1</span> <span class="content">Usage example</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#mp-units.design"><span class="secno">15.2</span> <span class="content">Design</span></a>
     </li></ol>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#polls"><span class="secno">16</span> <span class="content">Polls</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#lewg"><span class="secno">16.1</span> <span class="content">LEWG</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#sg6"><span class="secno">16.2</span> <span class="content">SG6</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#sg16"><span class="secno">16.3</span> <span class="content">SG16</span></a>
     </li></ol>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#acknowledgements"><span class="secno">17</span> <span class="content">Acknowledgments</span></a>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#index"><span class="secno"></span> <span class="content">Index</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#index-defined-here"><span class="secno"></span> <span class="content">Terms defined by this specification</span></a>
     </li></ol>
    </li><li>
     <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#normative"><span class="secno"></span> <span class="content">Normative References</span></a>
      </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </li></ol>
   </li></ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="revision-history"><span class="secno">1. </span><span class="content">Revision History</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#revision-history"></a></h2>
   <h3 class="heading settled" data-level="1.1" id="r0r1"><span class="secno">1.1. </span><span class="content">r0 ➡ r1</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#r0r1"></a></h3>
   <ul>
    <li data-md="">
     <p>New definitions added (coherent system of units, base dimension, derived dimension, reduced
dimension) to <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#terms-and_definitions">§ 4 Terms and definitions</a></p>
    </li><li data-md="">
     <p><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#prior-work">§ 5 Prior Work</a> chapter updated</p>
    </li><li data-md="">
     <p><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#prefixes-and-units">§ 13.1 How to represent SI prefixes and derived units?</a> extended with last paragraph</p>
    </li><li data-md="">
     <p><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#systems-support">§ 13.4 Should we support systems as a separate type?</a> extended</p>
    </li><li data-md="">
     <p><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#integral-udl">§ 13.6 Should we provide integral UDLs?</a> updated</p>
    </li><li data-md="">
     <p><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#number">§ 13.10 Number concept</a> added</p>
    </li><li data-md="">
     <p><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unicode">§ 13.11 What about Unicode?</a> chapter added</p>
    </li><li data-md="">
     <p><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#implementation">§ 15 Implementation Experience</a> extended</p>
    </li><li data-md="">
     <p><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#duration-interoperability">§ 13.5 Interoperability with std::chrono::duration</a> alternative 2 replaced with a better idea</p>
    </li><li data-md="">
     <p><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#polls">§ 16 Polls</a> extended and split to separate ISO C++ rooms</p>
    </li><li data-md="">
     <p><a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-mp-units">[MP-UNITS]</a> code samples updated to reflect the current library design</p>
   </li></ul>
   <h2 class="heading settled" data-level="2" id="introduction"><span class="secno">2. </span><span class="content">Introduction</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#introduction"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="overview"><span class="secno">2.1. </span><span class="content">Overview</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#overview"></a></h3>
   <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 <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-mars_orbiter">[MARS_ORBITER]</a>.
That is not the only example here. People tend to confuse units quite often. We see similar
errors occurring in various domains over the years:</p>
   <ul>
    <li data-md="">
     <p>On October 12, 1492, Christopher Columbus unintentionally discovered America because
during his travel preparations he mixed Arabic mile with a Roman mile which led to
the wrong estimation of the equator and his expected travel distance <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-columbus">[COLUMBUS]</a></p>
    </li><li data-md="">
     <p>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 <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-gimli_glider">[GIMLI_GLIDER]</a></p>
    </li><li data-md="">
     <p>On April 15, 1999, Korean Air Cargo Flight 6316 crashed due to the miscommunication
between pilots about desired flight altitude <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-flight_6316">[FLIGHT_6316]</a></p>
    </li><li data-md="">
     <p>In February 2001 Zoo crew built an enclosure for Clarence the Tortoise with a weight of
250 pounds instead of 250 kilograms <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-clarence">[CLARENCE]</a></p>
    </li><li data-md="">
     <p>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 the confusion after
upgrading the specification from imperial to metric units <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-disney">[DISNEY]</a></p>
    </li><li data-md="">
     <p>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 <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-wild_rice">[WILD_RICE]</a></p>
    </li><li data-md="">
     <p>A whole set of medication dose errors...</p>
   </li></ul>
   <h3 class="heading settled" data-level="2.2" id="lack-of-strong-types"><span class="secno">2.2. </span><span class="content">Lack of strong types</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#lack-of-strong-types"></a></h3>
   <p>It turns out that in the C++ software most of our calculations in the physical units domain
are handled with fundamental types like <code class="highlight"><c- b="">double</c-></code>. Code like below is a typical example
here:</p>
<pre class="language-cpp highlight"><c- b="">double</c-> <c- n="">GlidePolar</c-><c- o="">::</c-><c- n="">MacCreadyAltitude</c-><c- p="">(</c-><c- b="">double</c-> <c- n="">emcready</c-><c- p="">,</c->
                                     <c- b="">double</c-> <c- n="">Distance</c-><c- p="">,</c->
                                     <c- k="">const</c-> <c- b="">double</c-> <c- n="">Bearing</c-><c- p="">,</c->
                                     <c- k="">const</c-> <c- b="">double</c-> <c- n="">WindSpeed</c-><c- p="">,</c->
                                     <c- k="">const</c-> <c- b="">double</c-> <c- n="">WindBearing</c-><c- p="">,</c->
                                     <c- b="">double</c-> <c- o="">*</c-><c- n="">BestCruiseTrack</c-><c- p="">,</c->
                                     <c- b="">double</c-> <c- o="">*</c-><c- n="">VMacCready</c-><c- p="">,</c->
                                     <c- k="">const</c-> <c- b="">bool</c-> <c- n="">isFinalGlide</c-><c- p="">,</c->
                                     <c- b="">double</c-> <c- o="">*</c-><c- n="">TimeToGo</c-><c- p="">,</c->
                                     <c- k="">const</c-> <c- b="">double</c-> <c- n="">AltitudeAboveTarget</c-><c- p="">,</c->
                                     <c- k="">const</c-> <c- b="">double</c-> <c- n="">cruise_efficiency</c-><c- p="">,</c->
                                     <c- k="">const</c-> <c- b="">double</c-> <c- n="">TaskAltDiff</c-><c- p="">);</c->
</pre>
   <p>Even though this example comes from an Open Source project, expensive revenue-generating
production source code often does not differ too much. We lack strong typedefs feature in the
core language, and without it, we are often too lazy to handcraft a new class type for each
use case.</p>
   <h3 class="heading settled" data-level="2.3" id="magic-numbers"><span class="secno">2.3. </span><span class="content">The proliferation of magic numbers</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#magic-numbers"></a></h3>
   <p>There are a lot of constants and conversion factors involved in the dimensional analysis.
Source code responsible for such computations is often trashed with magic numbers</p>
<pre class="language-cpp highlight"><c- c1="">// Air Density(kg/m3) from relative humidity(%),</c->
<c- c1="">// temperature(°C) and absolute pressure(Pa)</c->
<c- b="">double</c-> <c- nf="">AirDensity</c-><c- p="">(</c-><c- b="">double</c-> <c- n="">hr</c-><c- p="">,</c-> <c- b="">double</c-> <c- n="">temp</c-><c- p="">,</c-> <c- b="">double</c-> <c- n="">abs_press</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- p="">(</c-><c- mi="">1</c-><c- o="">/</c-><c- p="">(</c-><c- mf="">287.06</c-><c- o="">*</c-><c- p="">(</c-><c- n="">temp</c-><c- o="">+</c-><c- mf="">273.15</c-><c- p="">)))</c-> <c- o="">*</c->
         <c- p="">(</c-><c- n="">abs_press</c-> <c- o="">-</c-> <c- mf="">230.617</c-> <c- o="">*</c-> <c- n="">hr</c-> <c- o="">*</c-> <c- n="">exp</c-><c- p="">((</c-><c- mf="">17.5043</c-><c- o="">*</c-><c- n="">temp</c-><c- p="">)</c-><c- o="">/</c-><c- p="">(</c-><c- mf="">241.2</c-><c- o="">+</c-><c- n="">temp</c-><c- p="">)));</c->
<c- p="">}</c->
</pre>
   <h2 class="heading settled" data-level="3" id="motivation-and-scope"><span class="secno">3. </span><span class="content">Motivation and Scope</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#motivation-and-scope"></a></h2>
   <h3 class="heading settled" data-level="3.1" id="motivation"><span class="secno">3.1. </span><span class="content">Motivation</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#motivation"></a></h3>
   <p>There is a huge demand for high-quality physical units library in the industry and
scientific environments. The code that we write for fun and living should be correct, safe,
and easy to write. Although there are multiple such libraries available on the market, none
of them is a widely accepted production standard. We could just provide a yet another 3rd
party library covering this topic, but it is probably not the best idea.</p>
   <p>First of all, software that could benefit from such a library is not a niche in the market.
If it was the case, probably its needs could be fulfilled with a 3rd party highly-specialized
and narrow-use library. On the contrary, a broad range of production projects deals with units
conversions and dimensional analysis. Right now, having no other reasonable and easy to access
alternatives results in the proliferation of plain <code class="highlight"><c- b="">double</c-></code> type usage to express physical
quantities. Space, aviation, automotive, embedded, scientific, computer science, and many
other domains could benefit from strong types and conversions provided by such a library.</p>
   <p>Secondly, yet another library will not solve the issue for many customers. Many corporations
are not allowed to use 3rd party libraries in the production code. Also, an important point
here is the cooperation of different products from multiple vendors that use physical quantities
as vocabulary types in their interfaces. From the author’s experience gathered while working
with numerous corporations all over the world, there is a considerable difference between the
adoption of a mature 3rd party library and the usage of features released as a part of
the C++ Standard Library. If it were not the case all products would use Boost.Units already.
A motivating example here can be <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-></code> released as a part of C++11. Right now, no one
asks questions on how to represent timestamps and how to handle their conversions in the code. <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-></code> is the ultimate answer. So let us try to get <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">units</c-></code> in the C++
Standard Library too.</p>
   <h3 class="heading settled" data-level="3.2" id="goal"><span class="secno">3.2. </span><span class="content">The Goal</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#goal"></a></h3>
   <p>The aim of this paper is to standardize a physical units library that enables operations on
various dimensions and units:</p>
<pre class="language-cpp highlight"><c- c1="">// simple numeric operations</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">10</c-><c- n="">km</c-> <c- o="">/</c-> <c- mi="">2</c-> <c- o="">==</c-> <c- mi="">5</c-><c- n="">km</c-><c- p="">);</c->

<c- c1="">// unit conversions</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">1</c-><c- n="">h</c-> <c- o="">==</c-> <c- mi="">3600</c-><c- n="">s</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">1</c-><c- n="">km</c-> <c- o="">+</c-> <c- mi="">1</c-><c- n="">m</c-> <c- o="">==</c-> <c- mi="">1001</c-><c- n="">m</c-><c- p="">);</c->

<c- c1="">// dimension conversions</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">1</c-><c- n="">km</c-> <c- o="">/</c-> <c- mi="">1</c-><c- n="">s</c-> <c- o="">==</c-> <c- mi="">1000</c-><c- n="">mps</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">2</c-><c- n="">kmph</c-> <c- o="">*</c-> <c- mi="">2</c-><c- n="">h</c-> <c- o="">==</c-> <c- mi="">4</c-><c- n="">km</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">2</c-><c- n="">km</c-> <c- o="">/</c-> <c- mi="">2</c-><c- n="">kmph</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">h</c-><c- p="">);</c->

<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">1000</c-> <c- o="">/</c-> <c- mi="">1</c-><c- n="">s</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">kHz</c-><c- p="">);</c->

<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">10</c-><c- n="">km</c-> <c- o="">/</c-> <c- mi="">5</c-><c- n="">km</c-> <c- o="">==</c-> <c- mi="">2</c-><c- p="">);</c->
</pre>
   <p>We intent to provide users with cleaner interfaces by using strong types and concepts in
the interfaces rather than fundamental types with meaning described in comments or documentation:</p>
<pre class="language-cpp highlight"><c- k="">constexpr</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Length</c-> <c- k="">auto</c-> <c- n="">d</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Time</c-> <c- k="">auto</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>We further aim to provide unit conversion facilities and constants for users to rely on,
instead of magic numbers:</p>
<pre class="language-cpp highlight"><c- k="">using</c-> <c- k="">namespace</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">units_literals</c-><c- p="">;</c->

<c- k="">const</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">speed</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mf="">220.</c-><c- n="">km</c-><c- p="">,</c-> <c- mf="">2.</c-><c- n="">h</c-><c- p="">);</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- s="">"Average speed: "</c->
          <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">quantity_cast</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">kilometre_per_hour</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">speed</c-><c- p="">)</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->
</pre>
   <h3 class="heading settled" data-level="3.3" id="scope"><span class="secno">3.3. </span><span class="content">Scope</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#scope"></a></h3>
   <p>Although there is a public demand for a generic units library that could handle any units and
dimensions, the author suggests scoping the Committee efforts only on the physical and possibly
computer science (i.e. <code class="highlight"><c- n="">bit</c-></code>, <code class="highlight"><c- n="">byte</c-></code>, <code class="highlight"><c- n="">bitrate</c-></code>) units first. The library should be designed
with easy extensibility in mind so anyone needing a new base or derived dimensions
(i.e. <code class="highlight"><c- n="">coffee</c-><c- o="">/</c-><c- n="">milk</c-><c- o="">/</c-><c- n="">water</c-><c- o="">/</c-><c- n="">sugar</c-></code> system) could achieve this with a few lines of the C++ code
(not preprocessor macros).</p>
   <p>After releasing a first, restricted version of the library and observing how it is used we
can consider standardizing additional dimensions, units, and constants in the following
C++ releases.</p>
   <h2 class="heading settled" data-level="4" id="terms-and_definitions"><span class="secno">4. </span><span class="content">Terms and definitions</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#terms-and_definitions"></a></h2>
   <h3 class="heading settled" data-level="4.1" id="iso-definitions"><span class="secno">4.1. </span><span class="content">ISO 80000-1:2009(E) definitions</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#iso-definitions"></a></h3>
   <p>ISO 80000-1:2009(E) Quantities and units - Part 1: General <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-iso_80000-1">[ISO_80000-1]</a> defines among others the following terms:</p>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="quantity">quantity</dfn></p>
   <ul>
    <li data-md="">
     <p>Property of a phenomenon, body, or substance, where the property has a magnitude that can
be expressed by means of a number and a reference.</p>
    </li><li data-md="">
     <p>A reference can be a measurement unit, a measurement procedure, a reference material, or
a combination of such.</p>
    </li><li data-md="">
     <p>A quantity as defined here is a scalar. However, a vector or a tensor, the components of
which are quantities, is also considered to be a quantity.</p>
    </li><li data-md="">
     <p>The concept ’quantity’ may be generically divided into, e.g. ‘physical quantity’,
‘chemical quantity’, and ‘biological quantity’, or ‘base quantity’ and ‘derived quantity’.</p>
    </li><li data-md="">
     <p>Examples of quantities are: mass, length, density, magnetic field strength, etc.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-lt="kind of quantity|kind" data-noexport="" id="kind-of-quantity">kind of quantity, kind</dfn></p>
   <ul>
    <li data-md="">
     <p>Aspect common to mutually comparable <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity">quantities</a>.</p>
    </li><li data-md="">
     <p>The division of the concept ‘quantity’ into several kinds is to some extent arbitrary</p>
     <ul>
      <li data-md="">
       <p>i.e. the quantities diameter, circumference, and wavelength are generally considered
to be <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①">quantities</a> of the same kind, namely, of the kind of quantity called length.)</p>
     </li></ul>
    </li><li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②">Quantities</a> of the same kind within a given <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities">system of quantities</a> have the same quantity <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity">dimension</a>. However, <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③">quantities</a> of the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①">dimension</a> are not necessarily of
the same kind.</p>
     <ul>
      <li data-md="">
       <p>For example, the absorbed dose and the dose equivalent have the same
dimension. However, the former measures the absolute amount of radiation one receives
wherase the latter is a weighted measurement taking into account the kind of radiation
on was exposed to.</p>
     </li></ul>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-lt="system of quantities|system" data-noexport="" id="system-of-quantities">system of quantities, system</dfn></p>
   <ul>
    <li data-md="">
     <p>Set of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④">quantities</a> together with a set of non-contradictory equations relating those <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity⑤">quantities</a>.</p>
    </li><li data-md="">
     <p>Examples of systems of quantities are: the International System of Quantities, the Imperial
System, etc.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="base-quantity">base quantity</dfn></p>
   <ul>
    <li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity⑥">Quantity</a> in a conventionally chosen subset of a given <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①">system of quantities</a>, where
no <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity⑦">quantity</a> in the subset can be expressed in terms of the other <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity⑧">quantities</a> within that subset.</p>
    </li><li data-md="">
     <p>Base quantities are referred to as being mutually independent since a base quantity
cannot be expressed as a product of powers of the other base quantities.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="derived-quantity">derived quantity</dfn></p>
   <ul>
    <li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity⑨">Quantity</a>, in a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities②">system of quantities</a>, defined in terms of the base quantities of
that system.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-lt="International System of Quantities|ISQ" data-noexport="" id="international-system-of-quantities">International System of Quantities (ISQ)</dfn></p>
   <ul>
    <li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities③">System of quantities</a> based on the seven <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity">base quantities</a>: length, mass, time,
electric current, thermodynamic temperature, amount of substance, and luminous intensity.</p>
    </li><li data-md="">
     <p>The International System of Units (SI) is based on the ISQ.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-lt="dimension of a quantity|quantity dimension|dimension" data-noexport="" id="dimension-of-a-quantity">dimension of a quantity,
quantity dimension, dimension</dfn></p>
   <ul>
    <li data-md="">
     <p>Expression of the dependence of a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①⓪">quantity</a> on the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity①">base quantities</a> of
a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities④">system of quantities</a> as a product of powers of factors corresponding to the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity②">base
quantities</a>, omitting any numerical factors.</p>
    </li><li data-md="">
     <p>A power of a factor is the factor raised to an exponent. Each factor is the dimension of
a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity③">base quantity</a>.</p>
    </li><li data-md="">
     <p>In deriving the dimension of a quantity, no account is taken of its scalar, vector, or
tensor character.</p>
    </li><li data-md="">
     <p>In a given <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities⑤">system of quantities</a>:</p>
     <ul>
      <li data-md="">
       <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①①">quantities</a> of the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#kind-of-quantity" id="ref-for-kind-of-quantity">kind</a> have the same quantity dimension,</p>
      </li><li data-md="">
       <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①②">quantities</a> of different quantity dimensions are always of different <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#kind-of-quantity" id="ref-for-kind-of-quantity①">kinds</a>,</p>
      </li><li data-md="">
       <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①③">quantities</a> having the same quantity dimension are not necessarily of the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#kind-of-quantity" id="ref-for-kind-of-quantity②">kind</a>.</p>
     </li></ul>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-lt="quantity of dimension one|quantities of dimension one|dimensionless quantity" data-noexport="" id="quantity-of-dimension-one"> quantity of dimension one, dimensionless quantity</dfn></p>
   <ul>
    <li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①④">Quantity</a> for which all the exponents of the factors corresponding to the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity④">base quantities</a> in its <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity②">quantity dimension</a> are zero.</p>
    </li><li data-md="">
     <p>The term “dimensionless quantity” is commonly used and is kept here for historical reasons.
It stems from the fact that all exponents are zero in the symbolic representation of
the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity③">dimension</a> for such <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①⑤">quantities</a>. The term “quantity of dimension one” reflects
the convention in which the symbolic representation of the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity④">dimension</a> for such <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①⑥">quantities</a> is the symbol 1. This <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity⑤">dimension</a> is not a number, but the neutral
element for multiplication of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity⑥">dimensions</a>.</p>
    </li><li data-md="">
     <p>The measurement <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement">units</a> and values of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①⑦">quantities</a> of dimension one are numbers, but
such <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①⑧">quantities</a> convey more information than a number.</p>
    </li><li data-md="">
     <p>Some <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity①⑨">quantities</a> of dimension one are defined as the ratios of two <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②⓪">quantities</a> of
the same kind. The <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-derived-unit" id="ref-for-coherent-derived-unit">coherent derived unit</a> is the number one, symbol 1.</p>
    </li><li data-md="">
     <p>Numbers of entities are quantities of dimension one.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-lt="unit of measurement|measurement unit|unit" data-noexport="" id="unit-of-measurement">unit of measurement, measurement unit,
unit</dfn></p>
   <ul>
    <li data-md="">
     <p>Real scalar <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②①">quantity</a>, defined and adopted by convention, with which any other <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②②">quantity</a> of the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#kind-of-quantity" id="ref-for-kind-of-quantity③">kind</a> can be compared to express the ratio of the second
quantity to the first one as a number.</p>
    </li><li data-md="">
     <p>Measurement units are designated by conventionally assigned names and symbols.</p>
    </li><li data-md="">
     <p>Measurement units of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②③">quantities</a> of the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity⑦">quantity dimension</a> may be designated
by the same name and symbol even when the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②④">quantities</a> are not of the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#kind-of-quantity" id="ref-for-kind-of-quantity④">kind</a>.
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 <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②⑤">quantities</a> of the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#kind-of-quantity" id="ref-for-kind-of-quantity⑤">kind</a>. However, in some cases special
measurement unit names are restricted to be used with <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②⑥">quantities</a> of specific kind
only. 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>
    </li><li data-md="">
     <p>Measurement units of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-of-dimension-one" id="ref-for-quantity-of-dimension-one">quantities of dimension one</a> are numbers. In some cases, these
measurement units are given special names, e.g. radian, steradian, and decibel, or are
expressed by quotients such as millimole per mole equal to 10<sup>−3</sup> and microgram
per kilogram equal to 10<sup>−9</sup>.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="base-unit">base unit</dfn></p>
   <ul>
    <li data-md="">
     <p>Measurement unit that is adopted by convention for a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity⑤">base quantity</a>.</p>
    </li><li data-md="">
     <p>In each <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-system-of-units" id="ref-for-coherent-system-of-units">coherent system of units</a>, there is only one base unit for each <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity⑥">base quantity</a>.</p>
    </li><li data-md="">
     <p>A base unit may also serve for a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-quantity" id="ref-for-derived-quantity">derived quantity</a> of the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity⑧">quantity dimension</a>.</p>
    </li><li data-md="">
     <p>For example, the ISQ has the base units of: metre, kilogram, second, Ampere, Kelvin, mole,
and candela.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="derived-unit">derived unit</dfn></p>
   <ul>
    <li data-md="">
     <p>Measurement unit for a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-quantity" id="ref-for-derived-quantity①">derived quantity</a>.</p>
    </li><li data-md="">
     <p>For example, in the ISQ Newton, Pascal, and katal are derived units.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="coherent-derived-unit">coherent derived unit</dfn></p>
   <ul>
    <li data-md="">
     <p>Derived <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①">unit</a> that, for a given <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities⑥">system of quantities</a> and for a chosen set of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit">base units</a>, is a product of powers of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①">base units</a> with no other proportionality
factor than one.</p>
    </li><li data-md="">
     <p>A power of a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit②">base unit</a> is the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit③">base unit</a> raised to an exponent.</p>
    </li><li data-md="">
     <p>Coherence can be determined only with respect to a particular <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities⑦">system of quantities</a> and a given set of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit④">base units</a>. That is, if the metre and the second are base units,
the metre per second is the coherent derived unit of velocity.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="system-of-units">system of units</dfn></p>
   <ul>
    <li data-md="">
     <p>Set of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit⑤">base units</a> and <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-unit" id="ref-for-derived-unit">derived units</a>, together with their multiples and submultiples,
defined in accordance with given rules, for a given <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities⑧">system of quantities</a>.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="coherent-system-of-units">coherent system of units</dfn></p>
   <ul>
    <li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units" id="ref-for-system-of-units">System of units</a>, based on a given <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities⑨">system of quantities</a>, in which the measurement
unit for each <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-quantity" id="ref-for-derived-quantity②">derived quantity</a> is a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-derived-unit" id="ref-for-coherent-derived-unit①">coherent derived unit</a>.</p>
    </li><li data-md="">
     <p>A <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units" id="ref-for-system-of-units①">system of units</a> can be coherent only with respect to a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①⓪">system of quantities</a> and
the adopted <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit⑥">base units</a>.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-lt="off-system measurement unit|off-system unit" data-noexport="" id="off-system-measurement-unit">off-system measurement unit,
off-system unit</dfn></p>
   <ul>
    <li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②">Measurement unit</a> that does not belong to a given <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units" id="ref-for-system-of-units②">system of units</a>. For example, the
electronvolt (≈ 1,602 18 × 10–19 J) is an off-system measurement unit of energy with
respect to the SI or day, hour, minute are off-system measurement units of time with
respect to the SI.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-lt="International System of Units|SI" data-noexport="" id="international-system-of-units">International System of Units (SI)</dfn></p>
   <ul>
    <li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units" id="ref-for-system-of-units③">System of units</a>, based on the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-quantities" id="ref-for-international-system-of-quantities">International System of Quantities</a>, their names and
symbols, including a series of prefixes and their names and symbols, together with rules
for their use, adopted by the General Conference on Weights and Measures (CGPM)</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="multiple-of-a-unit">multiple of a unit</dfn></p>
   <ul>
    <li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement③">Measurement unit</a> obtained by multiplying a given <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement④">measurement unit</a> by an integer
greater than one.</p>
    </li><li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units">SI</a> prefixes refer strictly to powers of 10, and should not be used for powers of 2. That
is, 1 kbit should not be used to represent 1024 bits (2<sup>10</sup> bits), which is a
kibibit (1 Kibit).</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="submultiple-of-a-unit">submultiple of a unit</dfn></p>
   <ul>
    <li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement⑤">Measurement unit</a> obtained by dividing a given <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement⑥">measurement unit</a> by an integer
greater than one.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-lt="quantity value|value of a quantity|value" data-noexport="" id="quantity-value">quantity value, value of a quantity,
value</dfn></p>
   <ul>
    <li data-md="">
     <p>Number and reference together expressing magnitude of a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②⑦">quantity</a>.</p>
    </li><li data-md="">
     <p>A quantity value can be presented in more than one way.</p>
   </li></ul>
   <h3 class="heading settled" data-level="4.2" id="other-definitions"><span class="secno">4.2. </span><span class="content">Other definitions</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#other-definitions"></a></h3>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="base-dimension">base dimension</dfn></p>
   <ul>
    <li data-md="">
     <p>A <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity⑨">dimension</a> of a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity⑦">base quantity</a>.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="derived-dimension">derived dimension</dfn></p>
   <ul>
    <li data-md="">
     <p>A <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①⓪">dimension</a> of a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-quantity" id="ref-for-derived-quantity③">derived quantity</a>.</p>
    </li><li data-md="">
     <p>Often implemented as a list of exponents of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension" id="ref-for-base-dimension">base dimensions</a>.</p>
   </li></ul>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport="" id="reduced-dimension">reduced dimension</dfn></p>
   <p>A <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-dimension" id="ref-for-derived-dimension">derived dimension</a> in which:</p>
   <ul>
    <li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension" id="ref-for-base-dimension①">base dimensions</a> are not repeated in a list (each base dimension is provided at most once),</p>
    </li><li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension" id="ref-for-base-dimension②">base dimensions</a> are consistently ordered,</p>
    </li><li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension" id="ref-for-base-dimension③">base dimensions</a> having zero exponent are elided.</p>
   </li></ul>
   <h2 class="heading settled" data-level="5" id="prior-work"><span class="secno">5. </span><span class="content">Prior Work</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#prior-work"></a></h2>
   <p>There are multiple dimensional analysis libraries available on the market today. Some of them
are more successful than others, but none of them is a widely accepted standard in the C++
codebase (both for Open Source as well as production code). The next sections of this chapter
will describe the most interesting parts of selected libraries. The last section provides
an extensive comparison of their main features.</p>
   <p>{This chapter is incomplete and will be filled in D1935R1 that should be available as a draft
on the LEWG Wiki before Belfast meeting}</p>
   <h3 class="heading settled" data-level="5.1" id="boost.units"><span class="secno">5.1. </span><span class="content">Boost.Units</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#boost.units"></a></h3>
   <p>Boost.Units <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-boostunits">[BOOST.UNITS]</a> is probably the most widely adopted library in this domain.
It was first included in Boost 1.36.0 that was released in 2008.</p>
   <h4 class="heading settled" data-level="5.1.1" id="boost.units.usage.example"><span class="secno">5.1.1. </span><span class="content">Usage example</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#boost.units.usage.example"></a></h4>
<pre class="language-cpp highlight"><c- cp="">#include</c-> &lt;boost/units/io.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/quantity.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/systems/si/length.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/systems/si/time.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/systems/si/velocity.hpp&gt;
<c- cp="">#include</c-> &lt;cassert&gt;
<c- cp="">#include</c-> &lt;iostream&gt;

<c- k="">namespace</c-> <c- n="">bu</c-> <c- o="">=</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- p="">;</c->

<c- k="">constexpr</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">velocity</c-><c- o="">&gt;</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&gt;</c-> <c- n="">d</c-><c- p="">,</c->
                                                   <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">time</c-><c- o="">&gt;</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c-> <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c-> <c- p="">}</c->

<c- b="">void</c-> <c- n="">test</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mi="">10</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meters</c-><c- p="">,</c-> <c- mi="">2</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">seconds</c-><c- p="">);</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- mi="">5</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meters_per_second</c-><c- p="">);</c->  <c- c1="">// passes</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-><c- p="">.</c-><c- n="">value</c-><c- p="">()</c-> <c- o="">==</c-> <c- mi="">5</c-><c- p="">);</c->                      <c- c1="">// passes</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">v</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->                      <c- c1="">// prints "5 m s^-1"</c->
<c- p="">}</c->
</pre>
   <p><a href="https://godbolt.org/z/XITZI2">Compiler Explorer</a></p>
   <p>First thing to notice above is that a few headers have to be included just to make such a
simple code to compile. Novices with Boost.Units library report this as an issue as sometimes
it is not obvious why the code does not compile and which headers are missing.</p>
   <p>Now, let us extend such a code sample for a real-life use case where we would like to pass
a distance in kilometers or miles and duration in hours and get a velocity in those <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement⑦">units</a>.</p>
<pre class="language-cpp highlight"><c- cp="">#include</c-> &lt;boost/units/base_units/metric/hour.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/base_units/us/mile.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/io.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/make_scaled_unit.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/quantity.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/systems/si/length.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/systems/si/time.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/systems/si/velocity.hpp&gt;
<c- cp="">#include</c-> &lt;boost/units/systems/si/prefixes.hpp&gt;
<c- cp="">#include</c-> &lt;cassert&gt;
<c- cp="">#include</c-> &lt;iostream&gt;

<c- k="">namespace</c-> <c- n="">bu</c-> <c- o="">=</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- p="">;</c->

<c- k="">using</c-> <c- n="">kilometer_base_unit</c-> <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">make_scaled_unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- p="">,</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">scale</c-><c- o="">&lt;</c-><c- mi="">10</c-><c- p="">,</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">static_rational</c-><c- o="">&lt;</c-><c- mi="">3</c-><c- o="">&gt;&gt;&gt;::</c-><c- n="">type</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">length_kilometer</c-> <c- o="">=</c-> <c- n="">kilometer_base_unit</c-><c- o="">::</c-><c- n="">unit_type</c-><c- p="">;</c->

<c- k="">using</c-> <c- n="">length_mile</c-> <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">us</c-><c- o="">::</c-><c- n="">mile_base_unit</c-><c- o="">::</c-><c- n="">unit_type</c-><c- p="">;</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">miles</c-><c- p="">,</c-> <c- n="">length_mile</c-><c- p="">);</c->

<c- k="">using</c-> <c- n="">time_hour</c-> <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">metric</c-><c- o="">::</c-><c- n="">hour_base_unit</c-><c- o="">::</c-><c- n="">unit_type</c-><c- p="">;</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">hours</c-><c- p="">,</c-> <c- n="">time_hour</c-><c- p="">);</c->

<c- k="">using</c-> <c- n="">velocity_kilometers_per_hour</c-> <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">divide_typeof_helper</c-><c- o="">&lt;</c-><c- n="">length_kilometer</c-><c- p="">,</c-> <c- n="">time_hour</c-><c- o="">&gt;::</c-><c- n="">type</c-><c- p="">;</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">kilometers_per_hour</c-><c- p="">,</c-> <c- n="">velocity_kilometers_per_hour</c-><c- p="">);</c->

<c- k="">using</c-> <c- n="">velocity_miles_per_hour</c-> <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">divide_typeof_helper</c-><c- o="">&lt;</c-><c- n="">length_mile</c-><c- p="">,</c-> <c- n="">time_hour</c-><c- o="">&gt;::</c-><c- n="">type</c-><c- p="">;</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">miles_per_hour</c-><c- p="">,</c-> <c- n="">velocity_miles_per_hour</c-><c- p="">);</c->


<c- k="">constexpr</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">velocity</c-><c- o="">&gt;</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&gt;</c-> <c- n="">d</c-><c- p="">,</c->
                                                   <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">time</c-><c- o="">&gt;</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c-> <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c-> <c- p="">}</c->

<c- b="">void</c-> <c- n="">test1</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">220</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">kilo</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meters</c-><c- p="">),</c->
                           <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">time</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">2</c-> <c- o="">*</c-> <c- n="">hours</c-><c- p="">));</c->
  <c- c1="">// assert(v.value() == 110);                   // fails</c->
  <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">velocity_kilometers_per_hour</c-><c- o="">&gt;</c-> <c- n="">kmph</c-><c- p="">(</c-><c- n="">v</c-><c- p="">);</c->
  <c- c1="">// assert(kmph == 110 * kilometers_per_hour);  // fails</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">kmph</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->                     <c- c1="">// prints "110 k(m h^-1)"</c->
<c- p="">}</c->

<c- b="">void</c-> <c- n="">test2</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">140</c-> <c- o="">*</c-> <c- n="">miles</c-><c- p="">),</c->
                           <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">time</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">2</c-> <c- o="">*</c-> <c- n="">hours</c-><c- p="">));</c->
  <c- c1="">// assert(v.value() == 70);             // fails</c->
  <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">velocity_miles_per_hour</c-><c- o="">&gt;</c-> <c- n="">mph</c-><c- p="">(</c-><c- n="">v</c-><c- p="">);</c->
  <c- c1="">// assert(mph == 70 * miles_per_hour);  // fails</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">mph</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->               <c- c1="">// prints "70 mi h^-1"</c->
<c- p="">}</c->
</pre>
   <p><a href="https://godbolt.org/z/-hRa66">Compiler Explorer</a></p>
   <p>Even with such a simple example we immediately need to include even more headers and we
have to define custom <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement⑧">unit</a> types and their constants for quantities that should be common
and provided by the library for user’s convenience.</p>
   <p>Also, please notice that both pairs of asserts fail. This is caused by the fact that this
and many other units libraries implicitly convert all the units to the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-derived-unit" id="ref-for-coherent-derived-unit②">coherent derived
units</a> of their dimensions which impacts the runtime performance and precision. This is another
common problem reported by users for Boost.Units. More information on this subject can be
found at <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#limiting-intermediate-value-conversions">§ 8 Limiting intermediate quantity value conversions</a>).</p>
   <p>To remove unnecessary conversions we will use a function template. The good part is it
makes the assert to pass as there are no more intermediate conversions being done in both cases.
However, the side effect of this change is an increased complexity of code which now is
probably too hard to be implemented by a common C++ developer:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">LengthSystem</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Rep1</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">TimeSystem</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Rep2</c-><c- o="">&gt;</c->
<c- k="">constexpr</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">divide_typeof_helper</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">length_dimension</c-><c- p="">,</c-> <c- n="">LengthSystem</c-><c- o="">&gt;</c-><c- p="">,</c->
                                                         <c- n="">bu</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">time_dimension</c-><c- p="">,</c-> <c- n="">TimeSystem</c-><c- o="">&gt;&gt;::</c-><c- n="">type</c-><c- o="">&gt;</c->
<c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">length_dimension</c-><c- p="">,</c-> <c- n="">LengthSystem</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">Rep1</c-><c- o="">&gt;</c-> <c- n="">d</c-><c- p="">,</c->
          <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">time_dimension</c-><c- p="">,</c-> <c- n="">TimeSystem</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">Rep2</c-><c- o="">&gt;</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c-> <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c-> <c- p="">}</c->

<c- b="">void</c-> <c- n="">test1</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mi="">220</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">kilo</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meters</c-><c- p="">,</c-> <c- mi="">2</c-> <c- o="">*</c-> <c- n="">hours</c-><c- p="">);</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-><c- p="">.</c-><c- n="">value</c-><c- p="">()</c-> <c- o="">==</c-> <c- mi="">110</c-><c- p="">);</c->                <c- c1="">// passes</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- mi="">110</c-> <c- o="">*</c-> <c- n="">kilometers_per_hour</c-><c- p="">);</c->  <c- c1="">// passes</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">v</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->                  <c- c1="">// prints "110 k(m h^-1)"</c->
<c- p="">}</c->

<c- b="">void</c-> <c- n="">test2</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mi="">140</c-> <c- o="">*</c-> <c- n="">miles</c-><c- p="">,</c-> <c- mi="">2</c-> <c- o="">*</c-> <c- n="">hours</c-><c- p="">);</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-><c- p="">.</c-><c- n="">value</c-><c- p="">()</c-> <c- o="">==</c-> <c- mi="">70</c-><c- p="">);</c->           <c- c1="">// passes</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- mi="">70</c-> <c- o="">*</c-> <c- n="">miles_per_hour</c-><c- p="">);</c->  <c- c1="">// passes</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">v</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->            <c- c1="">// prints "70 mi h^-1"</c->
<c- p="">}</c->
</pre>
   <p><a href="https://godbolt.org/z/6kRNEb">Compiler Explorer</a></p>
   <p>The above example will be used as base for comparison to other units libraries described
in the next chapters.</p>
   <h4 class="heading settled" data-level="5.1.2" id="boost.units.design"><span class="secno">5.1.2. </span><span class="content">Design</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#boost.units.design"></a></h4>
   <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension" id="ref-for-base-dimension④">Base dimensions</a> are associated with tag types that have assigned a unique integer in order
to be able to sort them on a list of a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-dimension" id="ref-for-derived-dimension①">derived dimension</a>. Negative ordinals are reserved
for use by the library.</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Derived</c-><c- p="">,</c-> <c- b="">long</c-> <c- n="">N</c-><c- o="">&gt;</c-> 
<c- k="">class</c-> <c- nc="">base_dimension</c-> <c- o="">:</c-> <c- k="">public</c-> <c- n="">ordinal</c-><c- o="">&lt;</c-><c- n="">N</c-><c- o="">&gt;</c-> <c- p="">{</c->
<c- k="">public</c-><c- o="">:</c->
  <c- k="">typedef</c-> <c- n="">unspecified</c-> <c- n="">dimension_type</c-><c- p="">;</c->
  <c- k="">typedef</c-> <c- n="">Derived</c-> <c- n="">type</c-><c- p="">;</c->
<c- p="">};</c->
</pre>
   <p>To define custom base dimension the user has to:</p>
<pre class="language-cpp highlight"><c- k="">struct</c-> <c- nl="">my_dimension</c-> <c- p="">:</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_dimension</c-><c- o="">&lt;</c-><c- n="">my_dimension</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- p="">{};</c->
</pre>
   <p>To define <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-dimension" id="ref-for-derived-dimension②">derived dimensions</a> corresponding to the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension" id="ref-for-base-dimension⑤">base dimensions</a>, MPL-conformant
typelists of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension" id="ref-for-base-dimension⑥">base dimensions</a> must be created by using the <code class="highlight"><c- n="">dim</c-></code> class to encapsulate
pairs of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension" id="ref-for-base-dimension⑦">base dimensions</a> and <code class="highlight"><c- n="">static_rational</c-></code> exponents. The <code class="highlight"><c- n="">make_dimension_list</c-></code> class acts as a wrapper to ensure that the resulting type is in the form of a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#reduced-dimension" id="ref-for-reduced-dimension">reduced dimension</a>:</p>
<pre class="language-cpp highlight"><c- k="">typedef</c-> <c- n="">make_dimension_list</c-><c- o="">&lt;</c->
    <c- n="">boost</c-><c- o="">::</c-><c- n="">mpl</c-><c- o="">::</c-><c- n="">list</c-><c- o="">&lt;</c-><c- n="">dim</c-><c- o="">&lt;</c-><c- n="">length_base_dimension</c-><c- p="">,</c-><c- n="">static_rational</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- o="">&gt;&gt;&gt;</c->
<c- o="">&gt;::</c-><c- n="">type</c-> <c- n="">length_dimension</c-><c- p="">;</c->
</pre>
   <p>This can also be accomplished using a convenience typedef provided by <code class="highlight"><c- n="">base_dimension</c-></code>:</p>
<pre class="language-cpp highlight"><c- k="">typedef</c-> <c- n="">length_base_dimension</c-><c- o="">::</c-><c- n="">dimension_type</c-> <c- n="">length_dimension</c-><c- p="">;</c->
</pre>
   <p>To define the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-dimension" id="ref-for-derived-dimension③">derived dimension</a> similar steps have to be done:</p>
<pre class="language-cpp highlight"><c- k="">typedef</c-> <c- n="">make_dimension_list</c-><c- o="">&lt;</c->
    <c- n="">boost</c-><c- o="">::</c-><c- n="">mpl</c-><c- o="">::</c-><c- n="">list</c-><c- o="">&lt;</c-><c- n="">dim</c-><c- o="">&lt;</c-><c- n="">mass_base_dimension</c-><c- p="">,</c-> <c- n="">static_rational</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- o="">&gt;&gt;</c-><c- p="">,</c->
                     <c- n="">dim</c-><c- o="">&lt;</c-><c- n="">length_base_dimension</c-><c- p="">,</c-> <c- n="">static_rational</c-><c- o="">&lt;</c-><c- mi="">2</c-><c- o="">&gt;&gt;</c-><c- p="">,</c->
                     <c- n="">dim</c-><c- o="">&lt;</c-><c- n="">time_base_dimension</c-><c- p="">,</c-> <c- n="">static_rational</c-><c- o="">&lt;-</c-><c- mi="">2</c-><c- o="">&gt;&gt;&gt;</c->
<c- o="">&gt;::</c-><c- n="">type</c-> <c- n="">energy_dimension</c-><c- p="">;</c->
</pre>
   <p>or</p>
<pre class="language-cpp highlight"><c- k="">typedef</c-> <c- n="">derived_dimension</c-><c- o="">&lt;</c-><c- n="">mass_base_dimension</c-><c- p="">,</c-> <c- mi="">1</c-><c- p="">,</c->
                          <c- n="">length_base_dimension</c-><c- p="">,</c-> <c- mi="">2</c-><c- p="">,</c->
                          <c- n="">time_base_dimension</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">2</c-><c- o="">&gt;::</c-><c- n="">type</c-> <c- n="">energy_dimension</c-><c- p="">;</c->
</pre>
   <p>A <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement⑨">unit</a> is defined as a set of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit⑦">base units</a> each of which can be raised to an arbitrary
rational exponent. Units are, like dimensions, purely compile-time variables with no
associated value.</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Dim</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">System</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Enable</c-><c- o="">&gt;</c->
<c- k="">class</c-> <c- nc="">unit</c-> <c- p="">{</c->
<c- k="">public</c-><c- o="">:</c->
  <c- k="">typedef</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">Dim</c-><c- p="">,</c-> <c- n="">System</c-><c- o="">&gt;</c-> <c- n="">unit_type</c-><c- p="">;</c->
  <c- k="">typedef</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">Dim</c-><c- p="">,</c-> <c- n="">System</c-><c- o="">&gt;</c-> <c- n="">this_type</c-><c- p="">;</c->
  <c- k="">typedef</c-> <c- n="">Dim</c-> <c- n="">dimension_type</c-><c- p="">;</c->
  <c- k="">typedef</c-> <c- n="">System</c-> <c- n="">system_type</c-><c- p="">;</c->

  <c- n="">unit</c-><c- p="">();</c->
  <c- n="">unit</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">this_type</c-><c- o="">&amp;</c-><c- p="">);</c->
  <c- n="">BOOST_CXX14_CONSTEXPR</c-> <c- n="">this_type</c-><c- o="">&amp;</c-> <c- k="">operator</c-><c- o="">=</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">this_type</c-><c- o="">&amp;</c-><c- p="">);</c->
<c- p="">};</c->
</pre>
   <p>In addition to supporting the compile-time dimensional analysis operations, the <code class="highlight"><c- o="">+</c-></code>, <code class="highlight"><c- o="">-</c-></code>, <code class="highlight"><c- o="">*</c-></code>, and <code class="highlight"><c- o="">/</c-></code> runtime operators are provided for unit variables.</p>
   <p>Base units are defined much like base dimensions and again negative ordinals are reserved:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Derived</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Dim</c-><c- p="">,</c-> <c- b="">long</c-> <c- n="">N</c-><c- o="">&gt;</c->
<c- k="">class</c-> <c- nc="">base_unit</c-><c- p="">;</c->
</pre>
   <p>To define a simple <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units" id="ref-for-system-of-units④">system of units</a>:</p>
<pre class="language-cpp highlight"><c- k="">struct</c-> <c- nl="">meter_base_unit</c-> <c- p="">:</c-> <c- n="">base_unit</c-><c- o="">&lt;</c-><c- n="">meter_base_unit</c-><c- p="">,</c-> <c- n="">length_dimension</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- p="">{</c-> <c- p="">};</c->
<c- k="">struct</c-> <c- nl="">kilogram_base_unit</c-> <c- p="">:</c-> <c- n="">base_unit</c-><c- o="">&lt;</c-><c- n="">kilogram_base_unit</c-><c- p="">,</c-> <c- n="">mass_dimension</c-><c- p="">,</c-> <c- mi="">2</c-><c- o="">&gt;</c-> <c- p="">{</c-> <c- p="">};</c->
<c- k="">struct</c-> <c- nl="">second_base_unit</c-> <c- p="">:</c-> <c- n="">base_unit</c-><c- o="">&lt;</c-><c- n="">second_base_unit</c-><c- p="">,</c-> <c- n="">time_dimension</c-><c- p="">,</c-> <c- mi="">3</c-><c- o="">&gt;</c-> <c- p="">{</c-> <c- p="">};</c->

<c- k="">typedef</c-> <c- n="">make_system</c-><c- o="">&lt;</c-><c- n="">meter_base_unit</c-><c- p="">,</c-> <c- n="">kilogram_base_unit</c-><c- p="">,</c-> <c- n="">second_base_unit</c-><c- o="">&gt;::</c-><c- n="">type</c-> <c- n="">mks_system</c-><c- p="">;</c->

<c- k="">typedef</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">dimensionless_type</c-><c- p="">,</c-> <c- n="">mks_system</c-><c- o="">&gt;</c->      <c- n="">dimensionless</c-><c- p="">;</c->

<c- k="">typedef</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">length_dimension</c-><c- p="">,</c-> <c- n="">mks_system</c-><c- o="">&gt;</c->        <c- n="">length</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">mass_dimension</c-><c- p="">,</c-> <c- n="">mks_system</c-><c- o="">&gt;</c->          <c- n="">mass</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">time_dimension</c-><c- p="">,</c-> <c- n="">mks_system</c-><c- o="">&gt;</c->          <c- n="">time</c-><c- p="">;</c->

<c- k="">typedef</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">area_dimension</c-><c- p="">,</c-> <c- n="">mks_system</c-><c- o="">&gt;</c->          <c- n="">area</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">energy_dimension</c-><c- p="">,</c-> <c- n="">mks_system</c-><c- o="">&gt;</c->        <c- n="">energy</c-><c- p="">;</c->
</pre>
   <p>The macro <code class="highlight"><c- n="">BOOST_UNITS_STATIC_CONSTANT</c-></code> is provided to facilitate ODR- and thread-safe
constant definition in header files. With this some constants are defined for the supported
units to simplify variable definitions:</p>
<pre class="language-cpp highlight"><c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">meter</c-><c- p="">,</c-> <c- n="">length</c-><c- p="">);</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">meters</c-><c- p="">,</c-> <c- n="">length</c-><c- p="">);</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">kilogram</c-><c- p="">,</c-> <c- n="">mass</c-><c- p="">);</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">kilograms</c-><c- p="">,</c-> <c- n="">mass</c-><c- p="">);</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">second</c-><c- p="">,</c-> <c- n="">time</c-><c- p="">);</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">seconds</c-><c- p="">,</c-> <c- n="">time</c-><c- p="">);</c->

<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">square_meter</c-><c- p="">,</c-> <c- n="">area</c-><c- p="">);</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">square_meters</c-><c- p="">,</c-> <c- n="">area</c-><c- p="">);</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">joule</c-><c- p="">,</c-> <c- n="">energy</c-><c- p="">);</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">joules</c-><c- p="">,</c-> <c- n="">energy</c-><c- p="">);</c->
</pre>
   <p>To provide a textual output of units specialize the <code class="highlight"><c- n="">base_unit_info</c-></code> class for each
fundamental dimension tag:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;&gt;</c->
<c- k="">struct</c-> <c- n="">base_unit_info</c-><c- o="">&lt;</c-><c- n="">meter_base_unit</c-><c- o="">&gt;</c-> <c- p="">{</c->
  <c- k="">static</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">string</c-> <c- n="">name</c-><c- p="">()</c-> <c- p="">{</c-> <c- k="">return</c-> <c- s="">"meter"</c-><c- p="">;</c-> <c- p="">}</c->
  <c- k="">static</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">string</c-> <c- n="">symbol</c-><c- p="">()</c-> <c- p="">{</c-> <c- k="">return</c-> <c- s="">"m"</c-><c- p="">;</c-> <c- p="">}</c->
<c- p="">};</c->
</pre>
   <p>and similarly for <code class="highlight"><c- n="">kilogram_base_unit</c-></code> and <code class="highlight"><c- n="">second_base_unit</c-></code>.</p>
   <p>It is possible to define a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit⑧">base unit</a> as being a multiple of another <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit⑨">base unit</a>.
For example, the way that <code class="highlight"><c- n="">kilogram_base_unit</c-></code> is actually defined by the library is
along the following lines:</p>
<pre class="language-cpp highlight"><c- k="">struct</c-> <c- nl="">gram_base_unit</c-> <c- p="">:</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_unit</c-><c- o="">&lt;</c-><c- n="">gram_base_unit</c-><c- p="">,</c-> <c- n="">mass_dimension</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- p="">{};</c->
<c- k="">typedef</c-> <c- n="">scaled_base_unit</c-><c- o="">&lt;</c-><c- n="">gram_base_unit</c-><c- p="">,</c-> <c- n="">scale</c-><c- o="">&lt;</c-><c- mi="">10</c-><c- p="">,</c-> <c- n="">static_rational</c-><c- o="">&lt;</c-><c- mi="">3</c-><c- o="">&gt;&gt;&gt;</c-> <c- n="">kilogram_base_unit</c-><c- p="">;</c->
</pre>
   <p>It is also possible to scale a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①⓪">unit</a> as a whole, rather than scaling the individual <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①⓪">base units</a> which comprise it. For this purpose, the metafunction <code class="highlight"><c- n="">make_scaled_unit</c-></code> is used:</p>
<pre class="language-cpp highlight"><c- k="">typedef</c-> <c- n="">make_scaled_unit</c-><c- o="">&lt;</c-><c- n="">si</c-><c- o="">::</c-><c- n="">time</c-><c- p="">,</c-> <c- n="">scale</c-><c- o="">&lt;</c-><c- mi="">10</c-><c- p="">,</c-> <c- n="">static_rational</c-><c- o="">&lt;-</c-><c- mi="">9</c-><c- o="">&gt;&gt;&gt;::</c-><c- n="">type</c-> <c- n="">nanosecond</c-><c- p="">;</c->
</pre>
   <p>Interesting point to note here is that even though Boost.Units has a strong and deeply
integrated support for <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units" id="ref-for-system-of-units⑤">systems of units</a> it implements a US Customary
Units in an <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units①">SI</a> system rather than as an independent system of units:</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">us</c-> <c- p="">{</c->
  <c- k="">struct</c-> <c- nl="">yard_base_unit</c-> <c- p="">:</c-> <c- k="">public</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_unit</c-><c- o="">&lt;</c-><c- n="">yard_base_unit</c-><c- p="">,</c->
                                                         <c- n="">si</c-><c- o="">::</c-><c- n="">meter_base_unit</c-><c- o="">::</c-><c- n="">dimension_type</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">501</c-><c- o="">&gt;</c-> <c- p="">{</c->
    <c- k="">static</c-> <c- k="">const</c-> <c- b="">char</c-><c- o="">*</c-> <c- n="">name</c-><c- p="">();</c->
    <c- k="">static</c-> <c- k="">const</c-> <c- b="">char</c-><c- o="">*</c-> <c- nf="">symbol</c-><c- p="">();</c->
  <c- p="">};</c->

  <c- k="">typedef</c-> <c- n="">scaled_base_unit</c-><c- o="">&lt;</c-><c- n="">yard_base_unit</c-><c- p="">,</c-> <c- n="">scale</c-><c- o="">&lt;</c-><c- mi="">1760</c-><c- p="">,</c-> <c- n="">static_rational</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- o="">&gt;&gt;&gt;</c-> <c- n="">mile_base_unit</c-><c- p="">;</c->
<c- p="">}</c->

<c- k="">template</c-><c- o="">&lt;&gt;</c-> <c- k="">struct</c-> <c- n="">base_unit_info</c-><c- o="">&lt;</c-><c- n="">us</c-><c- o="">::</c-><c- n="">mile_base_unit</c-><c- o="">&gt;</c-><c- p="">;</c->
</pre>
   <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②⑧">Quantities</a> are implemented by the <code class="highlight"><c- n="">quantity</c-></code> class template:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Unit</c-><c- p="">,</c-><c- k="">class</c-> <c- nc="">Y</c-> <c- o="">=</c-> <c- b="">double</c-><c- o="">&gt;</c->
<c- k="">class</c-> <c- nc="">quantity</c-><c- p="">;</c->
</pre>
   <p>Operators <code class="highlight"><c- o="">+</c-></code>, <code class="highlight"><c- o="">-</c-></code>, <code class="highlight"><c- o="">*</c-></code>, and <code class="highlight"><c- o="">/</c-></code> are provided for algebraic operations between scalars and <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①①">units</a>, scalars and <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity②⑨">quantities</a>, <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①②">units</a> and <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③⓪">quantities</a>, and between <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③①">quantities</a>.
Also, the standard set of boolean comparison operators (<code class="highlight"><c- o="">==</c-></code>, <code class="highlight"><c- o="">!=</c-></code>, <code class="highlight"><c- o="">&lt;</c-></code>, <code class="highlight"><c- o="">&lt;=</c-></code>, <code class="highlight"><c- o="">&gt;</c-></code>, and <code class="highlight"><c- o="">&gt;=</c-></code>) are provided to allow comparison of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③②">quantities</a> from the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units" id="ref-for-system-of-units⑥">system of units</a>.
In addition, integral and rational powers and roots can be computed using the <code class="highlight"><c- n="">pow</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code> and <code class="highlight"><c- n="">root</c-><c- o="">&lt;</c-><c- n="">R</c-><c- o="">&gt;</c-></code> non-member functions.</p>
   <p>To provide conversions between different <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①③">units</a> the following macro has to be used:</p>
<pre class="language-cpp highlight"><c- n="">BOOST_UNITS_DEFINE_CONVERSION_FACTOR</c-><c- p="">(</c-><c- n="">foot_base_unit</c-><c- p="">,</c-> <c- n="">meter_base_unit</c-><c- p="">,</c-> <c- b="">double</c-><c- p="">,</c-> <c- mf="">0.3048</c-><c- p="">);</c->
</pre>
   <p>The macro <code class="highlight"><c- n="">BOOST_UNITS_DEFAULT_CONVERSION</c-></code> specifies a conversion that will be applied
to a base unit when no direct conversion is possible. This can be used to make arbitrary
conversions work with a single specialization:</p>
<pre class="language-cpp highlight"><c- k="">struct</c-> <c- nl="">my_unit_tag</c-> <c- p="">:</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_unit</c-><c- o="">&lt;</c-><c- n="">my_unit_tag</c-><c- p="">,</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">force_type</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- p="">{};</c->

<c- c1="">// define the conversion factor</c->
<c- n="">BOOST_UNITS_DEFINE_CONVERSION_FACTOR</c-><c- p="">(</c-><c- n="">my_unit_tag</c-><c- p="">,</c-> <c- n="">SI</c-><c- o="">::</c-><c- n="">force</c-><c- p="">,</c-> <c- b="">double</c-><c- p="">,</c-> <c- mf="">3.14159265358979323846</c-><c- p="">);</c->

<c- c1="">// make conversion to SI the default.</c->
<c- n="">BOOST_UNITS_DEFAULT_CONVERSION</c-><c- p="">(</c-><c- n="">my_unit_tag</c-><c- p="">,</c-> <c- n="">SI</c-><c- o="">::</c-><c- n="">force</c-><c- p="">);</c->
</pre>
   <p>Boost.Units also allows to provide runtime-defined conversion factors with:</p>
<pre class="language-cpp highlight"><c- k="">using</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_dimension</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_unit</c-><c- p="">;</c->

<c- k="">static</c-> <c- k="">const</c-> <c- b="">long</c-> <c- n="">currency_base</c-> <c- o="">=</c-> <c- mi="">1</c-><c- p="">;</c->

<c- k="">struct</c-> <c- nl="">currency_base_dimension</c-> <c- p="">:</c-> <c- n="">base_dimension</c-><c- o="">&lt;</c-><c- n="">currency_base_dimension</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- p="">{};</c->

<c- k="">typedef</c-> <c- n="">currency_base_dimension</c-><c- o="">::</c-><c- n="">dimension_type</c-> <c- n="">currency_type</c-><c- p="">;</c->

<c- k="">template</c-><c- o="">&lt;</c-><c- b="">long</c-> <c- n="">N</c-><c- o="">&gt;</c->
<c- k="">struct</c-> <c- nl="">currency_base_unit</c-> <c- p="">:</c-> <c- n="">base_unit</c-><c- o="">&lt;</c-><c- n="">currency_base_unit</c-><c- o="">&lt;</c-><c- n="">N</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">currency_type</c-><c- p="">,</c-> <c- n="">currency_base</c-> <c- o="">+</c-> <c- n="">N</c-><c- o="">&gt;</c-> <c- p="">{};</c->

<c- k="">typedef</c-> <c- n="">currency_base_unit</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;</c-> <c- n="">us_dollar_base_unit</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">currency_base_unit</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- o="">&gt;</c-> <c- n="">euro_base_unit</c-><c- p="">;</c->

<c- k="">typedef</c-> <c- n="">us_dollar_base_unit</c-><c- o="">::</c-><c- n="">unit_type</c-> <c- n="">us_dollar</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">euro_base_unit</c-><c- o="">::</c-><c- n="">unit_type</c-> <c- n="">euro</c-><c- p="">;</c->

<c- c1="">// an array of all possible conversions</c->
<c- b="">double</c-> <c- n="">conversion_factors</c-><c- p="">[</c-><c- mi="">2</c-><c- p="">][</c-><c- mi="">2</c-><c- p="">]</c-> <c- o="">=</c-> <c- p="">{</c->
  <c- p="">{</c-><c- mf="">1.0</c-><c- p="">,</c-> <c- mf="">1.0</c-><c- p="">},</c->
  <c- p="">{</c-><c- mf="">1.0</c-><c- p="">,</c-> <c- mf="">1.0</c-><c- p="">}</c->
<c- p="">};</c->

<c- b="">double</c-> <c- nf="">get_conversion_factor</c-><c- p="">(</c-><c- b="">long</c-> <c- n="">from</c-><c- p="">,</c-> <c- b="">long</c-> <c- n="">to</c-><c- p="">)</c-> <c- p="">{</c->
  <c- k="">return</c-> <c- p="">(</c-><c- n="">conversion_factors</c-><c- p="">[</c-><c- n="">from</c-><c- p="">][</c-><c- n="">to</c-><c- p="">]);</c->
<c- p="">}</c->

<c- b="">void</c-> <c- nf="">set_conversion_factor</c-><c- p="">(</c-><c- b="">long</c-> <c- n="">from</c-><c- p="">,</c-> <c- b="">long</c-> <c- n="">to</c-><c- p="">,</c-> <c- b="">double</c-> <c- n="">value</c-><c- p="">)</c-> <c- p="">{</c->
  <c- n="">conversion_factors</c-><c- p="">[</c-><c- n="">from</c-><c- p="">][</c-><c- n="">to</c-><c- p="">]</c-> <c- o="">=</c-> <c- n="">value</c-><c- p="">;</c->
  <c- n="">conversion_factors</c-><c- p="">[</c-><c- n="">to</c-><c- p="">][</c-><c- n="">from</c-><c- p="">]</c-> <c- o="">=</c-> <c- mf="">1.0</c-> <c- o="">/</c-> <c- n="">value</c-><c- p="">;</c->
<c- p="">}</c->

<c- n="">BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE</c-><c- p="">((</c-><c- b="">long</c-> <c- n="">N1</c-><c- p="">)(</c-><c- b="">long</c-> <c- n="">N2</c-><c- p="">),</c->
                                              <c- n="">currency_base_unit</c-><c- o="">&lt;</c-><c- n="">N1</c-><c- o="">&gt;</c-><c- p="">,</c->
                                              <c- n="">currency_base_unit</c-><c- o="">&lt;</c-><c- n="">N2</c-><c- o="">&gt;</c-><c- p="">,</c->
                                              <c- b="">double</c-><c- p="">,</c-> <c- n="">get_conversion_factor</c-><c- p="">(</c-><c- n="">N1</c-><c- p="">,</c-> <c- n="">N2</c-><c- p="">));</c->
</pre>
   <p>This library is designed to emphasize safety above convenience when performing operations
with dimensioned <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③③">quantities</a>. Specifically:</p>
   <ul>
    <li data-md="">
     <p>construction of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③④">quantities</a> is required to fully specify both value and <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①④">unit</a></p>
    </li><li data-md="">
     <p>direct construction from a scalar value is prohibited (though the static member function <code class="highlight"><c- n="">from_value</c-></code> is provided to enable this functionality where it is necessary)</p>
    </li><li data-md="">
     <p><code class="highlight"><c- n="">quantity_cast</c-></code> to a reference allows direct access to the underlying value of a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③⑤">quantity</a> variable</p>
    </li><li data-md="">
     <p>an explicit constructor is provided to enable conversion between dimensionally compatible <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③⑥">quantities</a> in different <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①①">unit systems</a></p>
    </li><li data-md="">
     <p>implicit conversions between <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units" id="ref-for-system-of-units⑦">systems of units</a> are allowed only when
the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#reduced-dimension" id="ref-for-reduced-dimension①">reduced dimensions</a> are identical, allowing, for example, trivial conversions
between equivalent units in different systems (such as SI seconds and CGS seconds) while
simultaneously enabling unintentional <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①②">unit system</a> mismatches to be caught
at compile time and preventing potential loss of precision and performance overhead
from unintended conversions</p>
    </li><li data-md="">
     <p>assignment follows the same rules</p>
    </li><li data-md="">
     <p>an exception is made for <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③⑦">quantities</a> for which the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①⑤">unit</a> reduces to a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-of-dimension-one" id="ref-for-quantity-of-dimension-one①">dimensionless
quantity</a>;
in this case, implicit conversion to the underlying value type is allowed via class template
specialization</p>
    </li><li data-md="">
     <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③⑧">quantities</a> of different value types are implicitly convertible only if the value types
are themselves implicitly convertible</p>
    </li><li data-md="">
     <p>the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity③⑨">quantity</a> class also defines a <code class="highlight"><c- n="">value</c-><c- p="">()</c-></code> member for directly accessing the underlying
value</p>
   </li></ul>
   <p>There are two distinct types of systems that can be envisioned:</p>
   <ol>
    <li data-md="">
     <p>Homogeneous systems</p>
     <p>Systems which hold a linearly independent set of base units which can be used to represent
many different dimensions. For example, the SI system has seven base dimensions and seven
base units corresponding to them. It can represent any unit which uses only those seven
base dimensions. Thus it is a homogeneous_system.</p>
    </li><li data-md="">
     <p>Heterogeneous systems</p>
     <p>Systems which store the exponents of every base unit involved are termed heterogeneous.
Some units can only be represented in this way. For example, area in <code class="highlight"><c- n="">m</c-> <c- n="">ft</c-></code> is intrinsically
heterogeneous, because the base units of meters and feet have identical dimensions. As
a result, simply storing a dimension and a set of base units does not yield a unique
solution. A practical example of the need for heterogeneous units, is an empirical
equation used in aviation: <code class="highlight"><c- n="">H</c-> <c- o="">=</c-> <c- p="">(</c-><c- n="">r</c-><c- o="">/</c-><c- n="">C</c-><c- p="">)</c-><c- o="">^</c-><c- mi="">2</c-></code> where <code class="highlight"><c- n="">H</c-></code> is the radar beam height in feet and <code class="highlight"><c- n="">r</c-></code> is the radar range in nautical miles. In order to enforce dimensional correctness of
this equation, the constant, <code class="highlight"><c- n="">C</c-></code>, must be expressed in nautical <code class="highlight"><c- n="">miles</c-> <c- n="">per</c-> <c- n="">foot</c-><c- o="">^</c-><c- p="">(</c-><c- mi="">1</c-><c- o="">/</c-><c- mi="">2</c-><c- p="">)</c-></code>,
mixing two distinct base units of length.</p>
   </li></ol>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">cgs</c-> <c- p="">{</c->
  <c- k="">typedef</c-> <c- n="">scaled_base_unit</c-><c- o="">&lt;</c-><c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meter_base_unit</c-><c- p="">,</c->
                           <c- n="">scale</c-><c- o="">&lt;</c-><c- mi="">10</c-><c- p="">,</c-> <c- n="">static_rational</c-><c- o="">&lt;-</c-><c- mi="">2</c-><c- o="">&gt;&gt;&gt;</c-> <c- n="">centimeter_base_unit</c-><c- p="">;</c->
  <c- k="">typedef</c-> <c- n="">make_system</c-><c- o="">&lt;</c-><c- n="">centimeter_base_unit</c-><c- p="">,</c->
                      <c- n="">gram_base_unit</c-><c- p="">,</c->
                      <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">second_base_unit</c-><c- p="">,</c->
                      <c- n="">biot_base_unit</c-><c- o="">&gt;::</c-><c- n="">type</c-> <c- n="">system</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
<pre class="language-cpp highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">si</c-><c- o="">::</c-><c- n="">area</c-><c- o="">&gt;</c->      <c- n="">A</c-><c- p="">(</c-><c- mf="">1.5</c-><c- o="">*</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meter</c-><c- o="">*</c-><c- n="">cgs</c-><c- o="">::</c-><c- n="">centimeter</c-><c- p="">);</c->

<c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- mf="">1.5</c-><c- o="">*</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meter</c-><c- o="">*</c-><c- n="">cgs</c-><c- o="">::</c-><c- n="">centimeter</c-> <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">endl</c->  <c- c1="">// prints 1.5 cm m</c->
          <c- o="">&lt;&lt;</c-> <c- n="">A</c-> <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">endl</c->                              <c- c1="">// prints 0.015 m^2</c->
          <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">endl</c-><c- p="">;</c->
</pre>
   <p>To provide temperature support Boost.Units define 2 new systems:</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">celsius</c-> <c- p="">{</c->
  <c- k="">typedef</c-> <c- n="">make_system</c-><c- o="">&lt;</c-><c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">::</c-><c- n="">celsius_base_unit</c-><c- o="">&gt;::</c-><c- n="">type</c-> <c- n="">system</c-><c- p="">;</c->
  <c- k="">typedef</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">temperature_dimension</c-><c- p="">,</c-> <c- n="">system</c-><c- o="">&gt;</c-> <c- n="">temperature</c-><c- p="">;</c->

  <c- k="">static</c-> <c- k="">const</c-> <c- n="">temperature</c-> <c- n="">degree</c-><c- p="">;</c->
  <c- k="">static</c-> <c- k="">const</c-> <c- n="">temperature</c-> <c- n="">degrees</c-><c- p="">;</c->
<c- p="">}</c->

<c- k="">namespace</c-> <c- n="">fahrenheit</c-> <c- p="">{</c->
  <c- k="">typedef</c-> <c- n="">make_system</c-><c- o="">&lt;</c-><c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">::</c-><c- n="">fahrenheit_base_unit</c-><c- o="">&gt;::</c-><c- n="">type</c-> <c- n="">system</c-><c- p="">;</c->
  <c- k="">typedef</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">temperature_dimension</c-><c- p="">,</c-> <c- n="">system</c-><c- o="">&gt;</c-> <c- n="">temperature</c-><c- p="">;</c->

  <c- k="">static</c-> <c- k="">const</c-> <c- n="">temperature</c-> <c- n="">degree</c-><c- p="">;</c->
  <c- k="">static</c-> <c- k="">const</c-> <c- n="">temperature</c-> <c- n="">degrees</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>and a wrapper for handling absolute units (points rather than vectors) to provide affine space support:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Y</c-><c- o="">&gt;</c->
<c- k="">class</c-> <c- nc="">absolute</c-> <c- p="">{</c->
<c- k="">public</c-><c- o="">:</c->
  <c- c1="">// types</c->
  <c- k="">typedef</c-> <c- n="">absolute</c-><c- o="">&lt;</c-><c- n="">Y</c-><c- o="">&gt;</c-> <c- n="">this_type</c-><c- p="">;</c->
  <c- k="">typedef</c-> <c- n="">Y</c->           <c- n="">value_type</c-><c- p="">;</c->

  <c- c1="">// construct/copy/destruct</c->
  <c- n="">absolute</c-><c- p="">();</c->
  <c- n="">absolute</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">value_type</c-> <c- o="">&amp;</c-><c- p="">);</c->
  <c- n="">absolute</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">this_type</c-> <c- o="">&amp;</c-><c- p="">);</c->
  <c- n="">BOOST_CXX14_CONSTEXPR</c-> <c- n="">this_type</c-> <c- o="">&amp;</c-> <c- k="">operator</c-><c- o="">=</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">this_type</c-> <c- o="">&amp;</c-><c- p="">);</c->

  <c- c1="">// public member functions</c->
  <c- n="">BOOST_CONSTEXPR</c-> <c- k="">const</c-> <c- n="">value_type</c-> <c- o="">&amp;</c-> <c- n="">value</c-><c- p="">()</c-> <c- k="">const</c-><c- p="">;</c->
  <c- n="">BOOST_CXX14_CONSTEXPR</c-> <c- k="">const</c-> <c- n="">this_type</c-> <c- o="">&amp;</c-> <c- k="">operator</c-><c- o="">+=</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">value_type</c-> <c- o="">&amp;</c-><c- p="">);</c->
  <c- n="">BOOST_CXX14_CONSTEXPR</c-> <c- k="">const</c-> <c- n="">this_type</c-> <c- o="">&amp;</c-> <c- k="">operator</c-><c- o="">-=</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">value_type</c-> <c- o="">&amp;</c-><c- p="">);</c->
<c- p="">};</c->
</pre>
   <p>With above we can:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">From</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">To</c-><c- o="">&gt;</c->
<c- k="">struct</c-> <c- n="">conversion_helper</c-> <c- p="">{</c->
  <c- k="">static</c-> <c- n="">BOOST_CONSTEXPR</c-> <c- n="">To</c-> <c- n="">convert</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">From</c-><c- o="">&amp;</c-><c- p="">);</c->
<c- p="">};</c->

<c- k="">typedef</c-> <c- n="">conversion_helper</c-><c- o="">&lt;</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">absolute</c-><c- o="">&lt;</c-><c- n="">fahrenheit</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">&gt;&gt;</c-><c- p="">,</c->
                          <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">absolute</c-><c- o="">&lt;</c-><c- n="">si</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">&gt;&gt;&gt;</c-> <c- n="">absolute_conv_type</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">conversion_helper</c-><c- o="">&lt;</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">fahrenheit</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">&gt;</c-><c- p="">,</c->
                          <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">si</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">&gt;&gt;</c->           <c- n="">relative_conv_type</c-><c- p="">;</c->

<c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">absolute</c-><c- o="">&lt;</c-><c- n="">fahrenheit</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">&gt;&gt;</c-> <c- n="">T1p</c-><c- p="">(</c-><c- mf="">32.0</c-> <c- o="">*</c-> <c- n="">absolute</c-><c- o="">&lt;</c-><c- n="">fahrenheit</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">&gt;</c-><c- p="">());</c->
<c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">fahrenheit</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">&gt;</c->           <c- n="">T1v</c-><c- p="">(</c-><c- mf="">32.0</c-> <c- o="">*</c-> <c- n="">fahrenheit</c-><c- o="">::</c-><c- n="">degrees</c-><c- p="">);</c->

<c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">absolute</c-><c- o="">&lt;</c-><c- n="">si</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">&gt;&gt;</c->         <c- n="">T2p</c-><c- p="">(</c-><c- n="">T1p</c-><c- p="">);</c->
<c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">si</c-><c- o="">::</c-><c- n="">temperature</c-><c- o="">&gt;</c->                   <c- n="">T2v</c-><c- p="">(</c-><c- n="">T1v</c-><c- p="">);</c->

<c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">T1p</c-> <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">endl</c->                               <c- c1="">// prints 32 absolute  F</c->
          <c- o="">&lt;&lt;</c-> <c- n="">absolute_conv_type</c-><c- o="">::</c-><c- n="">convert</c-><c- p="">(</c-><c- n="">T1p</c-><c- p="">)</c-> <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">endl</c->  <c- c1="">// prints 273.15 absolute  K</c->
          <c- o="">&lt;&lt;</c-> <c- n="">T2p</c-> <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">endl</c->                               <c- c1="">// prints 273.15 absolute  K</c->
          <c- o="">&lt;&lt;</c-> <c- n="">T1v</c-> <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">endl</c->                               <c- c1="">// prints 32 F</c->
          <c- o="">&lt;&lt;</c-> <c- n="">relative_conv_type</c-><c- o="">::</c-><c- n="">convert</c-><c- p="">(</c-><c- n="">T1v</c-><c- p="">)</c-> <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">endl</c->  <c- c1="">// prints 17.7778 K</c->
          <c- o="">&lt;&lt;</c-> <c- n="">T2v</c-> <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">endl</c->                               <c- c1="">// prints 17.7778 K</c->
          <c- o="">&lt;&lt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">endl</c-><c- p="">;</c->
</pre>
   <h3 class="heading settled" data-level="5.2" id="cppnow17-units"><span class="secno">5.2. </span><span class="content">cppnow17-units</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#cppnow17-units"></a></h3>
   <p>Steven Watanabe, the coauthor of the previous library, started the work on the modernized
version of the library based on the results of LiaW on C++Now 2017 <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-cppnow17-units">[CPPNOW17-UNITS]</a>. As
the library was never finished we will not discuss it in details.</p>
   <h4 class="heading settled" data-level="5.2.1" id="cppnow17-units.design"><span class="secno">5.2.1. </span><span class="content">Design</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#cppnow17-units.design"></a></h4>
   <p>The main design is similar to <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-boostunits">[BOOST.UNITS]</a> with one important difference - no systems.
Steven Watanabe provided the following rationale for this design change:</p>
   <p><em>"My take is that a system is essentially a set of units with linearly independent
dimensions and this can be implemented as a convenience on top of the core functionality.
Boost.Units started out with a design based solely on systems, but that proved to be too
inflexible. We added support for combining individual units, similar to current libraries.
However, having both systems and base units supported directly in the core library results
in a very convoluted design and is one of the main issues that I wanted to fix in a new
library."</em></p>
   <p>Another interesting design change is the approach for temperatures. With the new design
Celsius and Fahrenheit are always treated as absolute temperatures and only Kelvins can
act as an absolute or relative value.</p>
<pre class="language-cpp highlight"><c- n="">kelvin</c-> <c- o="">+</c-> <c- n="">kelvin</c-> <c- o="">=</c-> <c- n="">kelvin</c->
<c- n="">celsius</c-> <c- o="">-</c-> <c- n="">celsius</c-> <c- o="">=</c-> <c- n="">kelvin</c->
<c- n="">celsius</c-> <c- o="">+</c-> <c- n="">kelvin</c-> <c- o="">=</c-> <c- n="">celsius</c->
</pre>
   <h3 class="heading settled" data-level="5.3" id="PhysUnits-CT-Cpp11"><span class="secno">5.3. </span><span class="content">PhysUnits-CT-Cpp11</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#PhysUnits-CT-Cpp11"></a></h3>
   <p><a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-physunits-ct-cpp11">[PHYSUNITS-CT-CPP11]</a> is the library based on the work of Michael Kenniston from 2001 and
expanded and adapted for C++11 by Martin Moene.</p>
   <h4 class="heading settled" data-level="5.3.1" id="PhysUnits-CT-Cpp11.usage.example"><span class="secno">5.3.1. </span><span class="content">Usage example</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#PhysUnits-CT-Cpp11.usage.example"></a></h4>
<pre class="language-cpp highlight"><c- cp="">#include</c-> &lt;phys/units/io.hpp&gt;
<c- cp="">#include</c-> &lt;phys/units/quantity.hpp&gt;
<c- cp="">#include</c-> &lt;phys/units/other_units.hpp&gt;
<c- cp="">#include</c-> &lt;iostream&gt;
<c- cp="">#include</c-> &lt;cassert&gt;

<c- k="">namespace</c-> <c- n="">pu</c-> <c- o="">=</c-> <c- n="">phys</c-><c- o="">::</c-><c- n="">units</c-><c- p="">;</c->
<c- k="">using</c-> <c- k="">namespace</c-> <c- n="">pu</c-><c- o="">::</c-><c- n="">literals</c-><c- p="">;</c->
<c- k="">using</c-> <c- k="">namespace</c-> <c- n="">phys</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">io</c-><c- p="">;</c->

<c- k="">constexpr</c-> <c- n="">pu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">pu</c-><c- o="">::</c-><c- n="">speed_d</c-><c- o="">&gt;</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">pu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">pu</c-><c- o="">::</c-><c- n="">length_d</c-><c- o="">&gt;</c-> <c- n="">d</c-><c- p="">,</c->
                                              <c- n="">pu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">pu</c-><c- o="">::</c-><c- n="">time_interval_d</c-><c- o="">&gt;</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->

<c- b="">void</c-> <c- n="">test1</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mi="">220</c-><c- n="">_km</c-><c- p="">,</c-> <c- mi="">2</c-> <c- o="">*</c-> <c- n="">pu</c-><c- o="">::</c-><c- n="">hour</c-><c- p="">);</c->
<c- c1="">//  assert(v.magnitude() == 110);  // fails</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- mi="">110</c-><c- n="">_km</c-> <c- o="">/</c-> <c- n="">pu</c-><c- o="">::</c-><c- n="">hour</c-><c- p="">);</c->  <c- c1="">// passes</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">v</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->          <c- c1="">// prints "30.5556 m/s"</c->
<c- p="">}</c->

<c- b="">void</c-> <c- n="">test2</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mi="">140</c-> <c- o="">*</c-> <c- n="">pu</c-><c- o="">::</c-><c- n="">mile</c-><c- p="">,</c-> <c- mi="">2</c-> <c- o="">*</c-> <c- n="">pu</c-><c- o="">::</c-><c- n="">hour</c-><c- p="">);</c->
<c- c1="">//  assert(v.magnitude() == 70);          // fails</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- mi="">70</c-> <c- o="">*</c-> <c- n="">pu</c-><c- o="">::</c-><c- n="">mile</c-> <c- o="">/</c-> <c- n="">pu</c-><c- o="">::</c-><c- n="">hour</c-><c- p="">);</c->  <c- c1="">// passes</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">v</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->                 <c- c1="">// prints "31.2928 m/s"</c->
<c- p="">}</c->
</pre>
   <p>Please note that this library is a pretty simple library and thus has a lot limitations:</p>
   <ol>
    <li data-md="">
     <p>We are unable to pass arguments to <code class="highlight"><c- n="">avg_speed</c-></code> in units provided by the user because
quantities are always converted to base units (so there is no need to try to make it
a function template).</p>
    </li><li data-md="">
     <p>Because of above we also do not get the result in the unit we would like. This it why
the first assert fails.</p>
    </li><li data-md="">
     <p>There is no possibility to cast returned quantity to the unit that we would like to use
for printing.</p>
    </li><li data-md="">
     <p>Because of always forced intermediate conversions to base units the second assert passes
even though the result’s precision is degraded (both sides of equality are the same broken).</p>
   </li></ol>
   <h4 class="heading settled" data-level="5.3.2" id="PhysUnits-CT-Cpp11.design"><span class="secno">5.3.2. </span><span class="content">Design</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#PhysUnits-CT-Cpp11.design"></a></h4>
   <p>The library defines dimensions such as <code class="highlight"><c- n="">length_d</c-></code> and <code class="highlight"><c- n="">mass_d</c-></code> as a list of 7 template
parameters representing exponents of each <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units②">SI</a> dimension:</p>
<pre class="language-cpp highlight"><c- cp="">#ifdef PHYS_UNITS_REP_TYPE</c->
   <c- k="">using</c-> <c- n="">Rep</c-> <c- o="">=</c-> <c- n="">PHYS_UNITS_REP_TYPE</c-><c- p="">;</c->
<c- cp="">#else</c->
   <c- k="">using</c-> <c- n="">Rep</c-> <c- o="">=</c-> <c- b="">double</c-><c- p="">;</c->
<c- cp="">#endif</c->

<c- k="">template</c-><c- o="">&lt;</c-><c- b="">int</c-> <c- n="">D1</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">D2</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">D3</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">D4</c-> <c- o="">=</c-> <c- mi="">0</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">D5</c-> <c- o="">=</c-> <c- mi="">0</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">D6</c-> <c- o="">=</c-> <c- mi="">0</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">D7</c-> <c- o="">=</c-> <c- mi="">0</c-><c- o="">&gt;</c->
<c- k="">struct</c-> <c- n="">dimensions</c-> <c- p="">{</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- b="">int</c-> <c- n="">R1</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R2</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R3</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R4</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R5</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R6</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R7</c-><c- o="">&gt;</c->
  <c- k="">constexpr</c-> <c- b="">bool</c-> <c- k="">operator</c-><c- o="">==</c-><c- p="">(</c-><c- n="">dimensions</c-><c- o="">&lt;</c-><c- n="">R1</c-><c- p="">,</c-> <c- n="">R2</c-><c- p="">,</c-> <c- n="">R3</c-><c- p="">,</c-> <c- n="">R4</c-><c- p="">,</c-> <c- n="">R5</c-><c- p="">,</c-> <c- n="">R6</c-><c- p="">,</c-> <c- n="">R7</c-><c- o="">&gt;</c-> <c- k="">const</c-><c- o="">&amp;</c-><c- p="">)</c-> <c- k="">const</c-><c- p="">;</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- b="">int</c-> <c- n="">R1</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R2</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R3</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R4</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R5</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R6</c-><c- p="">,</c-> <c- b="">int</c-> <c- n="">R7</c-><c- o="">&gt;</c->
  <c- k="">constexpr</c-> <c- b="">bool</c-> <c- k="">operator</c-><c- o="">!=</c-><c- p="">(</c-><c- n="">dimensions</c-><c- o="">&lt;</c-><c- n="">R1</c-><c- p="">,</c-> <c- n="">R2</c-><c- p="">,</c-> <c- n="">R3</c-><c- p="">,</c-> <c- n="">R4</c-><c- p="">,</c-> <c- n="">R5</c-><c- p="">,</c-> <c- n="">R6</c-><c- p="">,</c-> <c- n="">R7</c-><c- o="">&gt;</c-> <c- k="">const</c-><c- o="">&amp;</c-> <c- n="">rhs</c-><c- p="">)</c-> <c- k="">const</c-><c- p="">;</c->
<c- p="">};</c->

<c- k="">typedef</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- o="">&gt;</c-> <c- n="">dimensionless_d</c-><c- p="">;</c->

<c- k="">typedef</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- o="">&gt;</c-> <c- n="">length_d</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">1</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- o="">&gt;</c-> <c- n="">mass_d</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">1</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- o="">&gt;</c-> <c- n="">time_interval_d</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">1</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- o="">&gt;</c-> <c- n="">electric_current_d</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">1</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- o="">&gt;</c-> <c- n="">thermodynamic_temperature_d</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">1</c-><c- p="">,</c-> <c- mi="">0</c-><c- o="">&gt;</c-> <c- n="">amount_of_substance_d</c-><c- p="">;</c->
<c- k="">typedef</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- n="">luminous_intensity_d</c-><c- p="">;</c->
</pre>
   <p>Quantities represent their units (<code class="highlight"><c- n="">meter</c-></code>, <code class="highlight"><c- n="">kilogram</c-></code>, ...):</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Dims</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">T</c-> <c- o="">=</c-> <c- n="">Rep</c-><c- o="">&gt;</c->
<c- k="">class</c-> <c- nc="">quantity</c-> <c- p="">{</c-> <c- d="">/* ... */</c-> <c- p="">};</c->

<c- c1="">// The seven SI base units.  These tie our numbers to the real world.</c->

<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">length_d</c-><c- o="">&gt;</c-> <c- n="">meter</c-><c- p="">{</c-><c- n="">detail</c-><c- o="">::</c-><c- n="">magnitude_tag</c-><c- p="">,</c-> <c- mf="">1.0</c-><c- p="">};</c->
<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">mass_d</c-><c- o="">&gt;</c-> <c- n="">kilogram</c-><c- p="">{</c-><c- n="">detail</c-><c- o="">::</c-><c- n="">magnitude_tag</c-><c- p="">,</c-> <c- mf="">1.0</c-><c- p="">};</c->
<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">time_interval_d</c-><c- o="">&gt;</c-> <c- n="">second</c-><c- p="">{</c-><c- n="">detail</c-><c- o="">::</c-><c- n="">magnitude_tag</c-><c- p="">,</c-> <c- mf="">1.0</c-><c- p="">};</c->
<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">electric_current_d</c-><c- o="">&gt;</c-> <c- n="">ampere</c-><c- p="">{</c-><c- n="">detail</c-><c- o="">::</c-><c- n="">magnitude_tag</c-><c- p="">,</c-> <c- mf="">1.0</c-><c- p="">};</c->
<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">thermodynamic_temperature_d</c-><c- o="">&gt;</c-> <c- n="">kelvin</c-><c- p="">{</c-><c- n="">detail</c-><c- o="">::</c-><c- n="">magnitude_tag</c-><c- p="">,</c-> <c- mf="">1.0</c-><c- p="">};</c->
<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">amount_of_substance_d</c-><c- o="">&gt;</c-> <c- n="">mole</c-><c- p="">{</c-><c- n="">detail</c-><c- o="">::</c-><c- n="">magnitude_tag</c-><c- p="">,</c-> <c- mf="">1.0</c-><c- p="">};</c->
<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">luminous_intensity_d</c-><c- o="">&gt;</c-> <c- n="">candela</c-><c- p="">{</c-><c- n="">detail</c-><c- o="">::</c-><c- n="">magnitude_tag</c-><c- p="">,</c-> <c- mf="">1.0</c-><c- p="">};</c->
</pre>
   <p>Derived dimensions and units are defined in the same way:</p>
<pre class="language-cpp highlight"><c- c1="">// The rest of the standard dimensional types, as specified in SP811.</c->

<c- k="">using</c-> <c- n="">absorbed_dose_d</c->         <c- o="">=</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">2</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">2</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">absorbed_dose_rate_d</c->    <c- o="">=</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">2</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">3</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">acceleration_d</c->          <c- o="">=</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">2</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">activity_of_a_nuclide_d</c-> <c- o="">=</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">1</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">angular_velocity_d</c->      <c- o="">=</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">1</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">angular_acceleration_d</c->  <c- o="">=</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">2</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">area_d</c->                  <c- o="">=</c-> <c- n="">dimensions</c-><c- o="">&lt;</c-><c- mi="">2</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">capacitance_d</c->           <c- o="">=</c-> <c- n="">dimensions</c-><c- o="">&lt;-</c-><c- mi="">2</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">1</c-><c- p="">,</c-> <c- mi="">4</c-><c- p="">,</c-> <c- mi="">2</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">concentration_d</c->         <c- o="">=</c-> <c- n="">dimensions</c-><c- o="">&lt;-</c-><c- mi="">3</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">0</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- c1="">// ...</c->

<c- c1="">// The derived SI units, as specified in SP811.</c->

<c- k="">constexpr</c-> <c- n="">Rep</c-> <c- n="">radian</c-><c- p="">{</c-><c- n="">Rep</c-><c- p="">(</c-><c- mi="">1</c-><c- p="">)};</c->
<c- k="">constexpr</c-> <c- n="">Rep</c-> <c- n="">steradian</c-><c- p="">{</c-><c- n="">Rep</c-><c- p="">(</c-><c- mi="">1</c-><c- p="">)};</c->
<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">force_d</c-><c- o="">&gt;</c-> <c- n="">newton</c-><c- p="">{</c-><c- n="">meter</c-> <c- o="">*</c-> <c- n="">kilogram</c-> <c- o="">/</c-> <c- n="">square</c-><c- p="">(</c-><c- n="">second</c-><c- p="">)};</c->
<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">pressure_d</c-><c- o="">&gt;</c-> <c- n="">pascal</c-><c- p="">{</c-><c- n="">newton</c-> <c- o="">/</c-> <c- n="">square</c-><c- p="">(</c-><c- n="">meter</c-><c- p="">)};</c->
<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">energy_d</c-><c- o="">&gt;</c-> <c- n="">joule</c-><c- p="">{</c-><c- n="">newton</c-> <c- o="">*</c-> <c- n="">meter</c-><c- p="">};</c->
<c- k="">constexpr</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">power_d</c-><c- o="">&gt;</c-> <c- n="">watt</c-><c- p="">{</c-><c- n="">joule</c-> <c- o="">/</c-> <c- n="">second</c-><c- p="">};</c->
<c- c1="">// ...</c->
</pre>
   <p>The library also provides UDLs for SI units and their prefixes ranging from <code class="highlight"><c- n="">yocto</c-></code> to <code class="highlight"><c- n="">yotta</c-></code>. Thus it is possible to write quantity literals such as <code class="highlight"><c- mi="">1</c-><c- n="">_ns</c-></code> and <code class="highlight"><c- mf="">42.195</c-><c- n="">_km</c-></code>.</p>
   <h3 class="heading settled" data-level="5.4" id="nic-units"><span class="secno">5.4. </span><span class="content">Nic Holthaus units</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nic-units"></a></h3>
   <p>The next is C++14 library created by Nic Holthaus <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-nic_units">[NIC_UNITS]</a>.</p>
   <h4 class="heading settled" data-level="5.4.1" id="nic-units.usage.example"><span class="secno">5.4.1. </span><span class="content">Usage example</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nic-units.usage.example"></a></h4>
<pre class="language-cpp highlight"><c- cp="">#include</c-> &lt;include/units.h&gt;
<c- cp="">#include</c-> &lt;type_traits&gt;
<c- cp="">#include</c-> &lt;iostream&gt;
<c- cp="">#include</c-> &lt;cassert&gt;

<c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Length</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Time</c-><c- p="">,</c->
         <c- k="">typename</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">enable_if_t</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">traits</c-><c- o="">::</c-><c- n="">is_length_unit</c-><c- o="">&lt;</c-><c- n="">Length</c-><c- o="">&gt;::</c-><c- n="">value</c-> <c- o="">&amp;&amp;</c->
                                     <c- n="">units</c-><c- o="">::</c-><c- n="">traits</c-><c- o="">::</c-><c- n="">is_time_unit</c-><c- o="">&lt;</c-><c- n="">Time</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- o="">&gt;&gt;</c->
<c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">Length</c-> <c- n="">d</c-><c- p="">,</c-> <c- n="">Time</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">static_assert</c-><c- p="">(</c-><c- n="">units</c-><c- o="">::</c-><c- n="">traits</c-><c- o="">::</c-><c- n="">is_velocity_unit</c-><c- o="">&lt;</c-><c- k="">decltype</c-><c- p="">(</c-><c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">)</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- p="">);</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->

<c- k="">using</c-> <c- k="">namespace</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">literals</c-><c- p="">;</c->

<c- b="">void</c-> <c- nf="">test1</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mi="">220</c-><c- n="">_km</c-><c- p="">,</c-> <c- mi="">2</c-><c- n="">_hr</c-><c- p="">);</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-><c- p="">.</c-><c- n="">value</c-><c- p="">()</c-> <c- o="">==</c-> <c- mi="">110</c-><c- p="">);</c->    <c- c1="">// passes</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- mi="">110</c-><c- n="">_kph</c-><c- p="">);</c->        <c- c1="">// passes</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">v</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->      <c- c1="">// prints "30.5556 m s^-1"</c->
<c- p="">}</c->

<c- b="">void</c-> <c- nf="">test2</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">units</c-><c- o="">::</c-><c- n="">length</c-><c- o="">::</c-><c- n="">mile_t</c-><c- p="">(</c-><c- mi="">140</c-><c- p="">),</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">time</c-><c- o="">::</c-><c- n="">hour_t</c-><c- p="">(</c-><c- mi="">2</c-><c- p="">));</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-><c- p="">.</c-><c- n="">value</c-><c- p="">()</c-> <c- o="">==</c-> <c- mi="">70</c-><c- p="">);</c->                             <c- c1="">// passes</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">velocity</c-><c- o="">::</c-><c- n="">miles_per_hour_t</c-><c- p="">(</c-><c- mi="">70</c-><c- p="">));</c->  <c- c1="">// passes</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">v</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->                              <c- c1="">// prints "31.2928 m s^-1"</c->
<c- p="">}</c->
</pre>
   <p><a href="https://godbolt.org/z/2tEnRp">Compiler Explorer</a></p>
   <p>An interesting usability point to note here is the fact that we cannot provide partial
definition of quantity types in a function template. It is caused by the usage of unit
nesting which makes it impossible to determine on which level of nesting we will find
a dimension tag (i.e. <code class="highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">category</c-><c- o="">::</c-><c- n="">length_unit</c-></code>):</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">length</c-> <c- p="">{</c->
  <c- k="">using</c-> <c- n="">meters</c-> <c- o="">=</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">category</c-><c- o="">::</c-><c- n="">length_unit</c-><c- o="">&gt;</c-><c- p="">;</c->
  <c- k="">using</c-> <c- n="">feet</c-> <c- o="">=</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">381</c-><c- p="">,</c-> <c- mi="">1250</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">meters</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>This is why we can either provide a specific type that will force intermediate
conversions or just use <code class="highlight"><c- n="">T</c-></code> template parameter for function arguments.</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Length</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Time</c-><c- o="">&gt;</c->
<c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">Length</c-> <c- n="">d</c-><c- p="">,</c-> <c- n="">Time</c-> <c- n="">t</c-><c- p="">)</c->
</pre>
   <p>We can try to SFINAE other types using provided type traits (see the usage example above)
but it is not the most user-friendly solution and most of them will probably not use it
for their daily code.</p>
   <p>Also please note that even though the returned type is what we would expect (a velocity
in a correct unit) and there are no intermediate conversions, it is being printed in terms
of base units which is not what is expected by the user.</p>
   <h4 class="heading settled" data-level="5.4.2" id="nic-units.design"><span class="secno">5.4.2. </span><span class="content">Design</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nic-units.design"></a></h4>
   <p>The library consists of a single file (<code class="highlight"><c- n="">units</c-><c- p="">.</c-><c- n="">h</c-></code>) with the ability to remove some parts
of unneeded functionality with preprocessor macros (i.e. to speed up compilation time).
It provides a set of types, containers, and traits to solve dimensional analysis problems.
Each <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①①">dimension</a> is defined in its own namespace.</p>
   <p>Unit tags are the foundation of the unit library. Unit tags are types which are never
instantiated in user code, but which provide the meta-information about different units,
including how to convert between them, and how to determine their compatibility for
conversion.</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">units</c-> <c- p="">{</c->

<c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Meter</c-> <c- o="">=</c-> <c- n="">detail</c-><c- o="">::</c-><c- n="">meter_ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;</c-><c- p="">,</c->
         <c- k="">class</c-> <c- nc="">Kilogram</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;</c-><c- p="">,</c->
         <c- k="">class</c-> <c- nc="">Second</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;</c-><c- p="">,</c->
         <c- k="">class</c-> <c- nc="">Radian</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;</c-><c- p="">,</c->
         <c- k="">class</c-> <c- nc="">Ampere</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;</c-><c- p="">,</c->
         <c- k="">class</c-> <c- nc="">Kelvin</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;</c-><c- p="">,</c->
         <c- k="">class</c-> <c- nc="">Mole</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;</c-><c- p="">,</c->
         <c- k="">class</c-> <c- nc="">Candela</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;</c-><c- p="">,</c->
         <c- k="">class</c-> <c- nc="">Byte</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;&gt;</c->
<c- k="">struct</c-> <c- n="">base_unit</c-><c- p="">;</c->

<c- p="">}</c->
</pre>
   <p>Interesting to notice here is that beside typical SI dimensions, there are also <code class="highlight"><c- n="">Radian</c-></code> and <code class="highlight"><c- n="">Byte</c-></code>.</p>
   <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①⑥">Units</a> in the library are defined in terms of:</p>
   <ul>
    <li data-md="">
     <p>a scale factor relative to a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①①">base unit</a> type</p>
    </li><li data-md="">
     <p>a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①②">base unit</a></p>
    </li><li data-md="">
     <p>[optionally] a scale factor of <code class="highlight"><c- n="">pi</c-></code> required by the conversion (i.e. <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;-</c-><c- mi="">1</c-><c- o="">&gt;</c-></code> for a radians to degrees conversion)</p>
    </li><li data-md="">
     <p>[optionally] a datum translation (i.e. <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">32</c-><c- o="">&gt;</c-></code> for a Fahrenheit to Celsius conversion)</p>
   </li></ul>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">units</c-> <c- p="">{</c->

<c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Conversion</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">BaseUnit</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">PiExponent</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;</c-><c- p="">,</c->
         <c- k="">class</c-> <c- nc="">Translation</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- o="">&gt;&gt;</c->
<c- k="">struct</c-> <c- n="">unit</c-><c- p="">;</c->

<c- p="">}</c->
</pre>
   <p>All <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①⑦">units</a> have their origin in the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units③">SI</a>. A special exception is made for angle units,
which are defined in <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units④">SI</a> as (<code class="highlight"><c- n="">m</c-> <c- o="">*</c-> <c- n="">m</c-><c- o="">^-</c-><c- mi="">1</c-></code>), and in this library they are treated as a
base unit type because of their important engineering applications.</p>
   <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④⓪">Quantities</a> are represented in this library as unit containers that are the primary
classes which will be instantiated in user code. Containers are derived from the <code class="highlight"><c- n="">unit_t</c-></code> class, and have the form [unitname]_t, e.g. <code class="highlight"><c- n="">meter_t</c-></code> or <code class="highlight"><c- n="">radian_t</c-></code>.</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">units</c-> <c- p="">{</c->

<c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Units</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">T</c-> <c- o="">=</c-> <c- n="">UNIT_LIB_DEFAULT_TYPE</c-><c- p="">,</c->
         <c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-><c- o="">&gt;</c-> <c- k="">class</c-> <c- nc="">NonLinearScale</c-> <c- o="">=</c-> <c- n="">linear_scale</c-><c- o="">&gt;</c->
<c- k="">class</c-> <c- nc="">unit_t</c-> <c- o="">:</c-> <c- k="">public</c-> <c- n="">NonLinearScale</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-> <c- p="">{</c-> <c- p="">...</c-> <c- p="">};</c->

<c- p="">}</c->
</pre>
   <p>One more interesting point to notice here is that this library is using <code class="highlight"><c- k="">static_assert</c-></code> to
report conversion errors rather than to relay on an overload resolution process (and SFINAE).
The side effects of this are:</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><c- k="">static_assert</c-></code> being a QoI tool is not a part of function signature thus does not
influence overload resolution</p>
    </li><li data-md="">
     <p><code class="highlight"><c- k="">static_assert</c-></code> provides a short error message which might be a good thing but it also
often misses information about the source of the problem. For example below error
does not provide any information about the source and destination errors:</p>
<pre class="language-text highlight">    error: static assertion failed: Units are not compatible.
    static_assert(traits::is_convertible_unit&lt;UnitFrom, UnitTo&gt;::value, "Units are not compatible.");
                    ^~~~~~
</pre>
   </li></ul>
   <h3 class="heading settled" data-level="5.5" id="benri"><span class="secno">5.5. </span><span class="content">benri</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#benri"></a></h3>
   <p><a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-benri">[BENRI]</a> is a library written by Jan A. Sende and provides wide support for many <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①③">systems of units</a>, physical constants, mathematic operations, and affine spaces.</p>
   <h4 class="heading settled" data-level="5.5.1" id="benri.usage.example"><span class="secno">5.5.1. </span><span class="content">Usage example</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#benri.usage.example"></a></h4>
<pre class="language-cpp highlight"><c- cp="">#include</c-> &lt;benri/si/imperial.h&gt;
<c- cp="">#include</c-> &lt;benri/si/si.h&gt;
<c- cp="">#include</c-> &lt;iostream&gt;
<c- cp="">#include</c-> &lt;cassert&gt;

<c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Length</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">Time</c-><c- p="">,</c->
         <c- k="">typename</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">enable_if_t</c-><c- o="">&lt;</c-><c- n="">benri</c-><c- o="">::</c-><c- n="">type</c-><c- o="">::</c-><c- n="">detect_if</c-><c- o="">&lt;</c-><c- n="">Length</c-><c- p="">,</c-> <c- n="">benri</c-><c- o="">::</c-><c- n="">type</c-><c- o="">::</c-><c- n="">has_dimension</c-><c- p="">,</c->
                                                            <c- n="">benri</c-><c- o="">::</c-><c- n="">dimension</c-><c- o="">::</c-><c- n="">length_t</c-><c- o="">&gt;</c-> <c- o="">&amp;&amp;</c->
                                     <c- n="">benri</c-><c- o="">::</c-><c- n="">type</c-><c- o="">::</c-><c- n="">detect_if</c-><c- o="">&lt;</c-><c- n="">Time</c-><c- p="">,</c-> <c- n="">benri</c-><c- o="">::</c-><c- n="">type</c-><c- o="">::</c-><c- n="">has_dimension</c-><c- p="">,</c->
                                                            <c- n="">benri</c-><c- o="">::</c-><c- n="">dimension</c-><c- o="">::</c-><c- b="">time_t</c-><c- o="">&gt;&gt;&gt;</c->
<c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">Length</c-><c- o="">&amp;</c-> <c- n="">length</c-><c- p="">,</c-> <c- k="">const</c-> <c- n="">Time</c-><c- o="">&amp;</c-> <c- n="">time</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">ret</c-> <c- o="">=</c-> <c- n="">length</c-> <c- o="">/</c-> <c- n="">time</c-><c- p="">;</c->
  <c- k="">static_assert</c-><c- p="">(</c-><c- n="">benri</c-><c- o="">::</c-><c- n="">type</c-><c- o="">::</c-><c- n="">detect_if</c-><c- o="">&lt;</c-><c- k="">decltype</c-><c- p="">(</c-><c- n="">ret</c-><c- p="">),</c-> <c- n="">benri</c-><c- o="">::</c-><c- n="">type</c-><c- o="">::</c-><c- n="">has_dimension</c-><c- p="">,</c->
                <c- n="">benri</c-><c- o="">::</c-><c- n="">dimension</c-><c- o="">::</c-><c- n="">velocity_t</c-><c- o="">&gt;</c-><c- p="">);</c->
  <c- k="">return</c-> <c- n="">ret</c-><c- p="">;</c->
<c- p="">}</c->

<c- b="">void</c-> <c- n="">test1</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">using</c-> <c- k="">namespace</c-> <c- n="">benri</c-><c- o="">::</c-><c- n="">si</c-><c- p="">;</c->

  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mi="">220</c-><c- n="">_kilo</c-> <c- o="">*</c-> <c- n="">metre</c-><c- p="">,</c-> <c- mi="">2</c-><c- n="">_hour</c-><c- p="">);</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-><c- p="">.</c-><c- n="">value</c-><c- p="">()</c-> <c- o="">==</c-> <c- mi="">110</c-><c- p="">);</c->                <c- c1="">// passes</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- mi="">110</c-> <c- o="">*</c-> <c- n="">kilo</c-> <c- o="">*</c-> <c- n="">metre</c-> <c- o="">/</c-> <c- n="">hour</c-><c- p="">);</c->  <c- c1="">// passes</c->
<c- c1="">//  std::cout &lt;&lt; v &lt;&lt; '\n';                // no support</c->
<c- p="">}</c->

<c- b="">void</c-> <c- n="">test2</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">using</c-> <c- k="">namespace</c-> <c- n="">benri</c-><c- o="">::</c-><c- n="">si</c-><c- p="">;</c->

  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mi="">140</c-> <c- o="">*</c-> <c- n="">imperial</c-><c- o="">::</c-><c- n="">mile</c-><c- p="">,</c-> <c- mi="">2</c-> <c- o="">*</c-> <c- n="">hour</c-><c- p="">);</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-><c- p="">.</c-><c- n="">value</c-><c- p="">()</c-> <c- o="">==</c-> <c- mi="">70</c-><c- p="">);</c->                  <c- c1="">// passes</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- mi="">70</c-> <c- o="">*</c-> <c- n="">imperial</c-><c- o="">::</c-><c- n="">mile</c-> <c- o="">/</c-> <c- n="">hour</c-><c- p="">);</c->  <c- c1="">// passes</c->
<c- c1="">//  std::cout &lt;&lt; v &lt;&lt; '\n';                 // no support</c->
<c- p="">}</c->
</pre>
   <p><a href="https://godbolt.org/z/XANP7J">Compiler Explorer</a></p>
   <p>Above usage example is quite similar to the one in <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nic-units.usage.example">§ 5.4.1 Usage example</a> as both
libraries do not support function template arguments deduction for <code class="highlight"><c- n="">quantity</c-></code> class template
function arguments to improve overload resolution process. The interface architect has to use
SFINAE to achieve that.</p>
   <p>On contrary to <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-nic_units">[NIC_UNITS]</a> this library does not provide short predefined UDLs. UDLs are
defined only for prefixes and long names of named <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①⑧">units</a> while the user needs to compose
all other derived units by him/herself (i.e. <code class="highlight"><c- mi="">110</c-><c- n="">_kilo</c-> <c- o="">*</c-> <c- n="">metre</c-> <c- o="">/</c-> <c- n="">hour</c-></code>). This makes this
library to be similar to <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-boostunits">[BOOST.UNITS]</a> in that aspect.</p>
   <p>Interesting point to also notice here is that the library intentionally does not provide
text output support and leaves that work to the user. Beside forcing every user to
reinvent the wheel this approach might also result in some issues:</p>
   <ul>
    <li data-md="">
     <p>ODR violations (several dependency libraries might reimplement the same operator)</p>
    </li><li data-md="">
     <p>lookup problems (if user will not define the operators in <code class="highlight"><c- n="">std</c-></code> or <code class="highlight"><c- n="">benri</c-></code> namespace
those will not be found via ADL from a generic code)</p>
   </li></ul>
   <h4 class="heading settled" data-level="5.5.2" id="benri.design"><span class="secno">5.5.2. </span><span class="content">Design</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#benri.design"></a></h4>
   <p>The <code class="highlight"><c- n="">unit</c-></code> type implements the physics concept of a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement①⑨">unit</a> which is the product of a
prefix and a number of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension" id="ref-for-base-dimension⑧">base dimensions</a> with an associated power:</p>
<pre class="language-cpp highlight"><c- k="">template</c-> <c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Dimension</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">Prefix</c-><c- o="">&gt;</c->
<c- k="">struct</c-> <c- n="">unit</c-><c- p="">;</c->
</pre>
   <p>where both <code class="highlight"><c- n="">Dimension</c-></code> and <code class="highlight"><c- n="">Prefix</c-></code> are sorted type lists. Representing a prefix as a
type list is unique to this library and is meant to address limited range of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-></code>.</p>
   <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④①">Quantities</a> are addressed with two distinct types that are used to provide affine space
support:</p>
<pre class="language-cpp highlight"><c- k="">template</c-> <c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Unit</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">ValueType</c-> <c- o="">=</c-> <c- n="">Precision</c-><c- o="">&gt;</c->
<c- k="">class</c-> <c- nc="">quantity</c-><c- p="">;</c->

<c- k="">template</c-> <c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">Unit</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">ValueType</c-> <c- o="">=</c-> <c- n="">Precision</c-><c- o="">&gt;</c->
<c- k="">class</c-> <c- nc="">quantity_point</c-><c- p="">;</c->
</pre>
   <p>This library puts usage safety over user’s convenience. The effect of this is that even
obvious conversions require explicit casts on assignment, arithmetic operations, and
comparisons:</p>
<pre class="language-cpp highlight"><c- c1="">// auto a = 1_metre + 10_centi * metre;  // does not compile</c->
<c- c1="">//  assert(a &lt; 10_metre);                // does not compile</c->

<c- k="">auto</c-> <c- n="">a</c-> <c- o="">=</c-> <c- n="">benri</c-><c- o="">::</c-><c- n="">simple_cast</c-><c- o="">&lt;</c-><c- k="">decltype</c-><c- p="">(</c-><c- n="">centi</c-> <c- o="">*</c-> <c- n="">metre</c-><c- p="">)</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">1</c-><c- n="">_metre</c-><c- p="">)</c-> <c- o="">+</c-> <c- mi="">10</c-><c- n="">_centi</c-> <c- o="">*</c-> <c- n="">metre</c-><c- p="">;</c->
<c- n="">assert</c-><c- p="">(</c-><c- n="">a</c-> <c- o="">&lt;</c-> <c- n="">benri</c-><c- o="">::</c-><c- n="">simple_cast</c-><c- o="">&lt;</c-><c- k="">decltype</c-><c- p="">(</c-><c- n="">centi</c-> <c- o="">*</c-> <c- n="">metre</c-><c- p="">)</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">10</c-><c- n="">_metre</c-><c- p="">));</c->
</pre>
   <p>It can also be noted here that this library enforces AAA (Almost Always Auto) programming
style as due to limited number of predefined derived units it is often impossible to clearly
provide exact <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②⓪">unit</a> in a <code class="highlight"><c- n="">quantity</c-></code> type:</p>
<pre class="language-cpp highlight"><c- k="">const</c-> <c- k="">auto</c-> <c- n="">speed</c-> <c- o="">=</c-> <c- n="">a</c-> <c- o="">*</c-> <c- n="">metre</c-> <c- o="">/</c-> <c- n="">b</c-> <c- o="">*</c-> <c- n="">second</c-><c- p="">;</c->
</pre>
   <h3 class="heading settled" data-level="5.6" id="other"><span class="secno">5.6. </span><span class="content">Other</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#other"></a></h3>
   <p>There are more smaller units solutions out there. The author reviewed also the following
libraries:</p>
   <ul>
    <li data-md="">
     <p>Michael Ford units (<a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-mikeford3_units">[MIKEFORD3_UNITS]</a>)</p>
    </li><li data-md="">
     <p>Bryan St. Amour units (<a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-bryan_units">[BRYAN_UNITS]</a>)</p>
    </li><li data-md="">
     <p>Vincent Ducharme units (<a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-ducharme_units">[DUCHARME_UNITS]</a>)</p>
   </li></ul>
   <h3 class="heading settled" data-level="5.7" id="comparison"><span class="secno">5.7. </span><span class="content">Comparison</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#comparison"></a></h3>
   <table>
    <tbody>
     <tr>
      <th>Feature 
      </th><th>mp-units 
      </th><th>Boost.Units 
      </th><th>PhysUnits-CT-Cpp11 
      </th><th>nholthaus 
      </th><th>benri 
     </th></tr><tr>
      <td>SI 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
     </td></tr><tr>
      <td>Customary system 
      </td><td>yes 
      </td><td>yes 
      </td><td>some 
      </td><td>yes 
      </td><td>yes 
     </td></tr><tr>
      <td>Other systems 
      </td><td>??? 
      </td><td>yes 
      </td><td>no 
      </td><td>yes (<code class="highlight"><c- n="">bytes</c-></code>, <code class="highlight"><c- n="">radians</c-></code>) 
      </td><td>yes 
     </td></tr><tr>
      <td>C++ version 
      </td><td>C++20 
      </td><td>C++98 + <code class="highlight"><c- k="">constexpr</c-></code> 
      </td><td>C++11 
      </td><td>C++14 
      </td><td>C++14 
     </td></tr><tr>
      <td>Base dimension id 
      </td><td>string 
      </td><td>integer 
      </td><td>index on template parameter list 
      </td><td>index on template parameter list 
      </td><td>string 
     </td></tr><tr>
      <td>Dimension 
      </td><td>type (<code class="highlight"><c- n="">length</c-></code>) 
      </td><td>alias to type list (<code class="highlight"><c- n="">length_dimension</c-></code>) 
      </td><td>alias to type list (<code class="highlight"><c- n="">length_d</c-></code>) 
      </td><td>namespace (<code class="highlight"><c- n="">length</c-></code>) 
      </td><td>alias to type list (<code class="highlight"><c- n="">length_t</c-></code>) 
     </td></tr><tr>
      <td>Dimension representation 
      </td><td>type list 
      </td><td>type list 
      </td><td>class template arguments 
      </td><td>class template arguments 
      </td><td>type list 
     </td></tr><tr>
      <td>Fractional exponents 
      </td><td>yes 
      </td><td>yes 
      </td><td>no 
      </td><td>yes 
      </td><td>yes 
     </td></tr><tr>
      <td>Type traits for dimensions 
      </td><td>no 
      </td><td>yes 
      </td><td>no 
      </td><td>yes 
      </td><td>some 
     </td></tr><tr>
      <td>Unit 
      </td><td>type (<code class="highlight"><c- n="">metre</c-></code>) 
      </td><td>alias + constant (<code class="highlight"><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-></code> + <code class="highlight"><c- n="">si</c-><c- o="">::</c-><c- n="">meter</c-></code>) 
      </td><td>value (<code class="highlight"><c- n="">meter</c-></code>) 
      </td><td>alias (<code class="highlight"><c- n="">length</c-><c- o="">::</c-><c- n="">meter_t</c-></code>) 
      </td><td>alias (<code class="highlight"><c- n="">metre_t</c-></code>) 
     </td></tr><tr>
      <td>UDLs 
      </td><td>yes 
      </td><td>no 
      </td><td>some 
      </td><td>yes 
      </td><td>yes (long form only i.e. <code class="highlight"><c- n="">_metre</c-></code>) 
     </td></tr><tr>
      <td>Composable Units 
      </td><td>no 
      </td><td>prefix only (<code class="highlight"><c- n="">kilo</c-> <c- o="">*</c-> <c- n="">metre</c-></code>) 
      </td><td>prefix only (<code class="highlight"><c- n="">kilo</c-> <c- o="">*</c-> <c- n="">metre</c-></code>) 
      </td><td>no 
      </td><td>yes (<code class="highlight"><c- n="">kilo</c-> <c- o="">*</c-> <c- n="">metre</c-></code>) 
     </td></tr><tr>
      <td>Predefined scaled unit types 
      </td><td>some 
      </td><td>no 
      </td><td>some 
      </td><td>all 
      </td><td>no 
     </td></tr><tr>
      <td>Scaled units 
      </td><td>type + UDL (<code class="highlight"><c- n="">kilometre</c-></code> + <code class="highlight"><c- n="">km</c-></code>) 
      </td><td>predefined values or multiplied with a prefix (<code class="highlight"><c- n="">si</c-><c- o="">::</c-><c- n="">kilo</c-> <c- o="">*</c-> <c- n="">si</c-><c- o="">::</c-><c- n="">meter</c-></code>) 
      </td><td>value + UDL (<code class="highlight"><c- n="">mile</c-></code> + <code class="highlight"><c- n="">_km</c-></code>) 
      </td><td>type + UDL (<code class="highlight"><c- n="">length</c-><c- o="">::</c-><c- n="">kilometer_t</c-></code> + <code class="highlight"><c- n="">_km</c-></code>) 
      </td><td>no 
     </td></tr><tr>
      <td>Meter vs metre 
      </td><td>metre 
      </td><td>both 
      </td><td>both 
      </td><td>meter 
      </td><td>metre 
     </td></tr><tr>
      <td>Singular vs plural 
      </td><td>singular (<code class="highlight"><c- n="">metre</c-></code>) 
      </td><td>both (<code class="highlight"><c- n="">meter</c-></code> + <code class="highlight"><c- n="">meters</c-></code>) 
      </td><td>singular 
      </td><td>both (<code class="highlight"><c- n="">length</c-><c- o="">::</c-><c- n="">meter_t</c-></code> + <code class="highlight"><c- n="">length</c-><c- o="">::</c-><c- n="">meters_t</c-></code>) 
      </td><td>singular (<code class="highlight"><c- n="">metre</c-></code>) 
     </td></tr><tr>
      <td>Quantity 
      </td><td>type (<code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">metre</c-><c- o="">&gt;</c-> <c- n="">q</c-><c- p="">(</c-><c- mi="">2</c-><c- p="">);</c-></code>) 
      </td><td>type (<code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&gt;</c-> <c- n="">q</c-><c- p="">(</c-><c- mi="">2</c-> <c- o="">*</c-> <c- n="">si</c-><c- o="">::</c-><c- n="">meter</c-><c- p="">);</c-></code>) 
      </td><td>type (<code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">speed_d</c-><c- o="">&gt;</c-> <c- n="">speed</c-> <c- o="">=</c-> <c- mi="">45</c-><c- n="">_km</c-> <c- o="">/</c-> <c- n="">hour</c-><c- p="">;</c-></code>) 
      </td><td>type (<code class="highlight"><c- n="">length</c-><c- o="">::</c-><c- n="">meter_t</c-> <c- n="">d</c-><c- p="">(</c-><c- mi="">220</c-><c- p="">);</c-></code>) 
      </td><td>type (<code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">metre</c-><c- o="">&gt;</c-> <c- n="">q</c-><c- p="">(</c-><c- mi="">2</c-><c- p="">);</c-></code>) 
     </td></tr><tr>
      <td>Literal instance 
      </td><td>UDL (<code class="highlight"><c- mi="">123</c-><c- n="">m</c-></code>) 
      </td><td>Number * static constant (<code class="highlight"><c- mi="">123</c-> <c- o="">*</c-> <c- n="">si</c-><c- o="">::</c-><c- n="">meters</c-></code>) 
      </td><td>UDL (<code class="highlight"><c- mi="">1</c-><c- n="">_m</c-></code>) 
      </td><td>UDL (<code class="highlight"><c- mi="">123</c-><c- n="">_m</c-></code>) 
      </td><td>UDL (<code class="highlight"><c- mi="">1</c-><c- n="">_metre</c-></code>) 
     </td></tr><tr>
      <td>Variable instance 
      </td><td>constructor (<code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">metre</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">v</c-><c- p="">)</c-></code>) 
      </td><td>Variable * static constant (<code class="highlight"><c- n="">d</c-> <c- o="">*</c-> <c- n="">si</c-><c- o="">::</c-><c- n="">meters</c-></code>) 
      </td><td>Variable * static constant (<code class="highlight"><c- n="">d</c-> <c- o="">*</c-> <c- n="">kilo</c-> <c- o="">*</c-> <c- n="">meter</c-></code>) 
      </td><td>constructor (<code class="highlight"><c- n="">length</c-><c- o="">::</c-><c- n="">meter_t</c-><c- p="">(</c-><c- n="">v</c-><c- p="">)</c-></code>) 
      </td><td>constructor (<code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">metre</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">v</c-><c- p="">)</c-></code>) 
     </td></tr><tr>
      <td>Any representation 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>no (macro to set the default type) 
      </td><td>yes (macro default of <code class="highlight"><c- b="">double</c-></code>) 
     </td></tr><tr>
      <td>Quantity template arguments type deduction 
      </td><td>yes 
      </td><td>yes 
      </td><td>no 
      </td><td>no 
      </td><td>no 
     </td></tr><tr>
      <td>System support 
      </td><td>no 
      </td><td>yes 
      </td><td>no 
      </td><td>no 
      </td><td>no 
     </td></tr><tr>
      <td>C++ Concepts 
      </td><td>yes 
      </td><td>no 
      </td><td>no 
      </td><td>no 
      </td><td>no 
     </td></tr><tr>
      <td>Types downcasting 
      </td><td>yes 
      </td><td>no 
      </td><td>no 
      </td><td>no 
      </td><td>no 
     </td></tr><tr>
      <td>Implicit unit conversions 
      </td><td>same dimension non-truncating only 
      </td><td>no 
      </td><td>same dimension 
      </td><td>same dimension 
      </td><td>no 
     </td></tr><tr>
      <td>Explicit unit conversions 
      </td><td><code class="highlight"><c- n="">quantity_cast</c-></code> 
      </td><td><code class="highlight"><c- n="">quantity_cast</c-></code> 
      </td><td>yes 
      </td><td>no 
      </td><td><code class="highlight"><c- n="">simple_cast</c-></code> (<code class="highlight"><c- k="">constexpr</c-></code>)/<code class="highlight"><c- n="">unit_cast</c-></code> 
     </td></tr><tr>
      <td>Runtime conversion factors 
      </td><td>no 
      </td><td>yes 
      </td><td>no 
      </td><td>no 
      </td><td>no 
     </td></tr><tr>
      <td>Temperature support 
      </td><td>Kelvins only + conversion functions
      </td><td>Kelvins in SI + other in dedicated systems 
      </td><td>relative values only 
      </td><td>absolute values only 
      </td><td>yes 
     </td></tr><tr>
      <td>String output 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>no 
     </td></tr><tr>
      <td>String input 
      </td><td>no 
      </td><td>no 
      </td><td>no 
      </td><td>no 
      </td><td>no 
     </td></tr><tr>
      <td>Macros in the user interface 
      </td><td>no 
      </td><td>yes 
      </td><td>no 
      </td><td>yes 
      </td><td>yes 
     </td></tr><tr>
      <td>Non-linear scale support 
      </td><td>no 
      </td><td>no 
      </td><td>no 
      </td><td>yes 
      </td><td>no 
     </td></tr><tr>
      <td><code class="highlight"><c- o="">&lt;</c-><c- n="">cmath</c-><c- o="">&gt;</c-></code> support 
      </td><td>TBD 
      </td><td>yes 
      </td><td>no 
      </td><td>yes 
      </td><td>yes 
     </td></tr><tr>
      <td><code class="highlight"><c- o="">&lt;</c-><c- n="">chrono</c-><c- o="">&gt;</c-></code> support 
      </td><td>??? 
      </td><td>no 
      </td><td>no 
      </td><td>yes 
      </td><td>yes 
     </td></tr><tr>
      <td>Affine types 
      </td><td>??? 
      </td><td>yes (<code class="highlight"><c- n="">absolute</c-><c- o="">&lt;</c-><c- n="">Q</c-><c- o="">&gt;</c-></code>) 
      </td><td>no 
      </td><td>no 
      </td><td>yes (<code class="highlight"><c- n="">quantity</c-></code>, <code class="highlight"><c- n="">quantity_point</c-></code>) 
     </td></tr><tr>
      <td>Prefix representation 
      </td><td>ratio 
      </td><td><code class="highlight"><c- n="">scale</c-><c- o="">&lt;</c-><c- mi="">10</c-><c- p="">,</c-> <c- n="">static_rational</c-><c- o="">&lt;</c-><c- n="">exponent</c-><c- o="">&gt;&gt;</c-></code> 
      </td><td>long double 
      </td><td>ratio 
      </td><td>type list 
     </td></tr><tr>
      <td>Physical/Mathematical constants 
      </td><td>TBD 
      </td><td>yes 
      </td><td>limited 
      </td><td>limited 
      </td><td>all 
     </td></tr><tr>
      <td>Dimensionless quantity 
      </td><td>??? 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
     </td></tr><tr>
      <td>Arbitrary conversions 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>no 
      </td><td>yes 
     </td></tr><tr>
      <td>User defined base dimensions 
      </td><td>yes 
      </td><td>yes 
      </td><td>no 
      </td><td>no 
      </td><td>yes 
     </td></tr><tr>
      <td>User defined derived dimensions 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
     </td></tr><tr>
      <td>User defined units 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
     </td></tr><tr>
      <td>User defined prefixes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
      </td><td>yes 
   </td></tr></tbody></table>
   <h2 class="heading settled" data-level="6" id="concerns"><span class="secno">6. </span><span class="content">Fundamental concerns with current solutions</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#concerns"></a></h2>
   <p>Feedback from the users gathered so far signals the following significant complaints regarding
the libraries described in <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#prior-work">§ 5 Prior Work</a>:</p>
   <ol>
    <li data-md="">
     <p>Bad user experience caused by hard to understand and analyze compile-time errors and poor
debugging experience (addressed by <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#user-experience">§ 7 Improving user experience</a>).</p>
    </li><li data-md="">
     <p>Unnecessary intermediate <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-value" id="ref-for-quantity-value">quantity value</a> conversions to <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①③">base units</a> resulting in a
runtime overhead and loss of precision (addressed by <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#limiting-intermediate-value-conversions">§ 8 Limiting intermediate quantity value conversions</a>).</p>
    </li><li data-md="">
     <p>Poor support for really <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#multiple-of-a-unit" id="ref-for-multiple-of-a-unit">large</a> or <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#submultiple-of-a-unit" id="ref-for-submultiple-of-a-unit">small</a> unit ratios (i.e. <code class="highlight"><c- n="">eV</c-></code>) (addressed by <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ratio-on-steroids">§ 9 std::ratio on steroids</a>).</p>
    </li><li data-md="">
     <p>Impossibility or hard extensibility of the library with new <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity⑧">base quantities</a> (addressed by <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#extensibility">§ 10 Extensibility</a>).</p>
    </li><li data-md="">
     <p>Too high entry bar (e.g. Boost.Units is claimed to require expertise in both C++ and
dimensional analysis) (addressed by <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#easy-to-use-hard-to-abuse">§ 11 Easy to use and hard to abuse</a>).</p>
    </li><li data-md="">
     <p>Safety and security connected problems with the usage of an external 3rd party library
for production purposes (addresed by <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#motivation">§ 3.1 Motivation</a>).</p>
   </li></ol>
   <h2 class="heading settled" data-level="7" id="user-experience"><span class="secno">7. </span><span class="content">Improving user experience</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#user-experience"></a></h2>
   <h3 class="heading settled" data-level="7.1" id="type-aliasing-issues"><span class="secno">7.1. </span><span class="content">Type aliasing issues</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#type-aliasing-issues"></a></h3>
   <p>Type aliases benefit developers but not end-users. As a result users end up with colossal
error messages.</p>
   <p>Taking Boost.Units as an example, the code developer works with the following syntax:</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">bu</c-> <c- o="">=</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- p="">;</c->

<c- k="">constexpr</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">velocity</c-><c- o="">&gt;</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&gt;</c-> <c- n="">d</c-><c- p="">,</c->
                                                   <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">time</c-><c- o="">&gt;</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c-> <c- k="">return</c-> <c- n="">d</c-> <c- o="">*</c-> <c- n="">t</c-><c- p="">;</c-> <c- p="">}</c->
</pre>
   <p>Above calculation contains a simple error as a velocity <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-quantity" id="ref-for-derived-quantity④">derived quantity</a> cannot be
created from multiplication of length and time <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity⑨">base quantities</a>. If such an error happens
in the source code, user will need to analyze the following error for gcc-8:</p>
<pre class="language-text highlight">error: could not convert ‘boost::units::operator*(const boost::units::quantity&lt;Unit1, X&gt;&amp;,
const boost::units::quantity&lt;Unit2, Y&gt;&amp;) [with Unit1 = boost::units::unit&lt;boost::units::list&lt;boost::units::dim
&lt;boost::units::length_base_dimension, boost::units::static_rational&lt;1&gt; &gt;, boost::units::dimensionless_type&gt;,
boost::units::homogeneous_system&lt;boost::units::list&lt;boost::units::si::meter_base_unit,
boost::units::list&lt;boost::units::scaled_base_unit&lt;boost::units::cgs::gram_base_unit, boost::units::scale&lt;10,
boost::units::static_rational&lt;3&gt; &gt; &gt;, boost::units::list&lt;boost::units::si::second_base_unit,
boost::units::list&lt;boost::units::si::ampere_base_unit, boost::units::list&lt;boost::units::si::kelvin_base_unit,
boost::units::list&lt;boost::units::si::mole_base_unit, boost::units::list&lt;boost::units::si::candela_base_unit,
boost::units::list&lt;boost::units::angle::radian_base_unit, boost::units::list&lt;boost::units::angle::steradian_base_unit,
boost::units::dimensionless_type&gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt;; Unit2 = boost::units::unit&lt;boost::units::list&lt;boost::units::dim
&lt;boost::units::time_base_dimension, boost::units::static_rational&lt;1&gt; &gt;, boost::units::dimensionless_type&gt;,
boost::units::homogeneous_system&lt;boost::units::list&lt;boost::units::si::meter_base_unit,
boost::units::list&lt;boost::units::scaled_base_unit&lt;boost::units::cgs::gram_base_unit, boost::units::scale&lt;10,
boost::units::static_rational&lt;3&gt; &gt; &gt;, boost::units::list&lt;boost::units::si::second_base_unit, boost::units::list
&lt;boost::units::si::ampere_base_unit, boost::units::list&lt;boost::units::si::kelvin_base_unit, boost::units::list
&lt;boost::units::si::mole_base_unit, boost::units::list&lt;boost::units::si::candela_base_unit, boost::units::list
&lt;boost::units::angle::radian_base_unit, boost::units::list&lt;boost::units::angle::steradian_base_unit,
boost::units::dimensionless_type&gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt;; X = double; Y = double; typename
boost::units::multiply_typeof_helper&lt;boost::units::quantity&lt;Unit1, X&gt;, boost::units::quantity&lt;Unit2, Y&gt; &gt;::type =
boost::units::quantity&lt;boost::units::unit&lt;boost::units::list&lt;boost::units::dim&lt;boost::units::length_base_dimension,
boost::units::static_rational&lt;1&gt; &gt;, boost::units::list&lt;boost::units::dim&lt;boost::units::time_base_dimension,
boost::units::static_rational&lt;1&gt; &gt;, boost::units::dimensionless_type&gt; &gt;, boost::units::homogeneous_system
&lt;boost::units::list&lt;boost::units::si::meter_base_unit, boost::units::list&lt;boost::units::scaled_base_unit
&lt;boost::units::cgs::gram_base_unit, boost::units::scale&lt;10, boost::units::static_rational&lt;3&gt; &gt; &gt;,
boost::units::list&lt;boost::units::si::second_base_unit, boost::units::list&lt;boost::units::si::ampere_base_unit,
boost::units::list&lt;boost::units::si::kelvin_base_unit, boost::units::list&lt;boost::units::si::mole_base_unit,
boost::units::list&lt;boost::units::si::candela_base_unit, boost::units::list&lt;boost::units::angle::radian_base_unit,
boost::units::list&lt;boost::units::angle::steradian_base_unit, boost::units::dimensionless_type&gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt;,
void&gt;, double&gt;](t)’ from ‘quantity&lt;unit&lt;list&lt;[...],list&lt;dim&lt;[...],static_rational&lt;1&gt;&gt;,[...]&gt;&gt;,[...],[...]&gt;,[...]&gt;’
to ‘quantity&lt;unit&lt;list&lt;[...],list&lt;dim&lt;[...],static_rational&lt;-1&gt;&gt;,[...]&gt;&gt;,[...],[...]&gt;,[...]&gt;’
     return d * t;
            ~~^~~
</pre>
   <p>An important point to notice here is that above text is just the very first line of the
compilation error log. Error log for the same problem generated by clang-7 looks as follows:</p>
<pre class="language-text highlight">error: no viable conversion from returned value of type 'quantity&lt;unit&lt;list&lt;[...], list&lt;dim&lt;[...],
static_rational&lt;1, [...]&gt;&gt;, [...]&gt;&gt;, [...]&gt;, [...]&gt;' to function return type 'quantity&lt;unit&lt;list&lt;[...], list&lt;dim&lt;[...],
static_rational&lt;-1, [...]&gt;&gt;, [...]&gt;&gt;, [...]&gt;, [...]&gt;'
    return d * t;
           ^~~~~
</pre>
   <p>Despite being shorter, this message does not really help much in finding the actual fault too.</p>
   <p>Omnipresent type aliasing does not affect only compilation errors observed by the end-user
but also debugging. Here is how a breakpoint for the above function looks like in the gdb debugger:</p>
<pre class="language-text highlight">Breakpoint 1, avg_speed&lt;boost::units::heterogeneous_system&lt;boost::units::heterogeneous_system_impl
&lt;boost::units::list&lt;boost::units::heterogeneous_system_dim&lt;boost::units::si::meter_base_unit, boost::units::static_rational&lt;1&gt; &gt;,
boost::units::dimensionless_type&gt;, boost::units::list&lt;boost::units::dim&lt;boost::units::length_base_dimension,
boost::units::static_rational&lt;1&gt; &gt;, boost::units::dimensionless_type&gt;, boost::units::list&lt;boost::units::scale_list_dim
&lt;boost::units::scale&lt;10, boost::units::static_rational&lt;3&gt; &gt; &gt;, boost::units::dimensionless_type&gt; &gt; &gt;,
boost::units::heterogeneous_system&lt;boost::units::heterogeneous_system_impl&lt;boost::units::list
&lt;boost::units::heterogeneous_system_dim&lt;boost::units::scaled_base_unit&lt;boost::units::si::second_base_unit,
boost::units::scale&lt;60, boost::units::static_rational&lt;2&gt; &gt; &gt;, boost::units::static_rational&lt;1&gt; &gt;,
boost::units::dimensionless_type&gt;, boost::units::list&lt;boost::units::dim&lt;boost::units::time_base_dimension,
boost::units::static_rational&lt;1&gt; &gt;, boost::units::dimensionless_type&gt;, boost::units::dimensionless_type&gt; &gt; &gt; (d=..., t=...) at
velocity_2.cpp:39
39        return d / t;
</pre>
   <h3 class="heading settled" data-level="7.2" id="downcasting"><span class="secno">7.2. </span><span class="content">Downcasting facility</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#downcasting"></a></h3>
   <p>To provide much shorter error messages the author of the paper with the help of Richard Smith,
implemented a downcast facility in <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-mp-units">[MP-UNITS]</a>. It allowed converting the following error
log from:</p>
<pre class="language-text highlight">[with T = units::quantity&lt;units::unit&lt;units::dimension&lt;units::exp&lt;units::base_dim_length, 1&gt;,
units::exp&lt;units::base_dim_time, -1&gt; &gt; &gt;, std::ratio&lt;1&gt; &gt;, double&gt;]
</pre>
   <p>into:</p>
<pre class="language-text highlight">[with T = units::quantity&lt;units::metre_per_second, double&gt;]
</pre>
   <p>As a result the type dumped in the error log is exactly the same entity that the developer
used to implement the erroneous source code.</p>
   <p>The above is possible thanks to the fact that the downcasting facility provides a type
substitution mechanism. It connects a specific primary class template instantiation with
a strong type assigned by the user. A simplified mental model of the facility may be
represented as:</p>
<pre class="language-cpp highlight"><c- k="">struct</c-> <c- nl="">velocity</c-> <c- p="">:</c-> <c- n="">dimension</c-><c- o="">&lt;</c-><c- n="">exp</c-><c- o="">&lt;</c-><c- n="">base_dim_length</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">exp</c-><c- o="">&lt;</c-><c- n="">base_dim_time</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">1</c-><c- o="">&gt;&gt;</c-><c- p="">;</c->
<c- k="">struct</c-> <c- nl="">metre_per_second</c-> <c- p="">:</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">velocity</c-><c- p="">,</c-> <c- s="">"m/s"</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- o="">&gt;&gt;</c-><c- p="">;</c->
</pre>
   <p>In the above example, <code class="highlight"><c- n="">velocity</c-></code> and <code class="highlight"><c- n="">metre_per_second</c-></code> are the downcasting targets
(child classes), and specific <code class="highlight"><c- n="">dimension</c-></code> and <code class="highlight"><c- n="">unit</c-></code> class template instantiations
are downcasting sources (base classes). The downcasting facility provides one to one
type substitution mechanism for those types. This means that only one child class can
be created for a specific base class template instantiation.</p>
   <p>The downcasting facility is provided through two dedicated types, a concept, and a few
helper template aliases.</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">BaseType</c-><c- o="">&gt;</c->
<c- k="">struct</c-> <c- n="">downcast_base</c-> <c- p="">{</c->
  <c- k="">using</c-> <c- n="">base_type</c-> <c- o="">=</c-> <c- n="">BaseType</c-><c- p="">;</c->
  <c- k="">friend</c-> <c- k="">auto</c-> <c- nf="">downcast_guide</c-><c- p="">(</c-><c- n="">downcast_base</c-><c- p="">);</c->
<c- p="">};</c->
</pre>
   <p><code class="highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">downcast_base</c-></code> is a class that implements the CRTP idiom, marks the base of the
downcasting facility with a <code class="highlight"><c- n="">base_type</c-></code> member type, and provides a declaration of the
downcasting ADL friendly (Hidden Friend) entry point member function <code class="highlight"><c- n="">downcast_guide</c-></code>.
An important design point is that this function does not return any specific type in its
declaration. This non-member function is going to be defined in a child class template <code class="highlight"><c- n="">downcast_helper</c-></code> and will return a target type of the downcasting operation there.</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">T</c-><c- o="">&gt;</c->
<c- n="">concept</c-> <c- n="">Downcastable</c-> <c- o="">=</c->
    <c- n="">requires</c-> <c- p="">{</c->
      <c- k="">typename</c-> <c- n="">T</c-><c- o="">::</c-><c- n="">base_type</c-><c- p="">;</c->
    <c- p="">}</c-> <c- o="">&amp;&amp;</c->
    <c- n="">std</c-><c- o="">::</c-><c- n="">derived_from</c-><c- o="">&lt;</c-><c- n="">T</c-><c- p="">,</c-> <c- n="">downcast_base</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">T</c-><c- o="">::</c-><c- n="">base_type</c-><c- o="">&gt;&gt;</c-><c- p="">;</c->
</pre>
   <p><code class="highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">Downcastable</c-></code> is a concept that verifies if a type implements and can be used in
a downcasting facility.</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Target</c-><c- p="">,</c-> <c- n="">Downcastable</c-> <c- n="">T</c-><c- o="">&gt;</c->
<c- k="">struct</c-> <c- nl="">downcast_helper</c-> <c- p="">:</c-> <c- n="">T</c-> <c- p="">{</c->
  <c- k="">friend</c-> <c- k="">auto</c-> <c- n="">downcast_guide</c-><c- p="">(</c-><c- k="">typename</c-> <c- n="">downcast_helper</c-><c- o="">::</c-><c- n="">downcast_base</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">Target</c-><c- p="">();</c-> <c- p="">}</c->
<c- p="">};</c->
</pre>
   <p><code class="highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">downcast_helper</c-></code> is another CRTP class template that provides the implementation
of a non-member friend function of the <code class="highlight"><c- n="">downcast_base</c-></code> class template, which defines the target
type of a downcasting operation. It is used in the following way to define <code class="highlight"><c- n="">dimension</c-></code> and <code class="highlight"><c- n="">unit</c-></code> types in the library:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Child</c-><c- p="">,</c-> <c- n="">Exponent</c-><c- p="">...</c-> <c- n="">Es</c-><c- o="">&gt;</c->
<c- k="">struct</c-> <c- nl="">derived_dimension</c-> <c- p="">:</c-> <c- n="">downcast_helper</c-><c- o="">&lt;</c-><c- n="">Child</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">detail</c-><c- o="">::</c-><c- n="">make_dimension</c-><c- o="">&lt;</c-><c- n="">Es</c-><c- p="">...</c-><c- o="">&gt;::</c-><c- n="">type</c-><c- o="">&gt;</c-> <c- p="">{};</c->
</pre>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Child</c-><c- p="">,</c-> <c- n="">basic_fixed_string</c-> <c- n="">Symbol</c-><c- p="">,</c-> <c- n="">Dimension</c-> <c- n="">D</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">PrefixType</c-> <c- o="">=</c-> <c- n="">no_prefix</c-><c- o="">&gt;</c->
<c- k="">struct</c-> <c- nl="">coherent_derived_unit</c-> <c- p="">:</c-> <c- n="">downcast_helper</c-><c- o="">&lt;</c-><c- n="">Child</c-><c- p="">,</c-> <c- n="">unit</c-><c- o="">&lt;</c-><c- n="">D</c-><c- p="">,</c-> <c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- o="">&gt;&gt;&gt;</c-> <c- p="">{</c->
  <c- k="">static</c-> <c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">symbol</c-> <c- o="">=</c-> <c- n="">Symbol</c-><c- p="">;</c->
  <c- k="">using</c-> <c- n="">prefix_type</c-> <c- o="">=</c-> <c- n="">PrefixType</c-><c- p="">;</c->
<c- p="">};</c->
</pre>
   <p>With such helper types, the only thing the user has to do is to register a new type for the
downcasting facility by publicly deriving from one of those CRTP types and provide its new
child type as the first template parameter of the CRTP type:</p>
<pre class="language-cpp highlight"><c- k="">struct</c-> <c- nl="">velocity</c-> <c- p="">:</c-> <c- n="">derived_dimension</c-><c- o="">&lt;</c-><c- n="">velocity</c-><c- p="">,</c-> <c- n="">exp</c-><c- o="">&lt;</c-><c- n="">base_dim_length</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">exp</c-><c- o="">&lt;</c-><c- n="">base_dim_time</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">1</c-><c- o="">&gt;&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">metre_per_second</c-> <c- p="">:</c-> <c- n="">coherent_derived_unit</c-><c- o="">&lt;</c-><c- n="">metre_per_second</c-><c- p="">,</c-> <c- s="">"m/s"</c-><c- p="">,</c-> <c- n="">velocity</c-><c- o="">&gt;</c-> <c- p="">{};</c->
</pre>
   <p>The above types are used to define the base and target of a downcasting operation. To perform
the actual downcasting operation, a dedicated template alias is provided and used by the
library’s framework:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- n="">Downcastable</c-> <c- n="">T</c-><c- o="">&gt;</c->
<c- k="">using</c-> <c- n="">downcast_target</c-> <c- o="">=</c-> <c- k="">decltype</c-><c- p="">(</c-><c- n="">detail</c-><c- o="">::</c-><c- n="">downcast_target_impl</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">());</c->
</pre>
   <p><code class="highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">downcast_target</c-></code> is used to obtain the target type of the downcasting operation
registered for a given instantiation in a base type.</p>
   <p>For example, to determine a downcasted type of a quantity multiplication, the following
can be done:</p>
<pre class="language-cpp highlight"><c- k="">using</c-> <c- n="">dim</c-> <c- o="">=</c-> <c- n="">dimension_multiply</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">U1</c-><c- o="">::</c-><c- n="">dimension</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">U2</c-><c- o="">::</c-><c- n="">dimension</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">ratio</c-> <c- o="">=</c-> <c- n="">ratio_multiply</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">U1</c-><c- o="">::</c-><c- n="">ratio</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">U2</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">common_rep</c-> <c- o="">=</c-> <c- k="">decltype</c-><c- p="">(</c-><c- n="">lhs</c-><c- p="">.</c-><c- n="">count</c-><c- p="">()</c-> <c- o="">*</c-> <c- n="">rhs</c-><c- p="">.</c-><c- n="">count</c-><c- p="">());</c->
<c- k="">using</c-> <c- n="">ret</c-> <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">downcast_target</c-><c- o="">&lt;</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">dim</c-><c- p="">,</c-> <c- n="">ratio</c-><c- o="">&gt;&gt;</c-><c- p="">,</c-> <c- n="">common_rep</c-><c- o="">&gt;</c-><c- p="">;</c->
</pre>
   <p><code class="highlight"><c- n="">detail</c-><c- o="">::</c-><c- n="">downcast_target_impl</c-></code> checks if a downcasting target is registered for the specific
base class. If registered, <code class="highlight"><c- n="">detail</c-><c- o="">::</c-><c- n="">downcast_target_impl</c-></code> returns the registered type,
otherwise it returns the provided base class.</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">detail</c-> <c- p="">{</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">T</c-><c- o="">&gt;</c->
  <c- n="">concept</c-> <c- n="">has_downcast</c-> <c- o="">=</c-> <c- n="">requires</c-> <c- p="">{</c->
    <c- n="">downcast_guide</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- n="">declval</c-><c- o="">&lt;</c-><c- n="">downcast_base</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;&gt;</c-><c- p="">());</c->
  <c- p="">};</c->

  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">T</c-><c- o="">&gt;</c->
  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">downcast_target_impl</c-><c- p="">()</c->
  <c- p="">{</c->
    <c- k="">if</c-> <c- k="">constexpr</c-><c- p="">(</c-><c- n="">has_downcast</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">)</c->
      <c- k="">return</c-> <c- k="">decltype</c-><c- p="">(</c-><c- n="">downcast_guide</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- n="">declval</c-><c- o="">&lt;</c-><c- n="">downcast_base</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;&gt;</c-><c- p="">()))();</c->
    <c- k="">else</c->
      <c- k="">return</c-> <c- nf="">T</c-><c- p="">();</c->
  <c- p="">}</c->

<c- p="">}</c->
</pre>
   <h3 class="heading settled" data-level="7.3" id="template-instantiation-issues"><span class="secno">7.3. </span><span class="content">Template instantiation issues</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#template-instantiation-issues"></a></h3>
   <p>C++ is known for massive error logs caused by compilation errors deep down in the stack of
function template instantiations of an implementation. In the vast majority of cases, this
is caused by function templates just taking a <code class="highlight"><c- k="">typename</c-> <c- n="">T</c-></code> as their parameter, not placing
any constratints on the actual type. In C++17 placing such constraints is possible thanks
to SFINAE and helpers like <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">enable_if</c-></code> or <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">void_t</c-></code>. However, these are known to be
not really user-friendly.</p>
   <p>Consider the following example:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Length</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Time</c-><c- p="">,</c->
         <c- k="">typename</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">enable_if_t</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">traits</c-><c- o="">::</c-><c- n="">is_length_unit</c-><c- o="">&lt;</c-><c- n="">Length</c-><c- o="">&gt;::</c-><c- n="">value</c-> <c- o="">&amp;&amp;</c->
                                     <c- n="">units</c-><c- o="">::</c-><c- n="">traits</c-><c- o="">::</c-><c- n="">is_time_unit</c-><c- o="">&lt;</c-><c- n="">Time</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- o="">&gt;&gt;</c->
<c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">Length</c-> <c- n="">d</c-><c- p="">,</c-> <c- n="">Time</c-> <c- n="">t</c-><c- p="">)</c->
  <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">enable_if_t</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">traits</c-><c- o="">::</c-><c- n="">is_velocity_unit</c-><c- o="">&lt;</c-><c- k="">decltype</c-><c- p="">(</c-><c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">)</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- k="">decltype</c-><c- p="">(</c-><c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">)</c-><c- o="">&gt;</c->
<c- p="">{</c->
  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
  <c- k="">static_assert</c-><c- p="">(</c-><c- n="">units</c-><c- o="">::</c-><c- n="">traits</c-><c- o="">::</c-><c- n="">is_velocity_unit</c-><c- o="">&lt;</c-><c- k="">decltype</c-><c- p="">(</c-><c- n="">v</c-><c- p="">)</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- p="">);</c->
  <c- k="">return</c-> <c- n="">v</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>Clearly this is not the most user-friendly way to write code every day. Imagine the effort
involved for C++ experts and non-experts alike to write longer and more complex functions,
multiline calculations, or even whole programs in this style. Obviously C++20 concepts
radically simplify the boiler plate involved and are thus the way to go.</p>
   <h3 class="heading settled" data-level="7.4" id="better-errors-with-concepts"><span class="secno">7.4. </span><span class="content">Better errors with C++20 concepts</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#better-errors-with-concepts"></a></h3>
   <p>With C++20 concepts above example is simplified to:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Length</c-> <c- n="">L</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Time</c-> <c- n="">T</c-><c- o="">&gt;</c->
<c- k="">constexpr</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">L</c-> <c- n="">d</c-><c- p="">,</c-> <c- n="">T</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>Using generic functions, it can even be implemented, without the template syntax, as:</p>
<pre class="language-cpp highlight"><c- k="">constexpr</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Length</c-> <c- k="">auto</c-> <c- n="">d</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Time</c-> <c- k="">auto</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>Thanks to C++20 concepts we not only get much stronger interfaces with their compile-time
contracts clearly expressed by concepts in the function template signature, but also much
better error logs. Concept constraint validation being done early in the function instantiation
process catches errors early and not deep in the instantiation stack, significantly improving
the readability of the actual errors.</p>
   <p>For example, gcc with experimental Concepts TS support generates the following message:</p>
<pre class="language-text highlight">example.cpp: In instantiation of ‘constexpr units::Velocity avg_speed(D, T)
    [with D = units::quantity&lt;units::kilometre&gt;; T = units::quantity&lt;units::hour&gt;]’:
example.cpp:49:49:   required from here
example.cpp:34:14: error: placeholder constraints not satisfied
    34 |   return d * t;
       |              ^
include/units/dimensions/velocity.h:34:16: note: within ‘template&lt;class T&gt; concept units::Velocity&lt;T&gt;
    [with T = units::quantity&lt;units::unit&lt;units::dimension&lt;units::exp&lt;units::base_dim_length, 1, 1&gt;,
                units::exp&lt;units::base_dim_time, 1, 1&gt; &gt;, units::ratio&lt;3600000, 1&gt; &gt;, double&gt;]’
    34 |   concept Velocity = Quantity&lt;T&gt; &amp;&amp; std::same_as&lt;typename T::dimension, velocity&gt;;
       |           ^~~~~~~~
include/stl2/detail/concepts/core.hpp:37:15: note: within ‘template&lt;class T, class U&gt; concept std::same_as&lt;T, U&gt;
    [with T = units::dimension&lt;units::exp&lt;units::base_dim_length, 1, 1&gt;, units::exp&lt;units::base_dim_time, 1, 1&gt; &gt;;
          U = units::velocity]’
    37 |  META_CONCEPT same_as = meta::Same&lt;T, U&gt; &amp;&amp; meta::Same&lt;U, T&gt;;
       |               ^~~~~~~
include/meta/meta_fwd.hpp:224:18: note: within ‘template&lt;class T, class U&gt; concept meta::Same&lt;T, U&gt;
    [with T = units::dimension&lt;units::exp&lt;units::base_dim_length, 1, 1&gt;, units::exp&lt;units::base_dim_time, 1, 1&gt; &gt;;
          U = units::velocity]’
   224 |     META_CONCEPT Same =
       |                  ^~~~
include/meta/meta_fwd.hpp:224:18: note: ‘meta::detail::barrier’ evaluated to false
include/meta/meta_fwd.hpp:224:18: note: within ‘template&lt;class T, class U&gt; concept meta::Same&lt;T, U&gt;
    [with T = units::velocity;
          U = units::dimension&lt;units::exp&lt;units::base_dim_length, 1, 1&gt;, units::exp&lt;units::base_dim_time, 1, 1&gt; &gt;]’
include/meta/meta_fwd.hpp:224:18: note: ‘meta::detail::barrier’ evaluated to false
</pre>
   <p>While still being a little verbose, this is a big improvement to the page-long instantation
lists shown above. The user gets the exact information of what was wrong with the provided
type, why it did not meet the required constraints, and where the error occured. With concept
suppport still being experimental, we expect error message to improve even more in the future.</p>
   <h2 class="heading settled" data-level="8" id="limiting-intermediate-value-conversions"><span class="secno">8. </span><span class="content">Limiting intermediate quantity value conversions</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#limiting-intermediate-value-conversions"></a></h2>
   <p>Many of the physical units libraries on the market decide to quietly convert different <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②①">units</a> to the one fixed, <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-derived-unit" id="ref-for-coherent-derived-unit③">coherent derived unit</a> of the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①②">dimension</a>. For example:</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">bu</c-> <c- o="">=</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- p="">;</c->

<c- k="">constexpr</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">velocity</c-><c- o="">&gt;</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&gt;</c-> <c- n="">d</c-><c- p="">,</c->
                                                   <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">time</c-><c- o="">&gt;</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>The code always (implicitly) converts incoming <code class="highlight"><c- n="">d</c-></code> length and <code class="highlight"><c- n="">t</c-></code> time arguments to the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①④">base units</a> of their <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①③">dimensions</a>. So if the user intends to write the code like:</p>
<pre class="language-cpp highlight"><c- k="">using</c-> <c- n="">kilometer_base_unit</c-> <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">make_scaled_unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- p="">,</c->
                                                 <c- n="">bu</c-><c- o="">::</c-><c- n="">scale</c-><c- o="">&lt;</c-><c- mi="">10</c-><c- p="">,</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">static_rational</c-><c- o="">&lt;</c-><c- mi="">3</c-><c- o="">&gt;&gt;&gt;::</c-><c- n="">type</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">length_kilometer</c->    <c- o="">=</c-> <c- n="">kilometer_base_unit</c-><c- o="">::</c-><c- n="">unit_type</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">time_hour</c->           <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">metric</c-><c- o="">::</c-><c- n="">hour_base_unit</c-><c- o="">::</c-><c- n="">unit_type</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">kilometers_per_hour</c-> <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">divide_typeof_helper</c-><c- o="">&lt;</c-><c- n="">length_kilometer</c-><c- p="">,</c-> <c- n="">time_hour</c-><c- o="">&gt;::</c-><c- n="">type</c-><c- p="">;</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">hours</c-><c- p="">,</c-> <c- n="">time_hour</c-><c- p="">);</c->

<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">220</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">kilo</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meters</c-><c- p="">),</c->
                         <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">time</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">2</c-> <c- o="">*</c-> <c- n="">hours</c-><c- p="">));</c->
<c- k="">const</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">velocity_kilometers_per_hour</c-><c- o="">&gt;</c-> <c- n="">kmph</c-><c- p="">(</c-><c- n="">v</c-><c- p="">);</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">kmph</c-><c- p="">.</c-><c- n="">value</c-><c- p="">()</c-> <c- o="">&lt;&lt;</c-> <c- s="">" km/h</c-><c- se="">\n</c-><c- s="">"</c-><c- p="">;</c->
</pre>
   <p>All the values provided as arguments are first converted to SI <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①⑤">base units</a> before the
function executes. After the function returns, the result is converted back to the same
units as provided by the user for the input arguments. These conversions can significantly
slow down the execution of a function, and lead to an increased loss of precision.</p>
   <p>For our example, three conversions have to be made. One to convert the length from <code class="highlight"><c- mi="">220</c-><c- n="">km</c-></code> to <code class="highlight"><c- mi="">220000</c-><c- n="">m</c-></code>, one to convert the time from <code class="highlight"><c- mi="">2</c-><c- n="">h</c-></code> to <code class="highlight"><c- mi="">7200</c-><c- n="">s</c-></code>, and one to convert the result
back from <code class="highlight"><c- mf="">30.5555</c-><c- p="">...</c-><c- n="">m</c-><c- o="">/</c-><c- n="">s</c-></code> to <code class="highlight"><c- mi="">110</c-><c- n="">km</c-><c- o="">/</c-><c- n="">s</c-></code>. Yet, when considering the units, no conversion
actually has to be made. Simply dividing <code class="highlight"><c- mi="">220</c-></code> by <code class="highlight"><c- mi="">2</c-></code> would suffice.</p>
   <p>Even for the case where the result is desired in another unit, the implementation loses on
performance and precision:</p>
<pre class="language-cpp highlight"><c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">220</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">kilo</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meters</c-><c- p="">),</c->
                         <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">time</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">2</c-> <c- o="">*</c-> <c- n="">hours</c-><c- p="">));</c->
<c- k="">const</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">miles_per_hour</c-><c- o="">&gt;</c-> <c- n="">mph</c-><c- p="">(</c-><c- n="">v</c-><c- p="">);</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">mph</c-><c- p="">.</c-><c- n="">value</c-><c- p="">()</c-> <c- o="">&lt;&lt;</c-> <c- s="">" mi/h</c-><c- se="">\n</c-><c- s="">"</c-><c- p="">;</c->
</pre>
   <p>Still three conversions are performed, whereas an optimal implementation would store the result
of <code class="highlight"><c- mi="">220</c-><c- n="">km</c-><c- o="">/</c-><c- mi="">2</c-><c- n="">h</c-></code> as <code class="highlight"><c- mi="">110</c-><c- n="">km</c-><c- o="">/</c-><c- n="">h</c-></code> without conversion and only convert <code class="highlight"><c- mi="">110</c-><c- n="">km</c-><c- o="">/</c-><c- n="">h</c-></code> to <code class="highlight"><c- mf="">68.35</c-><c- n="">mi</c-><c- o="">/</c-><c- n="">h</c-></code>.</p>
   <h3 class="heading settled" data-level="8.1" id="arguments-type-deduction"><span class="secno">8.1. </span><span class="content">Template arguments type deduction</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#arguments-type-deduction"></a></h3>
   <p>Above problem can be solved using function template argument deduction:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">LengthSystem</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Rep1</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">TimeSystem</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Rep2</c-><c- o="">&gt;</c->
<c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">length_dimension</c-><c- p="">,</c-> <c- n="">LengthSystem</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">Rep1</c-><c- o="">&gt;</c-> <c- n="">d</c-><c- p="">,</c->
                         <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">time_dimension</c-><c- p="">,</c-> <c- n="">TimeSystem</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">Rep2</c-><c- o="">&gt;</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>This allows us to put requirements on the parameter dimensions without limiting the units
allowed. Therefore no conversion before the function call is necessary, reducing conversion
overhead and precision loss.</p>
   <p>Yet, constraining the return value is a bigger problem. In C++17 it is possible to achieve
a constrained return value, but the syntax is not very pretty:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">LengthSystem</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Rep1</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">TimeSystem</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Rep2</c-><c- o="">&gt;</c->
<c- k="">constexpr</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">divide_typeof_helper</c-><c- o="">&lt;</c->
                                          <c- n="">bu</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">length_dimension</c-><c- p="">,</c-> <c- n="">LengthSystem</c-><c- o="">&gt;</c-><c- p="">,</c->
                                          <c- n="">bu</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">time_dimension</c-><c- p="">,</c-> <c- n="">TimeSystem</c-><c- o="">&gt;&gt;::</c-><c- n="">type</c-><c- o="">&gt;</c->
<c- n="">avg_speed</c-><c- p="">(</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">length_dimension</c-><c- p="">,</c-> <c- n="">LengthSystem</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">Rep1</c-><c- o="">&gt;</c-> <c- n="">d</c-><c- p="">,</c->
          <c- n="">bu</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">time_dimension</c-><c- p="">,</c-> <c- n="">TimeSystem</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">Rep2</c-><c- o="">&gt;</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>What is more, the user has to manually reimplement dimensional analysis logic in template
metaprogramming land, not actually using the units library which should provide such a
functionality.</p>
   <p>It is worth noting, that for some libraries we cannot even address the first step for the
function template arguments. In the case of <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-nic_units">[NIC_UNITS]</a> <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-unit" id="ref-for-derived-unit①">derived units</a> are implemented
in terms of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①⑥">base units</a>:</p>
<pre class="language-cpp highlight"><c- k="">using</c-> <c- n="">meter_t</c->     <c- o="">=</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">unit_t</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">category</c-><c- o="">::</c-><c- n="">length_unit</c-><c- o="">&gt;&gt;</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">kilometer_t</c-> <c- o="">=</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">unit_t</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">1000</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">meter_t</c-><c- o="">&gt;</c-><c- p="">,</c->
                                  <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-><c- p="">,</c->
                                  <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">0</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;&gt;&gt;</c-><c- p="">;</c->
</pre>
   <p>This makes it impossible to know upfront where <code class="highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">category</c-><c- o="">::</c-><c- n="">length_unit</c-></code> will exist
in a class template instantiation.</p>
   <h3 class="heading settled" data-level="8.2" id="generic-programming-with-concepts"><span class="secno">8.2. </span><span class="content">Generic programming with concepts</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#generic-programming-with-concepts"></a></h3>
   <p>The answer to constraining templates is again C++20 concepts. With their help the above
function can be implemented as:</p>
<pre class="language-cpp highlight"><c- k="">constexpr</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Length</c-> <c- k="">auto</c-> <c- n="">d</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Time</c-> <c- k="">auto</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>This gives us the benefit of:</p>
   <ul>
    <li data-md="">
     <p>working on the user-provided units and values without any intermediate conversions,</p>
    </li><li data-md="">
     <p>better error logs (as described in <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#better-errors-with-concepts">§ 7.4 Better errors with C++20 concepts</a>),</p>
    </li><li data-md="">
     <p>function template parameter constraints clearly expressed in the function template signature,</p>
    </li><li data-md="">
     <p>possibility to constrain not only the function arguments but also its return type without
the need to reimplement the body of the function in a template metaprogramming dialect.</p>
   </li></ul>
   <p>With such an approach, the resulting binary generated by the compiler is the same fast
(or sometimes even faster) than the one generated for direct usage of fundamental types.</p>
   <p>Additionally, concept usage relieves us from the need to implement a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①④">system of quantities</a>,
which in other libraries needs to be defined to fix a custom base unit to a specific dimension.
In these libraries, defining such a unit system is a workaround for constraining template
function parameters and limiting the number of intermediate conversions.</p>
   <p>Futhermore it needs to be emphasized, that C++20 concepts are useful not only to constrain
function template arguments and their return value but can also be used to constrain the types
of user variables:</p>
<pre class="language-cpp highlight"><c- k="">const</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">speed</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mf="">220.</c-><c- n="">km</c-><c- p="">,</c-> <c- mf="">2.</c-><c- n="">h</c-><c- p="">);</c->
</pre>
   <p>If for some reason the function <code class="highlight"><c- n="">avg_speed</c-></code> would no longer return a velocity, the error would
be shown clearly by the compiler, a feature which cannot be provided by C++17 template
metaprogramming.</p>
   <h2 class="heading settled" data-level="9" id="ratio-on-steroids"><span class="secno">9. </span><span class="content"><code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-></code> on steroids</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ratio-on-steroids"></a></h2>
   <p>Some of the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-unit" id="ref-for-derived-unit②">derived units</a> have really <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#multiple-of-a-unit" id="ref-for-multiple-of-a-unit①">big</a> or <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#submultiple-of-a-unit" id="ref-for-submultiple-of-a-unit①">small</a> ratios. The difference from the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①⑦">base units</a> is so huge
that it cannot be expressed with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-></code>, which is implemented in terms of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-></code>.</p>
   <p>This makes it really hard to express units like electronvolt (eV) where
1eV = 1.602176634×10<sup>−19</sup> J or Dalton where
1 Da = 1.660539040(20)×10<sup>−27</sup> kg.
Although a custom <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①⑤">system of quantities</a> could be a solution, it would only be a workaround
as it cannot provide seamless conversion between all possible units.</p>
   <p>A better, more flexible solution is needed. One of the possiblities might be to redefine
ratio with one additional parameter:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">Num</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">Den</c-> <c- o="">=</c-> <c- mi="">1</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">Exp</c-> <c- o="">=</c-> <c- mi="">0</c-><c- o="">&gt;</c->
    <c- n="">requires</c-> <c- p="">(</c-><c- n="">Den</c-> <c- o="">!=</c-> <c- mi="">0</c-><c- p="">)</c->
<c- k="">struct</c-> <c- n="">new_ratio</c-><c- p="">;</c->
</pre>
   <p>With such an approach it will be possible to easily address any occuring ratio with a required
precision. For example, the conversion rate between one electronvolt and one Joule could be
expressed as:</p>
<pre class="language-cpp highlight"><c- n="">new_ratio</c-><c- o="">&lt;</c-><c- mi="">1602176634</c-><c- p="">,</c-> <c- mi="">1000000000</c-><c- p="">,</c-> <c- o="">-</c-><c- mi="">19</c-><c- o="">&gt;</c->
</pre>
   <h2 class="heading settled" data-level="10" id="extensibility"><span class="secno">10. </span><span class="content">Extensibility</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#extensibility"></a></h2>
   <p>The units library should be designed in a way that allows users to easily extend it with
their own units, derived, or even base dimensions. The C++ Standard Library will most likely
decide to ship with a support for "just" physical units with possible extension to digital
information dimensions and their units. This should not limit users to the units and
quantities provided by library engine, but address all their needs in their specific domains.</p>
   <p>The most important points that have to be provided by such C++ Standard library engine in
order to provide good extensibility are:</p>
   <ul>
    <li data-md="">
     <p>The library has to be extendible with new <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②②">units</a>, <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-quantity" id="ref-for-derived-quantity⑤">derived</a>, and <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity①⓪">base quantities</a>, interacting with the existing ones.</p>
    </li><li data-md="">
     <p>The user-defined entities have to provide the same user experience as built-in ones.</p>
    </li><li data-md="">
     <p>Extension shall be possible without preprocessor macros in the user interface.</p>
    </li><li data-md="">
     <p>Extensions to the C++ Standard library engine created by two independent vendors shall
not collide with each other as long as they address separate domains.</p>
   </li></ul>
   <h2 class="heading settled" data-level="11" id="easy-to-use-hard-to-abuse"><span class="secno">11. </span><span class="content">Easy to use and hard to abuse</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#easy-to-use-hard-to-abuse"></a></h2>
   <p>Users complain about the complexity of existing solutions. For example, Boost.Units users
have to:</p>
   <ul>
    <li data-md="">
     <p>include a lot of specific header files,</p>
    </li><li data-md="">
     <p>define a lot of types by themselves (see <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#limiting-intermediate-value-conversions">§ 8 Limiting intermediate quantity value conversions</a>),</p>
    </li><li data-md="">
     <p>fight with compilation errors (see <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#user-experience">§ 7 Improving user experience</a>) and debugging,</p>
    </li><li data-md="">
     <p>define custom <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①⑥">systems</a> to workaround intermediate conversions issues (see <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#generic-programming-with-concepts">§ 8.2 Generic programming with concepts</a> and <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ratio-on-steroids">§ 9 std::ratio on steroids</a>)</p>
    </li><li data-md="">
     <p>learn lots of library specific behaviors and their side effects (i.e. lack of implicit
conversions between units even when it is provable in compile time that such a
translation is non-truncating like km -&gt; m),</p>
   </li></ul>
   <p>Most of those issues can be solved during the design time. We should strive to provide:</p>
   <ol>
    <li data-md="">
     <p>Behavior similar to <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-></code> as it proved to be a good design and the user base already
got used to that.</p>
    </li><li data-md="">
     <p>Clear responsibility of each type (base_dimension -&gt; exp -&gt; dimension -&gt; unit -&gt; quantity).</p>
    </li><li data-md="">
     <p>Ease to extend with custom dimensions or units.</p>
    </li><li data-md="">
     <p>Ease to understand error messages and a good debugging experience thanks to downcast
facility and concepts.</p>
    </li><li data-md="">
     <p>No dedicated abstraction for <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①⑦">systems</a> that would complicate implementation and reasoning
about the library engine and functionality (at least until future users will not provide
solid requirements and use cases for such an entity).</p>
    </li><li data-md="">
     <p>A basic set of prefixes, units, quantities, constants, and concepts.</p>
   </li></ol>
   <h2 class="heading settled" data-level="12" id="design-principles"><span class="secno">12. </span><span class="content">Design principles</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#design-principles"></a></h2>
   <p>The basic design principles that should be used to implement a physical units library
for C++ are:</p>
   <ol>
    <li data-md="">
     <p>Safety and performance:</p>
     <ul>
      <li data-md="">
       <p>strong types</p>
      </li><li data-md="">
       <p>only safe implicit conversions should be allowed</p>
      </li><li data-md="">
       <p>compile-time safety and verification wherever possible (break at compile time, not at
runtime)</p>
      </li><li data-md="">
       <p>constexpr all the things</p>
      </li><li data-md="">
       <p>as fast or even faster than working with fundamental types</p>
     </li></ul>
    </li><li data-md="">
     <p>The best possible user experience:</p>
     <ul>
      <li data-md="">
       <p>interfaces embraced with clear concepts and contracts</p>
      </li><li data-md="">
       <p>user friendly compiler errors</p>
      </li><li data-md="">
       <p>good debugging experience</p>
     </li></ul>
    </li><li data-md="">
     <p>No macros in the user interface.</p>
    </li><li data-md="">
     <p>Easy extensibility.</p>
    </li><li data-md="">
     <p>No external dependencies.</p>
    </li><li data-md="">
     <p>Possibility to be standardized as a freestanding part of the C++ Standard Library.</p>
    </li><li data-md="">
     <p>Batteries included:</p>
     <ul>
      <li data-md="">
       <p>provide basic prefixes, units, quantities, constants, and concepts</p>
      </li><li data-md="">
       <p>non-experts should easily be able to achieve simple calculations</p>
     </li></ul>
   </li></ol>
   <h2 class="heading settled" data-level="13" id="open-questions"><span class="secno">13. </span><span class="content">Open questions</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#open-questions"></a></h2>
   <h3 class="heading settled" data-level="13.1" id="prefixes-and-units"><span class="secno">13.1. </span><span class="content">How to represent SI prefixes and derived units?</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#prefixes-and-units"></a></h3>
   <p>There are at least 3 ways to represent derived units:</p>
   <ol>
    <li data-md="">
     <p>Provide a new strong type and an UDL for each unit</p>
    </li><li data-md="">
     <p>Define the type only for a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-derived-unit" id="ref-for-coherent-derived-unit④">coherent derived unit</a> and use multiplier syntax to obtain
more <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-unit" id="ref-for-derived-unit③">derived units</a></p>
    </li><li data-md="">
     <p>Mixed approach using strong types, NTTPs, and variable templates</p>
   </li></ol>
   <p>Starting with the first case. Each <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-unit" id="ref-for-derived-unit④">derived unit</a> gets its own type and an UDL. With such
an approach we can easily write:</p>
<pre class="language-cpp highlight"><c- k="">using</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">literals</c-><c- p="">;</c->

<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d1</c-> <c- o="">=</c-> <c- mi="">123</c-><c- n="">km</c-><c- p="">;</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d2</c-> <c- o="">=</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">kilometre</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->

<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v1</c-> <c- o="">=</c-> <c- mi="">123</c-><c- n="">kmph</c-><c- p="">;</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v2</c-> <c- o="">=</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">kilometre_per_hour</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
</pre>
   <p>The good parts here are:</p>
   <ul>
    <li data-md="">
     <p>clear, strong types for each defined unit</p>
    </li><li data-md="">
     <p>support for such a unit by the downcasting facility</p>
    </li><li data-md="">
     <p>existence of an UDL</p>
   </li></ul>
   <p>The drawbacks of such a solution are:</p>
   <ul>
    <li data-md="">
     <p>as library framework will probably not predefine all possible variations of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①⑧">base units</a> and their <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#multiple-of-a-unit" id="ref-for-multiple-of-a-unit②">prefixes</a> (i.e gigametre_per_second) the user will have
to define every such a unit before the first use</p>
    </li><li data-md="">
     <p>the same as above applies to UDLs</p>
    </li><li data-md="">
     <p>only one unit spelling form (<code class="highlight"><c- n="">meter</c-></code> vs. <code class="highlight"><c- n="">meters</c-></code> vs. <code class="highlight"><c- n="">metre</c-></code> vs. <code class="highlight"><c- n="">metres</c-></code>) supported</p>
    </li><li data-md="">
     <p>naming of some units can become clunky (i.e. <code class="highlight"><c- n="">sq_volt_per_hertz</c-></code>)</p>
   </li></ul>
   <p>The second case assumes that each dimension will get only a predefined <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-derived-unit" id="ref-for-coherent-derived-unit⑤">coherent derived unit</a> and the rest of the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-unit" id="ref-for-derived-unit⑤">derived units</a> will be either created with
a multiplier syntax or defined by the user:</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">bu</c-> <c- o="">=</c-> <c- n="">boost</c-><c- o="">::</c-><c- n="">units</c-><c- p="">;</c->

<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d1</c-> <c- o="">=</c-> <c- mi="">123</c-><c- n="">k</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meters</c-><c- p="">;</c->  <c- c1="">// no an actual Boost.Units syntax</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d2</c-> <c- o="">=</c-> <c- mi="">123</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">kilo</c-> <c- o="">*</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">meters</c-><c- p="">;</c->

<c- k="">using</c-> <c- n="">kilometer_base_unit</c-> <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">make_scaled_unit</c-><c- o="">&lt;</c-><c- n="">bu</c-><c- o="">::</c-><c- n="">si</c-><c- o="">::</c-><c- n="">length</c-><c- p="">,</c->
                                                 <c- n="">bu</c-><c- o="">::</c-><c- n="">scale</c-><c- o="">&lt;</c-><c- mi="">10</c-><c- p="">,</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">static_rational</c-><c- o="">&lt;</c-><c- mi="">3</c-><c- o="">&gt;&gt;&gt;::</c-><c- n="">type</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">length_kilometer</c-> <c- o="">=</c-> <c- n="">kilometer_base_unit</c-><c- o="">::</c-><c- n="">unit_type</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">time_hour</c-> <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">metric</c-><c- o="">::</c-><c- n="">hour_base_unit</c-><c- o="">::</c-><c- n="">unit_type</c-><c- p="">;</c->
<c- k="">using</c-> <c- n="">velocity_kilometers_per_hour</c-> <c- o="">=</c-> <c- n="">bu</c-><c- o="">::</c-><c- n="">divide_typeof_helper</c-><c- o="">&lt;</c-><c- n="">length_kilometer</c-><c- p="">,</c-> <c- n="">time_hour</c-><c- o="">&gt;::</c-><c- n="">type</c-><c- p="">;</c->
<c- n="">BOOST_UNITS_STATIC_CONSTANT</c-><c- p="">(</c-><c- n="">kilometers_per_hour</c-><c- p="">,</c-> <c- n="">velocity_kilometers_per_hour</c-><c- p="">);</c->

<c- c1="">// const auto v1 = ???</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v2</c-> <c- o="">=</c-> <c- mi="">123</c-> <c- o="">*</c-> <c- n="">kilometers_per_hour</c-><c- p="">;</c->
</pre>
   <p>The good parts here are:</p>
   <ul>
    <li data-md="">
     <p>multiple possible spellings of unit names</p>
    </li><li data-md="">
     <p>easy to use existing <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-derived-unit" id="ref-for-coherent-derived-unit⑥">coherent derived units</a> with all SI prefixes</p>
   </li></ul>
   <p>The drawbacks of such a solution are:</p>
   <ul>
    <li data-md="">
     <p>verbose UDLs</p>
    </li><li data-md="">
     <p>no support by the downcasting facility</p>
    </li><li data-md="">
     <p>user has to make a significant effort to create new <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-unit" id="ref-for-derived-unit⑥">derived units</a> that are not easily
constructible with SI prefixes (i.e. kilometre)</p>
   </li></ul>
   <p>The third approach is using a mix of several language features including strong types,
Non Type Template Parameters (NTTP), and UDLs. With such an approach we can end up with a
variety of syntaxes. Please note that the long list below is only to list all of
the possibilities in this design space and we do not propose anything like this for now.
We can easily forbid any or all of the following syntaxes:</p>
<pre class="language-cpp highlight"><c- kr="">inline</c-> <c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">kilometre</c-> <c- o="">=</c-> <c- n="">kilo</c-><c- o="">*</c-><c- n="">metre</c-><c- p="">;</c->
<c- kr="">inline</c-> <c- k="">constexpr</c-> <c- k="">auto</c-> <c- n="">km</c-> <c- o="">=</c-> <c- n="">kilometre</c-><c- p="">;</c->

<c- k="">namespace</c-> <c- n="">literals</c-> <c- p="">{</c->
  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-> <c- s="">""</c-><c- n="">km</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">km</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-> <c- s="">""</c-><c- n="">km</c-><c- p="">(</c-><c- b="">long</c-> <c- b="">double</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">km</c-><c- p="">,</c-> <c- b="">long</c-> <c- b="">double</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
<c- p="">}</c->

<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d1</c->  <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">kilo</c-><c- o="">*</c-><c- n="">metre</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d2</c->  <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">kilometre</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d3</c->  <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">k</c-><c- o="">*</c-><c- n="">metre</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d4</c->  <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">k</c-><c- o="">*</c-><c- n="">m</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d5</c->  <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">km</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d6</c->  <c- o="">=</c-> <c- n="">kilo</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">)</c-><c- o="">*</c-><c- n="">metre</c-><c- p="">;</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d7</c->  <c- o="">=</c-> <c- n="">kilometre</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d8</c->  <c- o="">=</c-> <c- n="">kilo</c-><c- o="">*</c-><c- n="">metre</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d9</c->  <c- o="">=</c-> <c- n="">kilometre</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d10</c-> <c- o="">=</c-> <c- mi="">1000</c-><c- o="">*</c-><c- n="">metre</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d11</c-> <c- o="">=</c-> <c- n="">metre</c-><c- p="">(</c-><c- mi="">123</c->’<c- mo="">000</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d12</c-> <c- o="">=</c-> <c- mi="">123</c-><c- n="">k</c-><c- o="">*</c-><c- n="">m</c-><c- p="">;</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d13</c-> <c- o="">=</c-> <c- mi="">123</c-><c- n="">km</c-><c- p="">;</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d14</c-> <c- o="">=</c-> <c- n="">k</c-><c- o="">*</c-><c- mi="">123</c-><c- n="">m</c-><c- p="">;</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d15</c-> <c- o="">=</c-> <c- mi="">123</c-><c- n="">kilo</c-><c- o="">*</c-><c- n="">metres</c-><c- p="">;</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">d16</c-> <c- o="">=</c-> <c- p="">(</c-><c- n="">km</c-><c- p="">)(</c-><c- mi="">123</c-><c- p="">);</c->

<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v1</c->  <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">kilo</c-><c- o="">*</c-><c- n="">metre</c-><c- o="">/</c-><c- n="">hour</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v2</c->  <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">kilometre</c-><c- o="">/</c-><c- n="">hour</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v3</c->  <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">k</c-><c- o="">*</c-><c- n="">m</c-><c- o="">/</c-><c- n="">h</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v4</c->  <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">km</c-><c- o="">/</c-><c- n="">h</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v5</c->  <c- o="">=</c-> <c- n="">kilo</c-> <c- o="">*</c-> <c- n="">metre</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">)</c-> <c- o="">/</c-> <c- n="">hour</c-><c- p="">(</c-><c- mi="">1</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v6</c->  <c- o="">=</c-> <c- n="">kilo</c-> <c- o="">*</c-> <c- n="">metre</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">)</c-> <c- o="">/</c-> <c- n="">hour</c-><c- p="">();</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v7</c->  <c- o="">=</c-> <c- n="">kilometre</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">)</c-> <c- o="">/</c-> <c- n="">hour</c-><c- p="">;</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v8</c->  <c- o="">=</c-> <c- n="">k</c-><c- o="">*</c-><c- n="">m</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">)</c-><c- o="">/</c-><c- n="">h</c-><c- p="">;</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v9</c->  <c- o="">=</c-> <c- n="">km</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">)</c-><c- o="">/</c-><c- n="">h</c-><c- p="">;</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v10</c-> <c- o="">=</c-> <c- p="">(</c-><c- n="">km</c-><c- o="">/</c-><c- n="">h</c-><c- p="">)(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">const</c-> <c- k="">auto</c-> <c- n="">v11</c-> <c- o="">=</c-> <c- mi="">123</c-><c- n="">km</c-><c- o="">/</c-><c- n="">h</c-><c- p="">;</c->
</pre>
   <p>All of the above variables for length and velocity are respectively of the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②③">unit</a> and
contain the same value.</p>
   <p>The good parts here are:</p>
   <ul>
    <li data-md="">
     <p>library has to implement only base named units</p>
    </li><li data-md="">
     <p>
      natural syntax of spelling units (i.e. 123km/h or quantity
      <kilometre hour="">(123))</kilometre>
     </p>
    </li><li data-md="">
     <p>user is able to easily construct any possible variation of base units without any additional
library support</p>
    </li><li data-md="">
     <p>multiple possible spellings of unit names</p>
   </li></ul>
   <p>The drawbacks of such a solution are:</p>
   <ul>
    <li data-md="">
     <p>"there is more than one way to do it" problem</p>
    </li><li data-md="">
     <p>the code written by the developer will not be similar to the types printed in the compilation
error logs</p>
    </li><li data-md="">
     <p>no support for such a unit by the downcasting facility (units are values instead of types)</p>
   </li></ul>
   <p>Please note that 2nd and 3rd case may look tempting because nice examples where used. It can
get worse for a lot of <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①④">dimensions</a>:</p>
   <ul>
    <li data-md="">
     <p>volume (<code class="highlight"><c- mi="">3</c-> <c- o="">*</c-> <c- n="">m</c-> <c- o="">*</c-> <c- n="">m</c-> <c- o="">*</c-> <c- n="">m</c-></code>, <code class="highlight"><c- mi="">3</c-> <c- o="">*</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">metre</c-> <c- o="">*</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">metre</c-> <c- o="">*</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">metre</c-></code>)</p>
    </li><li data-md="">
     <p>acceleration (<code class="highlight"><c- mi="">10</c-> <c- o="">*</c-> <c- n="">m</c-> <c- o="">/</c-> <c- n="">s</c-> <c- o="">/</c-> <c- n="">s</c-></code>, <code class="highlight"><c- mi="">3</c-> <c- o="">*</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">metre</c-> <c- o="">/</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">second</c-> <c- o="">/</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">second</c-></code>)</p>
   </li></ul>
   <p>while the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①⑤">dimensions</a> with the first approach looks as follows:</p>
   <ul>
    <li data-md="">
     <p>volume (<code class="highlight"><c- mi="">3</c-><c- n="">cub_m</c-></code>, <code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">cubic_metre</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">3</c-><c- p="">)</c-></code>)</p>
    </li><li data-md="">
     <p>acceleration (<code class="highlight"><c- mi="">10</c-><c- n="">mps_sq</c-></code>, <code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">metre_per_second_sq</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">3</c-><c- p="">)</c-></code>)</p>
   </li></ul>
   <p>and provide dowcasting support at the same time which will provide exactly the same experience
for the end user in a compilation log or the compiler to the one that developer has while
implementing the library code.</p>
   <h3 class="heading settled" data-level="13.2" id="nttp-usage"><span class="secno">13.2. </span><span class="content">NTTP usage</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nttp-usage"></a></h3>
   <p>There are a few points in the physical units domain design that could benefit from Non-Type
Template Parameters usage. One of the most apparent cases here is <code class="highlight"><c- n="">ratio</c-></code>. A classical
implementation of such a class template looks like this:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- b="">intmax_t</c-> <c- n="">Num</c-><c- p="">,</c-> <c- b="">intmax_t</c-> <c- n="">Den</c-> <c- o="">=</c-> <c- mi="">1</c-><c- o="">&gt;</c->
<c- k="">struct</c-> <c- n="">ratio</c-> <c- p="">{</c->
  <c- k="">static</c-> <c- k="">constexpr</c-> <c- b="">intmax_t</c-> <c- n="">num</c-> <c- o="">=</c-> <c- n="">Num</c-> <c- o="">*</c-> <c- n="">static_sign</c-><c- o="">&lt;</c-><c- n="">Den</c-><c- o="">&gt;::</c-><c- n="">value</c-> <c- o="">/</c-> <c- n="">static_gcd</c-><c- o="">&lt;</c-><c- n="">Num</c-><c- p="">,</c-> <c- n="">Den</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- p="">;</c->
  <c- k="">static</c-> <c- k="">constexpr</c-> <c- b="">intmax_t</c-> <c- n="">den</c-> <c- o="">=</c-> <c- n="">static_abs</c-><c- o="">&lt;</c-><c- n="">Den</c-><c- o="">&gt;::</c-><c- n="">value</c-> <c- o="">/</c-> <c- n="">static_gcd</c-><c- o="">&lt;</c-><c- n="">Num</c-><c- p="">,</c-> <c- n="">Den</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- p="">;</c->
  <c- k="">using</c-> <c- n="">type</c-> <c- o="">=</c-> <c- n="">ratio</c-><c- o="">&lt;</c-><c- n="">num</c-><c- p="">,</c-> <c- n="">den</c-><c- o="">&gt;</c-><c- p="">;</c->
<c- p="">};</c->
</pre>
   <p>Besides, it provides a few utilities to do operations on such types:</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">detail</c-> <c- p="">{</c->
  <c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">R1</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">R2</c-><c- o="">&gt;</c->
  <c- k="">struct</c-> <c- n="">ratio_multiply_impl</c-> <c- p="">{</c->
  <c- k="">private</c-><c- o="">:</c->
    <c- k="">static</c-> <c- k="">constexpr</c-> <c- b="">intmax_t</c-> <c- n="">gcd1</c-> <c- o="">=</c-> <c- n="">static_gcd</c-><c- o="">&lt;</c-><c- n="">R1</c-><c- o="">::</c-><c- n="">num</c-><c- p="">,</c-> <c- n="">R2</c-><c- o="">::</c-><c- n="">den</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- p="">;</c->
    <c- k="">static</c-> <c- k="">constexpr</c-> <c- b="">intmax_t</c-> <c- n="">gcd2</c-> <c- o="">=</c-> <c- n="">static_gcd</c-><c- o="">&lt;</c-><c- n="">R2</c-><c- o="">::</c-><c- n="">num</c-><c- p="">,</c-> <c- n="">R1</c-><c- o="">::</c-><c- n="">den</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- p="">;</c->
  <c- k="">public</c-><c- o="">:</c->
    <c- k="">using</c-> <c- n="">type</c-> <c- o="">=</c-> <c- n="">ratio</c-><c- o="">&lt;</c-><c- n="">safe_multiply</c-><c- o="">&lt;</c-><c- p="">(</c-><c- n="">R1</c-><c- o="">::</c-><c- n="">num</c-> <c- o="">/</c-> <c- n="">gcd1</c-><c- p="">),</c-> <c- p="">(</c-><c- n="">R2</c-><c- o="">::</c-><c- n="">num</c-> <c- o="">/</c-> <c- n="">gcd2</c-><c- p="">)</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- p="">,</c->
                       <c- n="">safe_multiply</c-><c- o="">&lt;</c-><c- p="">(</c-><c- n="">R1</c-><c- o="">::</c-><c- n="">den</c-> <c- o="">/</c-> <c- n="">gcd2</c-><c- p="">),</c-> <c- p="">(</c-><c- n="">R2</c-><c- o="">::</c-><c- n="">den</c-> <c- o="">/</c-> <c- n="">gcd1</c-><c- p="">)</c-><c- o="">&gt;::</c-><c- n="">value</c-><c- o="">&gt;</c-><c- p="">;</c->
    <c- k="">static</c-> <c- k="">constexpr</c-> <c- b="">intmax_t</c-> <c- n="">num</c-> <c- o="">=</c-> <c- n="">type</c-><c- o="">::</c-><c- n="">num</c-><c- p="">;</c->
    <c- k="">static</c-> <c- k="">constexpr</c-> <c- b="">intmax_t</c-> <c- n="">den</c-> <c- o="">=</c-> <c- n="">type</c-><c- o="">::</c-><c- n="">den</c-><c- p="">;</c->
  <c- p="">};</c->
<c- p="">}</c->
<c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">R1</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">R2</c-><c- o="">&gt;</c->
<c- k="">using</c-> <c- n="">ratio_multiply</c-> <c- o="">=</c-> <c- n="">detail</c-><c- o="">::</c-><c- n="">ratio_multiply_impl</c-><c- o="">&lt;</c-><c- n="">R1</c-><c- p="">,</c-> <c- n="">R2</c-><c- o="">&gt;::</c-><c- n="">type</c-><c- p="">;</c->
</pre>
   <p>Usage examples of such an approach looks as follows:</p>
<pre class="language-cpp highlight"><c- k="">struct</c-> <c- nl="">yard</c-> <c- p="">:</c-> <c- n="">derived_unit</c-><c- o="">&lt;</c-><c- n="">yard</c-><c- p="">,</c-> <c- s="">"yd"</c-><c- p="">,</c-> <c- n="">length</c-><c- p="">,</c-> <c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">9</c->’<c- mi="">144</c-><c- p="">,</c-> <c- mi="">10</c->’<c- mo="">000</c-><c- o="">&gt;&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">foot</c-> <c- p="">:</c-> <c- n="">derived_unit</c-><c- o="">&lt;</c-><c- n="">foot</c-><c- p="">,</c-> <c- s="">"ft"</c-><c- p="">,</c-> <c- n="">length</c-><c- p="">,</c-> <c- n="">ratio_multiply</c-><c- o="">&lt;</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- p="">,</c-> <c- mi="">3</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">yard</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&gt;&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">inch</c-> <c- p="">:</c-> <c- n="">derived_unit</c-><c- o="">&lt;</c-><c- n="">inch</c-><c- p="">,</c-> <c- s="">"in"</c-><c- p="">,</c-> <c- n="">length</c-><c- p="">,</c-> <c- n="">ratio_multiply</c-><c- o="">&lt;</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">1</c-><c- p="">,</c-> <c- mi="">12</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">foot</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&gt;&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">mile</c-> <c- p="">:</c-> <c- n="">derived_unit</c-><c- o="">&lt;</c-><c- n="">mile</c-><c- p="">,</c-> <c- s="">"mi"</c-><c- p="">,</c-> <c- n="">length</c-><c- p="">,</c-> <c- n="">ratio_multiply</c-><c- o="">&lt;</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">1</c->’<c- mi="">760</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">yard</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&gt;&gt;</c-> <c- p="">{};</c->
</pre>
   <p>With NTTP the implementation and usage of the <code class="highlight"><c- n="">ratio</c-></code> are much easier:</p>
<pre class="language-cpp highlight"><c- k="">struct</c-> <c- n="">ratio</c-> <c- p="">{</c->
  <c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">num</c-><c- p="">;</c->
  <c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">den</c-><c- p="">;</c->

  <c- k="">explicit</c-> <c- k="">constexpr</c-> <c- nf="">ratio</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">n</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">d</c-> <c- o="">=</c-> <c- mi="">1</c-><c- p="">)</c-> <c- o="">:</c->
    <c- n="">num</c-><c- p="">(</c-><c- n="">n</c-> <c- o="">*</c-> <c- p="">(</c-><c- n="">d</c-> <c- o="">&lt;</c-> <c- mi="">0</c-> <c- o="">?</c-> <c- o="">-</c-><c- mi="">1</c-> <c- o="">:</c-> <c- mi="">1</c-><c- p="">)</c-> <c- o="">/</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">gcd</c-><c- p="">(</c-><c- n="">n</c-><c- p="">,</c-> <c- n="">d</c-><c- p="">)),</c->
    <c- n="">den</c-><c- p="">(</c-><c- n="">abs</c-><c- p="">(</c-><c- n="">d</c-><c- p="">)</c-> <c- o="">/</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">gcd</c-><c- p="">(</c-><c- n="">n</c-><c- p="">,</c-> <c- n="">d</c-><c- p="">))</c->
  <c- p="">{</c->
  <c- p="">}</c->

  <c- p="">[[</c-><c- n="">nodiscard</c-><c- p="">]]</c-> <c- k="">constexpr</c-> <c- b="">bool</c-> <c- k="">operator</c-><c- o="">==</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">ratio</c-><c- o="">&amp;</c-><c- p="">)</c-> <c- o="">=</c-> <c- k="">default</c-><c- p="">;</c->

  <c- p="">[[</c-><c- n="">nodiscard</c-><c- p="">]]</c-> <c- k="">friend</c-> <c- k="">constexpr</c-> <c- n="">ratio</c-> <c- k="">operator</c-><c- o="">*</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">ratio</c-><c- o="">&amp;</c-> <c- n="">lhs</c-><c- p="">,</c-> <c- k="">const</c-> <c- n="">ratio</c-><c- o="">&amp;</c-> <c- n="">rhs</c-><c- p="">)</c->
  <c- p="">{</c->
    <c- k="">const</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">gcd1</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">gcd</c-><c- p="">(</c-><c- n="">lhs</c-><c- p="">.</c-><c- n="">num</c-><c- p="">,</c-> <c- n="">rhs</c-><c- p="">.</c-><c- n="">den</c-><c- p="">);</c->
    <c- k="">const</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">gcd2</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">gcd</c-><c- p="">(</c-><c- n="">rhs</c-><c- p="">.</c-><c- n="">num</c-><c- p="">,</c-> <c- n="">lhs</c-><c- p="">.</c-><c- n="">den</c-><c- p="">);</c->
    <c- k="">return</c-> <c- nf="">ratio</c-><c- p="">(</c-><c- n="">safe_multiply</c-><c- p="">(</c-><c- n="">lhs</c-><c- p="">.</c-><c- n="">num</c-> <c- o="">/</c-> <c- n="">gcd1</c-><c- p="">,</c-> <c- n="">rhs</c-><c- p="">.</c-><c- n="">num</c-> <c- o="">/</c-> <c- n="">gcd2</c-><c- p="">),</c->
                 <c- n="">safe_multiply</c-><c- p="">(</c-><c- n="">lhs</c-><c- p="">.</c-><c- n="">den</c-> <c- o="">/</c-> <c- n="">gcd2</c-><c- p="">,</c-> <c- n="">rhs</c-><c- p="">.</c-><c- n="">den</c-> <c- o="">/</c-> <c- n="">gcd1</c-><c- p="">));</c->
  <c- p="">}</c->

  <c- p="">[[</c-><c- n="">nodiscard</c-><c- p="">]]</c-> <c- k="">friend</c-> <c- k="">constexpr</c-> <c- n="">ratio</c-> <c- k="">operator</c-><c- o="">*</c-><c- p="">(</c-><c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">n</c-><c- p="">,</c-> <c- k="">const</c-> <c- n="">ratio</c-><c- o="">&amp;</c-> <c- n="">rhs</c-><c- p="">)</c->
  <c- p="">{</c->
    <c- k="">return</c-> <c- n="">ratio</c-><c- p="">(</c-><c- n="">n</c-><c- p="">)</c-> <c- o="">*</c-> <c- n="">rhs</c-><c- p="">;</c->
  <c- p="">}</c->

  <c- p="">[[</c-><c- n="">nodiscard</c-><c- p="">]]</c-> <c- k="">friend</c-> <c- k="">constexpr</c-> <c- n="">ratio</c-> <c- k="">operator</c-><c- o="">*</c-><c- p="">(</c-><c- k="">const</c-> <c- n="">ratio</c-><c- o="">&amp;</c-> <c- n="">lhs</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">intmax_t</c-> <c- n="">n</c-><c- p="">)</c->
  <c- p="">{</c->
    <c- k="">return</c-> <c- n="">lhs</c-> <c- o="">*</c-> <c- n="">ratio</c-><c- p="">(</c-><c- n="">n</c-><c- p="">);</c->
  <c- p="">}</c->
<c- p="">};</c->
</pre>
<pre class="language-cpp highlight"><c- c1="">// US customary units</c->
<c- k="">struct</c-> <c- nl="">yard</c-> <c- p="">:</c-> <c- n="">derived_unit</c-><c- o="">&lt;</c-><c- n="">yard</c-><c- p="">,</c-> <c- s="">"yd"</c-><c- p="">,</c-> <c- n="">length</c-><c- p="">,</c-> <c- n="">ratio</c-><c- p="">(</c-><c- mi="">9</c->’<c- mi="">144</c-><c- p="">,</c-> <c- mi="">10</c->’<c- mo="">000</c-><c- p="">)</c-><c- o="">&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">foot</c-> <c- p="">:</c-> <c- n="">derived_unit</c-><c- o="">&lt;</c-><c- n="">foot</c-><c- p="">,</c-> <c- s="">"ft"</c-><c- p="">,</c-> <c- n="">length</c-><c- p="">,</c-> <c- n="">yard</c-><c- o="">::</c-><c- n="">ratio</c-> <c- o="">/</c-> <c- mi="">3</c-><c- o="">&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">inch</c-> <c- p="">:</c-> <c- n="">derived_unit</c-><c- o="">&lt;</c-><c- n="">inch</c-><c- p="">,</c-> <c- s="">"in"</c-><c- p="">,</c-> <c- n="">length</c-><c- p="">,</c-> <c- n="">foot</c-><c- o="">::</c-><c- n="">ratio</c-> <c- o="">/</c-> <c- mi="">12</c-><c- o="">&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">mile</c-> <c- p="">:</c-> <c- n="">derived_unit</c-><c- o="">&lt;</c-><c- n="">mile</c-><c- p="">,</c-> <c- s="">"mi"</c-><c- p="">,</c-> <c- n="">length</c-><c- p="">,</c-> <c- mi="">1</c->’<c- mi="">760</c-> <c- o="">*</c-> <c- n="">yard</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&gt;</c-> <c- p="">{};</c->
</pre>
   <p>Also, please see the mixed approach described in <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#prefixes-and-units">§ 13.1 How to represent SI prefixes and derived units?</a> which opens the door
to new natural syntax of spelling <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②④">units</a>.</p>
   <h3 class="heading settled" data-level="13.3" id="relative-vs-absolute"><span class="secno">13.3. </span><span class="content">Relative vs absolute quantity</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#relative-vs-absolute"></a></h3>
   <p>One of the most critical aspects of the physical units library is to understand what a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④②">quantity</a> is? An absolute or relative value? For most <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①⑥">dimensions</a> only relative values
have sense. For example:</p>
   <ul>
    <li data-md="">
     <p>Where are absolute 123 meters?</p>
    </li><li data-md="">
     <p>If I am sitting in a moving train, is my velocity == 0?</p>
    </li><li data-md="">
     <p>Is my velocity == 0 when the train stops?</p>
   </li></ul>
   <p>However, for some <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity①①">base quantities</a> like temperature, absolute values are really needed.
For example, how much is <code class="highlight"><c- mi="">0</c-> ℃ <c- o="">+</c-> <c- mi="">0</c-> ℃</code>? Is it <code class="highlight"><c- mi="">0</c-> ℃</code> or <code class="highlight"><c- mi="">0</c-> ℃</code> or <code class="highlight"><c- mf="">273.15</c-> ℃</code>? Yes, the
repeated value of <code class="highlight"><c- mi="">0</c-> ℃</code> is not an error here ;-) Actually, all of the answers are right:</p>
   <ul>
    <li data-md="">
     <p>Two (absolute) temperatures:</p>
<pre class="language-text highlight">    0 ℃ + 0 ℃ = 273.15 K + 273.15 K = 546.30 K = 273.15 ℃
</pre>
    </li><li data-md="">
     <p>An (absolute) temperature and a (relative) temperature interval:</p>
<pre class="language-text highlight">    0 ℃ + 0 ℃ = 273.15 K + 0 K = 273.15 K = 0 ℃
</pre>
    </li><li data-md="">
     <p>Two (relative) temperature intervals:</p>
<pre class="language-text highlight">    0 ℃ + 0 ℃ = 0 K + 0 K = 0 K = 0 ℃
</pre>
   </li></ul>
   <p>As proven above, it is a complex and a pretty hard problem. The average user of the library
will probably not be able to distinguish between different kinds of quantities. This is
why it was decided that only relative quantity values will be modeled by the library.
Moreover, providing support for only relative quantities of other temperature units than
Kelvin will probably still be misused by the users. This is why we suggest to support
only Kelvins as built-in temperature units and provide verbose non-member utility
functions for conversions between different kinds of temperature values and their units.</p>
   <p>Alternatively, we could consider:</p>
   <ol>
    <li data-md="">
     <p>Providing a fully featured engine to implement an affine space. For example <code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">absolute</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">&gt;&gt;</c-><c- p="">,</c-> <c- n="">Rep</c-><c- o="">&gt;</c-></code> (like in <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-boostunits">[BOOST.UNITS]</a>) or <code class="highlight"><c- n="">quantity_point</c-></code> (like in <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-benri">[BENRI]</a>) could be used for this purpose. If we decide to go this route,
how to distinguish between UDLs for the same unit addressing such two abstractions?</p>
    </li><li data-md="">
     <p>The solution based on <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-cppnow17-units">[CPPNOW17-UNITS]</a> where Kelvin is always treated as relative
temperature and Celsius and Fahrenheit are always treated as an absolute one.</p>
   </li></ol>
   <h3 class="heading settled" data-level="13.4" id="systems-support"><span class="secno">13.4. </span><span class="content">Should we support <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①⑧">systems</a> as a separate type?</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#systems-support"></a></h3>
   <p>For many years we have requirements to support multiple <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities①⑨">systems of units</a>.
Walter E. Brown started to present papers on this subject more than 20 years ago <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-walter_e_brown">[WALTER_E_BROWN]</a>.</p>
   <p>The basic rationale for a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units" id="ref-for-system-of-units⑧">system of units</a> is that "Unit systems should form closed
universes independent from each other" as stated by <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-p1930r0">[P1930R0]</a>. But what does it really
mean? Does it mean that every system should be independent from others and define its
own dimensions and their units? Does it mean that it should not be possible to mix
units from different systems even with explicit casts? If yes, are we ready to reimplement
most of the same dimensional logic for every system from scratch?</p>
   <p>US Customary System has the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①⑦">dimensions</a> and most of the units as the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units⑤">SI</a> with
the differences scoped mostly only in length and mass <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②⑤">units</a> and <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-quantity" id="ref-for-derived-quantity⑥">derived quantities</a> using those. From the implementation and standardization point of view it is much simpler
to use the common definitions of such physical dimensions and just provide <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②⑥">units</a> dedicated
to such a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities②⓪">system</a> next to the <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units⑥">SI</a> ones (i.e. meters and miles). This is why even
Boost.Units, the only library supporting systems, implements US units in <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units⑦">SI</a> system.</p>
   <p>Another potential candidate for a dedicated system could be CGS (centimetre–gram–second)
system, but even here all physical dimensions are defined in the same way so the units
can, and in some cases should, be possible to be mixed with units from <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units⑧">SI</a>.</p>
   <p>Even <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities②①">systems</a> like <code class="highlight"><c- n="">coffee</c-><c- o="">/</c-><c- n="">milk</c-><c- o="">/</c-><c- n="">water</c-><c- o="">/</c-><c- n="">sugar</c-></code> system that seem to be totally isolated
from typical <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units⑨">SI</a> use cases at some point will probably need time, volume, and other <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units①⓪">SI</a> dimensions too.</p>
   <p>This is why even when the library claims to support different unit systems it often does
that based on <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units" id="ref-for-international-system-of-units①①">SI</a> anyway (i.e. <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-benri">[BENRI]</a> provides headers like <code class="highlight"><c- n="">si</c-><c- o="">/</c-><c- n="">cgs</c-><c- p="">.</c-><c- n="">h</c-></code>).</p>
   <p>Boost.Units uses <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities②②">systems</a> mostly to provide the capability of having a different <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit" id="ref-for-base-unit①⑨">base unit</a> for a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①⑧">dimension</a> to limit intermediate conversions while passing quantities
as vocabulary types in the interfaces. Usage of templates functions constrained with concepts
for generic algorithms and concrete types for domain-specific needs addresses this area easily.
For more information on this subject please refer to <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#limiting-intermediate-value-conversions">§ 8 Limiting intermediate quantity value conversions</a>.</p>
   <p>Important point to note here is that adding direct <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities" id="ref-for-system-of-quantities②③">systems</a> support in the library type
system might negatively affect user experience. Most of the verbose compilation errors
presented in <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#type-aliasing-issues">§ 7.1 Type aliasing issues</a> are caused by a dedicated systems support in
Boost.Units.</p>
   <p>Please also note that the author of the only library providing direct systems support <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-boostunits">[BOOST.UNITS]</a> removed them in the refreshed design of a new library
(<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#cppnow17-units.design">§ 5.2.1 Design</a>).</p>
   <p>For example here is how we can support CGS without having direct systems support:</p>
<pre class="language-cpp highlight"><c- k="">namespace</c-> <c- n="">cgs</c-> <c- p="">{</c->

  <c- k="">using</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">centimetre</c-><c- p="">;</c->
  <c- k="">using</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">gram</c-><c- p="">;</c->
  <c- k="">using</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">second</c-><c- p="">;</c->
  <c- k="">struct</c-> <c- nl="">centimetre_per_second</c-> <c- p="">:</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">deduced_derived_unit</c-><c- o="">&lt;</c-><c- n="">centimetre_per_second</c-><c- p="">,</c-> <c- s="">"cm/s"</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">velocity</c-><c- p="">,</c-> <c- n="">centimetre</c-><c- p="">,</c-> <c- n="">second</c-><c- o="">&gt;</c-> <c- p="">{};</c->
  <c- k="">struct</c-> <c- nl="">gal</c-> <c- p="">:</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">deduced_derived_unit</c-><c- o="">&lt;</c-><c- n="">gal</c-><c- p="">,</c-> <c- s="">"Gal"</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">acceleration</c-><c- p="">,</c-> <c- n="">centimetre</c-><c- p="">,</c-> <c- n="">second</c-><c- o="">&gt;</c-> <c- p="">{};</c->
  <c- k="">struct</c-> <c- nl="">dyne</c-> <c- p="">:</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">deduced_derived_unit</c-><c- o="">&lt;</c-><c- n="">dyne</c-><c- p="">,</c-> <c- s="">"dyn"</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">force</c-><c- p="">,</c-> <c- n="">centimetre</c-><c- p="">,</c-> <c- n="">gram</c-><c- p="">,</c-> <c- n="">second</c-><c- o="">&gt;</c-> <c- p="">{};</c->
  <c- k="">struct</c-> <c- nl="">erg</c-> <c- p="">:</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">deduced_derived_unit</c-><c- o="">&lt;</c-><c- n="">erg</c-><c- p="">,</c-> <c- s="">"erg"</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">energy</c-><c- p="">,</c-> <c- n="">centimetre</c-><c- p="">,</c-> <c- n="">gram</c-><c- p="">,</c-> <c- n="">second</c-><c- o="">&gt;</c-> <c- p="">{};</c->
  <c- k="">struct</c-> <c- nl="">ergps</c-> <c- p="">:</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">deduced_derived_unit</c-><c- o="">&lt;</c-><c- n="">ergps</c-><c- p="">,</c-> <c- s="">"erg/s"</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">power</c-><c- p="">,</c-> <c- n="">centimetre</c-><c- p="">,</c-> <c- n="">gram</c-><c- p="">,</c-> <c- n="">second</c-><c- o="">&gt;</c-> <c- p="">{};</c->
  <c- k="">struct</c-> <c- nl="">barye</c-> <c- p="">:</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">deduced_derived_unit</c-><c- o="">&lt;</c-><c- n="">barye</c-><c- p="">,</c-> <c- s="">"Ba"</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">pressure</c-><c- p="">,</c-> <c- n="">centimetre</c-><c- p="">,</c-> <c- n="">gram</c-><c- p="">,</c-> <c- n="">second</c-><c- o="">&gt;</c-> <c- p="">{};</c->


  <c- kr="">inline</c-> <c- k="">namespace</c-> <c- n="">literals</c-> <c- p="">{</c->

    <c- k="">using</c-> <c- k="">namespace</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">literals</c-><c- p="">;</c->

    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">cmps</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">centimetre_per_second</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">cmps</c-><c- p="">(</c-><c- b="">long</c-> <c- b="">double</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">centimetre_per_second</c-><c- p="">,</c-> <c- b="">long</c-> <c- b="">double</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">Gal</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">gal</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">Gal</c-><c- p="">(</c-><c- b="">long</c-> <c- b="">double</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">gal</c-><c- p="">,</c-> <c- b="">long</c-> <c- b="">double</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">dyn</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">dyne</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">dyn</c-><c- p="">(</c-><c- b="">long</c-> <c- b="">double</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">dyne</c-><c- p="">,</c-> <c- b="">long</c-> <c- b="">double</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">_erg</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">erg</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">_erg</c-><c- p="">(</c-><c- b="">long</c-> <c- b="">double</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">erg</c-><c- p="">,</c-> <c- b="">long</c-> <c- b="">double</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">_ergps</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">ergps</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">_ergps</c-><c- p="">(</c-><c- b="">long</c-> <c- b="">double</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">ergps</c-><c- p="">,</c-> <c- b="">long</c-> <c- b="">double</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">Ba</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">barye</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
    <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">Ba</c-><c- p="">(</c-><c- b="">long</c-> <c- b="">double</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">barye</c-><c- p="">,</c-> <c- b="">long</c-> <c- b="">double</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->

  <c- p="">}</c->  <c- c1="">// namespace literals</c->

<c- p="">}</c->
</pre>
<pre class="language-cpp highlight"><c- k="">using</c-> <c- k="">namespace</c-> <c- n="">cgs</c-><c- o="">::</c-><c- n="">literals</c-><c- p="">;</c->

<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">100</c-><c- n="">cm</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">m</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">1</c->’<c- mo="">000</c-><c- n="">g</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">kg</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">100</c-><c- n="">cmps</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">mps</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">100</c-><c- n="">Gal</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">mps_sq</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">100</c->’<c- mo="">000</c-><c- n="">dyn</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">N</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">10</c->’<c- mo="">000</c->’<c- mo="">000</c-><c- n="">_erg</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">_J</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">10</c->’<c- mo="">000</c->’<c- mo="">000</c-><c- n="">_ergps</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">W</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">10</c-><c- n="">Ba</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">Pa</c-><c- p="">);</c->
</pre>
   <h3 class="heading settled" data-level="13.5" id="duration-interoperability"><span class="secno">13.5. </span><span class="content">Interoperability with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code></span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#duration-interoperability"></a></h3>
   <p>One of the most challenging problems to solve in the physical units library will be
the interoperability with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code>. <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-></code> is an excellent library
and has a wide adoption in the industry right now. However it has also some issues that
make its design not suitable for a general purpose units library framework:</p>
   <ol>
    <li data-md="">
     <p>It addresses only one of many <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity①⑨">dimensions</a>, namely time. There is no possibility to extend
it with other <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity②⓪">dimensions</a> support.</p>
    </li><li data-md="">
     <p><code class="highlight"><c- n="">quantity</c-></code> class template needs a few more member functions to provide support for
conversions between different <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity②①">dimensions</a>.</p>
    </li><li data-md="">
     <p>SG6 members raised an issue with <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code> returning <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">common_type_t</c-><c- o="">&lt;</c-><c- n="">Rep1</c-><c- p="">,</c-> <c- n="">Rep2</c-><c- o="">&gt;</c-></code> from most of the arithmetic operators. This does note
play well with custom representation types that return different type in case of
multiplication and different in case of division operation.</p>
    </li><li data-md="">
     <p><code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-></code> is not able to handle large prefixes required by some units (more
information in <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ratio-on-steroids">§ 9 std::ratio on steroids</a>).</p>
   </li></ol>
   <p>Because of the above issues we cannot just use <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code> design as it is right
now and use it for physical units implementation or even as a representation of only time <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity②②">dimension</a>. There are however, a few possibilities here to provide interoperability between
the types:</p>
   <ol>
    <li data-md="">
     <p>One of the solutions could be making a <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code> an alias or a child class
of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-></code> class template (assuming that we will not use NTTP ratios
as described in <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nttp-usage">§ 13.2 NTTP usage</a>). This would be probably the best solution from
the API point of view but unfortunately it will cause an ABI break.</p>
    </li><li data-md="">
     <p>Provide built-in conversion facility that among others can be used to allow conversion
between <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code> and <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-></code>.</p>
    </li><li data-md="">
     <p>Provide non-member function to convert and compare between those two types.</p>
    </li><li data-md="">
     <p>Just ignore <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code> and do not provide any conversion utilities in the
standard library.</p>
   </li></ol>
   <p>From all options above we propose the first one if we decide that C++23 will be an ABI breaking
release. In such a case we could update <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-></code> type as described in <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ratio-on-steroids">§ 9 std::ratio on steroids</a>. Otherwise, we would probably go with the option #3.</p>
   <h3 class="heading settled" data-level="13.6" id="integral-udl"><span class="secno">13.6. </span><span class="content">Should we provide integral UDLs?</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#integral-udl"></a></h3>
   <p>User Defined Literals support is really handy for the end-users. However, it sometimes might
cause more confusion than benefits. For example defining both UDL versions for a velocity:</p>
<pre class="language-cpp highlight"><c- kr="">inline</c-> <c- k="">namespace</c-> <c- n="">literals</c-> <c- p="">{</c->

  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">kmph</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c->
  <c- p="">{</c-> <c- k="">return</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">kilometre_per_hour</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->

  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">kmph</c-><c- p="">(</c-><c- b="">long</c-> <c- b="">double</c-> <c- n="">l</c-><c- p="">)</c->
  <c- p="">{</c-> <c- k="">return</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">kilometre_per_hour</c-><c- p="">,</c-> <c- b="">long</c-> <c- b="">double</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->

<c- p="">}</c->
</pre>
   <p>and a function template defined as:</p>
<pre class="language-cpp highlight"><c- k="">constexpr</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Length</c-> <c- k="">auto</c-> <c- n="">d</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Time</c-> <c- k="">auto</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>might cause the following code to not compile:</p>
<pre class="language-cpp highlight"><c- k="">const</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">speed</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mi="">220</c-><c- n="">km</c-><c- p="">,</c-> <c- mi="">2</c-><c- n="">h</c-><c- p="">);</c->
</pre>
   <p>while the following one compiles fine:</p>
<pre class="language-cpp highlight"><c- k="">const</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">speed</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mf="">220.</c-><c- n="">km</c-><c- p="">,</c-> <c- mi="">2</c-><c- n="">h</c-><c- p="">);</c->
</pre>
   <p>Above is caused by the constraints copied from <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code> and put on the
conversion constructors requiring the denominator of <code class="highlight"><c- n="">ratio</c-></code> to be 1 in case of the integral
representation type.</p>
   <p>Based on the above we could agree on making integral UDLs returning a quantity with <code class="highlight"><c- b="">long</c-> <c- b="">double</c-></code> as a representation type. However, if we consider a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity" id="ref-for-base-quantity①②">base quantity</a> like
a digital information, what does it mean to have a fraction of bit? This probably is not
the only one isolated example when actually only integral UDLs have sense.</p>
   <p>Summarizing above we have the following options to choose from as an answer to
"Should we provide integral UDLs?":</p>
   <ol>
    <li data-md="">
     <p>Yes, as is (always both integral and floating-point for all units). And leave it up to the
user to use them correctly.</p>
    </li><li data-md="">
     <p>Yes, but integral literals get floating-point <code class="highlight"><c- n="">Rep</c-></code>.</p>
    </li><li data-md="">
     <p>Yes, but only for specific units like a <code class="highlight"><c- n="">bit</c-></code>, <code class="highlight"><c- n="">byte</c-></code>, etc. where floating-point types do
not have much sense (no floating-point UDLs in such case).</p>
   </li></ol>
   <h3 class="heading settled" data-level="13.7" id="dimension-in-quantity"><span class="secno">13.7. </span><span class="content"><code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">dim_length</c-><c- p="">,</c-> <c- n="">metre</c-><c- o="">&gt;</c-></code> or <code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">metre</c-><c- o="">&gt;</c-></code>?</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-in-quantity"></a></h3>
   <p>The initial version of the mp-units library provided the following <code class="highlight"><c- n="">quantity</c-></code> class template
definition:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- n="">Dimension</c-> <c- n="">D</c-><c- p="">,</c-> <c- n="">Unit</c-> <c- n="">U</c-><c- p="">,</c-> <c- n="">Scalar</c-> <c- n="">Rep</c-><c- o="">&gt;</c->
  <c- n="">requires</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">D</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">U</c-><c- o="">::</c-><c- n="">dimension</c-><c- o="">&gt;</c->
<c- k="">class</c-> <c- nc="">quantity</c-><c- p="">;</c->
</pre>
   <p>This allowed the following helper aliases:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- n="">Unit</c-> <c- n="">U</c-> <c- o="">=</c-> <c- n="">meter</c-><c- p="">,</c-> <c- n="">Scalar</c-> <c- n="">Rep</c-> <c- o="">=</c-> <c- b="">double</c-><c- o="">&gt;</c->
<c- k="">using</c-> <c- n="">length</c-> <c- o="">=</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">dimension_length</c-><c- p="">,</c-> <c- n="">U</c-><c- p="">,</c-> <c- n="">Rep</c-><c- o="">&gt;</c-><c- p="">;</c->
</pre>
   <p>With such a framework and CTAD usage user could write the following:</p>
<pre class="language-cpp highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">length</c-> <c- n="">d</c-><c- p="">(</c-><c- mi="">3</c-><c- p="">);</c->                <c- c1="">// 3 meters</c->
<c- n="">units</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">mile</c-><c- o="">&gt;</c-> <c- n="">d3</c-><c- p="">(</c-><c- mi="">3</c-><c- p="">);</c->  <c- c1="">// 3 miles</c->
</pre>
   <p>or</p>
<pre class="language-cpp highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">velocity</c-> <c- n="">speed</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mf="">220.</c-><c- n="">km</c-><c- p="">,</c-> <c- mf="">2.</c-><c- n="">h</c-><c- p="">);</c->
</pre>
   <p>or</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">U</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Rep</c-><c- o="">&gt;</c->
<c- b="">void</c-> <c- n="">foo</c-><c- p="">(</c-><c- n="">units</c-><c- o="">::</c-><c- n="">length</c-><c- o="">&lt;</c-><c- n="">U</c-><c- p="">,</c-> <c- n="">Rep</c-><c- o="">&gt;</c-> <c- n="">dist</c-><c- p="">);</c->
</pre>
   <p>to constrain the type to a length dimension.</p>
   <p>The downside of such a design was that the dimension was provided twice in every <code class="highlight"><c- n="">quantity</c-></code> class template instantiation which was affecting user experience by longer types in error logs
or during debugging:</p>
<pre class="language-cpp highlight"><c- nl="">error</c-><c- p="">:</c-> <c- n="">conversion</c-> <c- n="">from</c-> ‘<c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">dimension</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">exp</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_dim_length</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-><c- p="">,</c->
<c- n="">units</c-><c- o="">::</c-><c- n="">exp</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_dim_time</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- o="">&gt;</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">dimension</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">exp</c-><c- o="">&lt;</c->
<c- n="">units</c-><c- o="">::</c-><c- n="">base_dim_length</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">exp</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_dim_time</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- o="">&gt;</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">3600000</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- o="">&gt;</c-><c- p="">,</c->
<c- p="">[...]</c-><c- o="">&gt;</c->’ <c- n="">to</c-> <c- n="">non</c-><c- o="">-</c-><c- n="">scalar</c-> <c- n="">type</c-> ‘<c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">dimension_velocity</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">kilometer_per_hour</c-><c- p="">,</c->
<c- p="">[...]</c-><c- o="">&gt;</c->’ <c- n="">requested</c->
</pre>
   <p>During evening session in Cologne the author received a feedback from SG6 members that such
a duplication should be removed. Right now the design looks as follows:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- n="">Unit</c-> <c- n="">U</c-><c- p="">,</c-> <c- n="">Scalar</c-> <c- n="">Rep</c-><c- o="">&gt;</c->
<c- k="">class</c-> <c- nc="">quantity</c-><c- p="">;</c->
</pre>
   <p>With this there is no possibility to provide a helper alias for a length <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity②③">dimension</a> and
above examples have to be implemented in terms of concepts:</p>
<pre class="language-cpp highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">metre</c-><c- o="">&gt;</c-> <c- n="">d</c-><c- p="">(</c-><c- mi="">3</c-><c- p="">);</c->  <c- c1="">// 3 meters</c->
<c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">mile</c-><c- o="">&gt;</c-> <c- n="">d3</c-><c- p="">(</c-><c- mi="">3</c-><c- p="">);</c->  <c- c1="">// 3 miles</c->
</pre>
   <p>or</p>
<pre class="language-cpp highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">speed</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mf="">220.</c-><c- n="">km</c-><c- p="">,</c-> <c- mf="">2.</c-><c- n="">h</c-><c- p="">);</c->
</pre>
   <p>or</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Length</c-> <c- n="">Quantity</c-><c- o="">&gt;</c->
<c- b="">void</c-> <c- n="">foo</c-><c- p="">(</c-><c- n="">Quantity</c-> <c- n="">dist</c-><c- p="">);</c->
</pre>
   <p>The good part here is that the error logs are more readable with such an approach:</p>
<pre class="language-cpp highlight"><c- nl="">error</c-><c- p="">:</c-> <c- n="">conversion</c-> <c- n="">from</c-> ‘<c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">unit</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">dimension</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">exp</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_dim_length</c-><c- p="">,</c->
<c- mi="">1</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">exp</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">base_dim_time</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- o="">&gt;</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">3600000</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;</c-> <c- o="">&gt;</c-><c- p="">,</c-> <c- p="">[...]</c-><c- o="">&gt;</c->’ <c- n="">to</c-> <c- n="">non</c-><c- o="">-</c-><c- n="">scalar</c-> <c- n="">type</c->
‘<c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">kilometer_per_hour</c-><c- p="">,</c-> <c- p="">[...]</c-><c- o="">&gt;</c->’ <c- n="">requested</c->
</pre>
   <p>Both cases provide the similar functionality so it is a matter of taste here on which of the
syntaxes the Committee will choose to continue with.</p>
   <h3 class="heading settled" data-level="13.8" id="seconds-int"><span class="secno">13.8. </span><span class="content">Should we provide <code class="highlight"><c- n="">seconds</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-></code> or stay with <code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">second</c-><c- p="">,</c-> <c- b="">int</c-><c- o="">&gt;</c-></code>?</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#seconds-int"></a></h3>
   <p>Some of the users complain that writing <code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">second</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">)</c-></code> is too verbose and they would
prefer a helper alias that would allow them to write <code class="highlight"><c- n="">seconds</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">)</c-></code>. This however, starts to
generate a few issues:</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><c- n="">second</c-></code> represent a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②⑦">unit</a></p>
    </li><li data-md="">
     <p><code class="highlight"><c- n="">seconds</c-></code> represents a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④③">quantity</a></p>
    </li><li data-md="">
     <p>plural form reserved for quantities might not be easy to achieve or easy to distinguish for
some <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②⑧">units</a> like <code class="highlight"><c- n="">sq_volt_per_hertz</c-></code>.</p>
   </li></ul>
   <p>We can consider renaming <code class="highlight"><c- n="">second</c-></code> to <code class="highlight"><c- n="">unit_second</c-></code> and provide <code class="highlight"><c- n="">seconds</c-></code> as an alias to the <code class="highlight"><c- n="">quantity</c-></code> class template. However, this will probably set in stone usage of aliases as no
one will be willing to write a verbose code like <code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">unit_second</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">)</c-></code>. This is why
we are looking for a concrete guideline on which of the options the Committee prefers.</p>
   <p>Author preference is to stay with the current design and leave it up to the users to create
any helper aliases for their domains and use cases if they choose so (i.e. <code class="highlight"><c- n="">s</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">)</c-></code>).</p>
   <h3 class="heading settled" data-level="13.9" id="dimensionless-quantities"><span class="secno">13.9. </span><span class="content">Should we provide support for <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-of-dimension-one" id="ref-for-quantity-of-dimension-one②">dimensionless quantities</a>?</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimensionless-quantities"></a></h3>
   <p>Some <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-of-dimension-one" id="ref-for-quantity-of-dimension-one③">quantities of dimension one</a> are defined as the ratios of two <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④④">quantities</a> of
the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#kind-of-quantity" id="ref-for-kind-of-quantity⑥">kind</a>. The <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-derived-unit" id="ref-for-coherent-derived-unit⑦">coherent derived unit</a> is the number one, symbol 1. For example:
plane angle, solid angle, refractive index, relative permeability, mass fraction,
friction factor, Mach number, etc. However, should all such division results be treated as
dimensionless quantities rather than scalars?</p>
<pre class="language-cpp highlight"><c- k="">auto</c-> <c- n="">q1</c-> <c- o="">=</c-> <c- mi="">10</c-><c- n="">s</c-> <c- o="">/</c-> <c- mi="">2</c-><c- n="">s</c-><c- p="">;</c->
<c- k="">auto</c-> <c- n="">q2</c-> <c- o="">=</c-> <c- mi="">90</c-><c- n="">kmph</c-> <c- o="">/</c-> <c- mi="">30</c-><c- n="">kmph</c-><c- p="">;</c->
</pre>
   <p>If not, how to determine when to return a scalar an when the dimensionless quantity?</p>
   <p>Numbers of entities are also <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-of-dimension-one" id="ref-for-quantity-of-dimension-one④">quantities of dimension one</a>. For example: number of
turns in a coil, number of molecules in a given sample, degeneracy of the energy levels
of a quantum system.</p>
   <p>Should the library treat such entities as regular scalars or should some strong typing
mechanism be provided to support those?</p>
   <h3 class="heading settled" data-level="13.10" id="number"><span class="secno">13.10. </span><span class="content">Number concept</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#number"></a></h3>
   <p>Assuming that we will vote for a widespread concepts usage in the library it would be
also nice to have a concept for scalars. Currently <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-mp-units">[MP-UNITS]</a> defines a scalar as:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">T</c-><c- o="">&gt;</c->
<c- n="">concept</c-> <c- n="">Number</c-> <c- o="">=</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">regular</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-> <c- o="">&amp;&amp;</c->
    <c- n="">std</c-><c- o="">::</c-><c- n="">totally_ordered</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-> <c- o="">&amp;&amp;</c->
    <c- n="">requires</c-><c- p="">(</c-><c- n="">T</c-> <c- n="">a</c-><c- p="">,</c-> <c- n="">T</c-> <c- n="">b</c-><c- p="">)</c-> <c- p="">{</c->
      <c- p="">{</c-> <c- n="">a</c-> <c- o="">+</c-> <c- n="">b</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">;</c->
      <c- p="">{</c-> <c- n="">a</c-> <c- o="">-</c-> <c- n="">b</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">;</c->
      <c- p="">{</c-> <c- n="">a</c-> <c- o="">*</c-> <c- n="">b</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">;</c->
      <c- p="">{</c-> <c- n="">a</c-> <c- o="">/</c-> <c- n="">b</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">;</c->
      <c- p="">{</c-> <c- o="">+</c-><c- n="">a</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">;</c->
      <c- p="">{</c-> <c- o="">-</c-><c- n="">a</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">;</c->
      <c- p="">{</c-> <c- n="">a</c-> <c- o="">+=</c-> <c- n="">b</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&amp;&gt;</c-><c- p="">;</c->
      <c- p="">{</c-> <c- n="">a</c-> <c- o="">-=</c-> <c- n="">b</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&amp;&gt;</c-><c- p="">;</c->
      <c- p="">{</c-> <c- n="">a</c-> <c- o="">*=</c-> <c- n="">b</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&amp;&gt;</c-><c- p="">;</c->
      <c- p="">{</c-> <c- n="">a</c-> <c- o="">/=</c-> <c- n="">b</c-> <c- p="">}</c-> <c- o="">-&gt;</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">same_as</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&amp;&gt;</c-><c- p="">;</c->
      <c- p="">{</c-> <c- n="">T</c-><c- p="">{</c-><c- mi="">0</c-><c- p="">}</c-> <c- p="">};</c->
<c- p="">};</c->

<c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">T</c-><c- o="">&gt;</c->
<c- n="">concept</c-> <c- n="">Scalar</c-> <c- o="">=</c-> <c- p="">(</c-><c- o="">!</c-><c- n="">Quantity</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">)</c-> <c- o="">&amp;&amp;</c-> <c- n="">Number</c-><c- o="">&lt;</c-><c- n="">T</c-><c- o="">&gt;</c-><c- p="">;</c->
</pre>
   <h3 class="heading settled" data-level="13.11" id="unicode"><span class="secno">13.11. </span><span class="content">What about Unicode?</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unicode"></a></h3>
   <p>Every unit and its prefix can be printed with ASCII characters but it will probably not
result with the best user experience. <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④⑤">Quantities</a> can often be represented better with
Unicode symbols. For example an ASCII text output can look like:</p>
<pre class="language-cpp highlight"><c- mi="">10</c-> <c- n="">us</c->
<c- mi="">2</c-> <c- n="">kg</c-><c- o="">*</c-><c- n="">m</c-><c- o="">/</c-><c- n="">s</c-><c- o="">^</c-><c- mi="">2</c->
<c- mi="">37</c-> <c- n="">deg</c-><c- p="">.</c-> <c- n="">C</c->
</pre>
   <p>while the same <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④⑥">quantities</a> can be represented as:</p>
<pre class="language-cpp highlight"><c- mi="">10</c-> μ<c- n="">s</c->
<c- mi="">2</c-> <c- n="">kg</c->⋅<c- n="">m</c-><c- o="">/</c-><c- n="">s</c->²
<c- mi="">37</c-> °<c- n="">C</c->
</pre>
   <p>If we decide to continue with the second approach it is not clear how to achieve this. For
example <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code> is specified to return <code class="highlight">μ<c- n="">s</c-></code> if the character <code class="highlight"><c- n="">U</c-><c- o="">+</c-><c- mo="">00</c-><c- n="">B5</c-></code> can be
represented in the encoding used for <code class="highlight"><c- n="">charT</c-></code>, <code class="highlight"><c- n="">us</c-></code> otherwise. However this is specified for:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">class</c-> <c- nc="">charT</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">traits</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">Rep</c-><c- p="">,</c-> <c- k="">class</c-> <c- nc="">Period</c-><c- o="">&gt;</c->
<c- n="">basic_ostream</c-><c- o="">&lt;</c-><c- n="">charT</c-><c- p="">,</c-> <c- n="">traits</c-><c- o="">&gt;&amp;</c-> <c- k="">operator</c-><c- o="">&lt;&lt;</c-><c- p="">(</c-><c- n="">basic_ostream</c-><c- o="">&lt;</c-><c- n="">charT</c-><c- p="">,</c-> <c- n="">traits</c-><c- o="">&gt;&amp;</c-> <c- n="">os</c-><c- p="">,</c->
                                         <c- k="">const</c-> <c- n="">duration</c-><c- o="">&lt;</c-><c- n="">Rep</c-><c- p="">,</c-> <c- n="">Period</c-><c- o="">&gt;&amp;</c-> <c- n="">d</c-><c- p="">);</c->
</pre>
   <p>which requires <code class="highlight"><c- n="">charT</c-></code> to be <code class="highlight"><c- b="">char</c-></code> or <code class="highlight"><c- b="">wchar_t</c-></code>. C++20 specification does not mention
Unicode characters at all here. Even if we decide to provide a support for Unicode character
sets (<code class="highlight"><c- n="">charN_t</c-></code>) here, it is not clear how to create such streams. Currently we do not have <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">u8cout</c-></code> or even <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">u8ostream</c-></code> in the C++ Standard Library.</p>
   <p>Also, providing partial specializations to define such <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement②⑨">unit</a> symbols:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">CharT</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Traits</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Prefix</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Ratio</c-><c- o="">&gt;</c->
<c- kr="">inline</c-> <c- k="">constexpr</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- n="">CharT</c-><c- p="">,</c-> <c- n="">Traits</c-><c- o="">&gt;</c-> <c- n="">prefix_symbol</c-><c- p="">;</c->

<c- c1="">// one definition for all character types</c->
<c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">CharT</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
<c- kr="">inline</c-> <c- k="">constexpr</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- n="">CharT</c-><c- p="">,</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
    <c- n="">prefix_symbol</c-><c- o="">&lt;</c-><c- n="">CharT</c-><c- p="">,</c-> <c- n="">Traits</c-><c- p="">,</c-> <c- n="">si_prefix</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">milli</c-><c- o="">&gt;</c-> <c- o="">=</c-> <c- s="">"m"</c-><c- p="">;</c->

<c- c1="">// definition for non-Unicode systems</c->
<c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
<c- kr="">inline</c-> <c- k="">constexpr</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- b="">char</c-><c- p="">,</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
    <c- n="">prefix_symbol</c-><c- o="">&lt;</c-><c- b="">char</c-><c- p="">,</c-> <c- n="">Traits</c-><c- p="">,</c-> <c- n="">si_prefix</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">micro</c-><c- o="">&gt;</c-> <c- o="">=</c-> <c- s="">"u"</c-><c- p="">;</c->
<c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
<c- kr="">inline</c-> <c- k="">constexpr</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- b="">wchar_t</c-><c- p="">,</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
    <c- n="">prefix_symbol</c-><c- o="">&lt;</c-><c- b="">wchar_t</c-><c- p="">,</c-> <c- n="">Traits</c-><c- p="">,</c-> <c- n="">si_prefix</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">micro</c-><c- o="">&gt;</c-> <c- o="">=</c-> L<c- s="">"u"</c-><c- p="">;</c->

<c- c1="">// definition for Unicode</c->
<c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
<c- kr="">inline</c-> <c- k="">constexpr</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">char8_t</c-><c- p="">,</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
    <c- n="">prefix_symbol</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- n="">char8_t</c-><c- p="">,</c-> <c- n="">Traits</c-><c- p="">,</c-> <c- n="">si_prefix</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">micro</c-><c- o="">&gt;</c-> <c- o="">=</c-> u8<c- s="">"µ"</c-><c- p="">;</c->
<c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
<c- kr="">inline</c-> <c- k="">constexpr</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- b="">char16_t</c-><c- p="">,</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
    <c- n="">prefix_symbol</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- b="">char16_t</c-><c- p="">,</c-> <c- n="">Traits</c-><c- p="">,</c-> <c- n="">si_prefix</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">micro</c-><c- o="">&gt;</c-> <c- o="">=</c-> u<c- s="">"µ"</c-><c- p="">;</c->
<c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
<c- kr="">inline</c-> <c- k="">constexpr</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- b="">char32_t</c-><c- p="">,</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
    <c- n="">prefix_symbol</c-><c- o="">&lt;</c-><c- n="">std</c-><c- o="">::</c-><c- b="">char32_t</c-><c- p="">,</c-> <c- n="">Traits</c-><c- p="">,</c-> <c- n="">si_prefix</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">micro</c-><c- o="">&gt;</c-> <c- o="">=</c-> U<c- s="">"µ"</c-><c- p="">;</c->
</pre>
   <p>starts to be a nightmare for library developers. Even, though we provided dedicated
specializations for all character types for <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">micro</c-></code> (which is actually a lot of
boilerplate code), the first definition of <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">milli</c-></code> will not compile for other
character types than <code class="highlight"><c- b="">char</c-></code>. Right now there is no possibility in the C++ standard
to define one literal that will allow to initialize all versions of such a variable
template. If we had such a feature, additionally, it would be great to be able to
initialize all non-Unicode character types with one literal and all Unicode character
types with another one using Unicode character set. If we had such facility we could
implement <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">micro</c-></code> case from above with only two partial specializations:</p>
<pre class="language-cpp highlight"><c- c1="">// definition for non-Unicode systems</c->
<c- k="">template</c-><c- o="">&lt;</c-><c- n="">non_unicode</c-> <c- n="">charT</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
<c- kr="">inline</c-> <c- k="">constexpr</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- n="">charT</c-><c- p="">,</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
    <c- n="">prefix_symbol</c-><c- o="">&lt;</c-><c- n="">charT</c-><c- p="">,</c-> <c- n="">Traits</c-><c- p="">,</c-> <c- n="">si_prefix</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">micro</c-><c- o="">&gt;</c-> <c- o="">=</c-> <c- n="">NON_UNICODE</c-><c- p="">(</c-><c- s="">"u"</c-><c- p="">);</c->

<c- c1="">// definition for Unicode</c->
<c- k="">template</c-><c- o="">&lt;</c-><c- n="">unicode</c-> <c- n="">charT</c-><c- p="">,</c-> <c- k="">typename</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
<c- kr="">inline</c-> <c- k="">constexpr</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">basic_string_view</c-><c- o="">&lt;</c-><c- n="">charT</c-><c- p="">,</c-> <c- n="">Traits</c-><c- o="">&gt;</c->
    <c- n="">prefix_symbol</c-><c- o="">&lt;</c-><c- n="">charT</c-><c- p="">,</c-> <c- n="">Traits</c-><c- p="">,</c-> <c- n="">si_prefix</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- n="">micro</c-><c- o="">&gt;</c-> <c- o="">=</c-> <c- n="">UNICODE</c-><c- p="">(</c-><c- s="">"µ"</c-><c- p="">);</c->
</pre>
   <h2 class="heading settled" data-level="14" id="impact"><span class="secno">14. </span><span class="content">Impact on the Standard</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#impact"></a></h2>
   <p>The library would be mostly a pure addition to the C++ Standard Library with the following
potential exceptions:</p>
   <ol>
    <li data-md="">
     <p>It is unclear how to provide interoperability with the <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code> (more information in <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#duration-interoperability">§ 13.5 Interoperability with std::chrono::duration</a>).</p>
    </li><li data-md="">
     <p><code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">units</c-><c- o="">::</c-><c- n="">ratio</c-></code> will most probably need to be a different type with the similar
semantics to <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-></code> (more information in <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ratio-on-steroids">§ 9 std::ratio on steroids</a>). However, if we
decide C++23 to be an ABI breaking release we could update <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">ratio</c-></code> with an additional
template parameter.</p>
   </li></ol>
   <h2 class="heading settled" data-level="15" id="implementation"><span class="secno">15. </span><span class="content">Implementation Experience</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#implementation"></a></h2>
   <p>The author of this document implemented <code class="highlight"><c- n="">mp</c-><c- o="">-</c-><c- n="">units</c-></code> <a data-link-type="biblio" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#biblio-mp-units">[MP-UNITS]</a> library, where he tested
different ideas and proved the implementability of the features described in the paper.</p>
   <h3 class="heading settled" data-level="15.1" id="mp-units.usage.example"><span class="secno">15.1. </span><span class="content">Usage example</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#mp-units.usage.example"></a></h3>
<pre class="language-cpp highlight"><c- cp="">#include</c-> &lt;units/dimensions/velocity.h&gt;
<c- cp="">#include</c-> &lt;iostream&gt;
<c- cp="">#include</c-> &lt;cassert&gt;

<c- k="">constexpr</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Length</c-> <c- k="">auto</c-> <c- n="">d</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Time</c-> <c- k="">auto</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->

<c- b="">void</c-> <c- n="">test1</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">using</c-> <c- k="">namespace</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">literals</c-><c- p="">;</c->

  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mf="">220.</c-><c- n="">km</c-><c- p="">,</c-> <c- mi="">2</c-><c- n="">h</c-><c- p="">);</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-><c- p="">.</c-><c- n="">count</c-><c- p="">()</c-> <c- o="">==</c-> <c- mi="">110</c-><c- p="">);</c->   <c- c1="">// passes</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- mi="">110</c-><c- n="">kmph</c-><c- p="">);</c->       <c- c1="">// passes</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">v</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->     <c- c1="">// prints "110 km/h"</c->
<c- p="">}</c->

<c- b="">void</c-> <c- n="">test2</c-><c- p="">()</c->
<c- p="">{</c->
  <c- k="">using</c-> <c- k="">namespace</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">literals</c-><c- p="">;</c->

  <c- k="">const</c-> <c- k="">auto</c-> <c- n="">v</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">mile</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">140</c-><c- p="">),</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">hour</c-><c- o="">&gt;</c-><c- p="">(</c-><c- mi="">2</c-><c- p="">));</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-><c- p="">.</c-><c- n="">count</c-><c- p="">()</c-> <c- o="">==</c-> <c- mi="">70</c-><c- p="">);</c->    <c- c1="">// passes</c->
  <c- n="">assert</c-><c- p="">(</c-><c- n="">v</c-> <c- o="">==</c-> <c- mi="">70</c-><c- n="">mph</c-><c- p="">);</c->         <c- c1="">// passes</c->
  <c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">v</c-> <c- o="">&lt;&lt;</c-> <c- sc="">'\n'</c-><c- p="">;</c->     <c- c1="">// prints "70 mi/h"</c->
<c- p="">}</c->
</pre>
   <p><a href="https://godbolt.org/z/I8JXj4">Compiler Explorer</a></p>
   <h3 class="heading settled" data-level="15.2" id="mp-units.design"><span class="secno">15.2. </span><span class="content">Design</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#mp-units.design"></a></h3>
   <p>The library framework consists of a few concepts: <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④⑦">quantities</a>, <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement③⓪">units</a>, <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity②④">dimensions</a>,
and their exponents. From the user’s point of view, the most important is a <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④⑧">quantity</a>.</p>
   <p><a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity" id="ref-for-quantity④⑨">Quantity</a> is a precise amount of a unit for a specified dimension with a specific representation:</p>
<pre class="language-cpp highlight"><c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">kilometre</c-><c- p="">,</c-> <c- b="">double</c-><c- o="">&gt;</c-> <c- n="">d1</c-><c- p="">(</c-><c- mi="">123</c-><c- p="">);</c->
<c- k="">auto</c-> <c- n="">d2</c-> <c- o="">=</c-> <c- mi="">123</c-><c- n="">km</c-><c- p="">;</c->    <c- c1="">// units::quantity&lt;units::kilometre, std::int64_t&gt;</c->
</pre>
   <p>There are C++ concepts provided for each such quantity type:</p>
<pre class="language-cpp highlight"><c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">T</c-><c- o="">&gt;</c->
<c- n="">concept</c-> <c- n="">Length</c-> <c- o="">=</c-> <c- n="">QuantityOf</c-><c- o="">&lt;</c-><c- n="">T</c-><c- p="">,</c-> <c- n="">length</c-><c- o="">&gt;</c-><c- p="">;</c->
</pre>
   <p>With these concepts, we can easily write a function template:</p>
<pre class="language-cpp highlight"><c- k="">constexpr</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- n="">units</c-><c- o="">::</c-><c- n="">Length</c-> <c- k="">auto</c-> <c- n="">d</c-><c- p="">,</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Time</c-> <c- k="">auto</c-> <c- n="">t</c-><c- p="">)</c->
<c- p="">{</c->
  <c- k="">return</c-> <c- n="">d</c-> <c- o="">/</c-> <c- n="">t</c-><c- p="">;</c->
<c- p="">}</c->
</pre>
   <p>This template function can be used in the following way:</p>
<pre class="language-cpp highlight"><c- k="">const</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">kilometre</c-><c- o="">&gt;</c-> <c- n="">d</c-><c- p="">(</c-><c- mi="">220</c-><c- p="">);</c->
<c- k="">const</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">hour</c-><c- o="">&gt;</c-> <c- n="">t</c-><c- p="">(</c-><c- mi="">2</c-><c- p="">);</c->
<c- k="">const</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">kmph</c-> <c- o="">=</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity_cast</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">kilometre_per_hour</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">avg_speed</c-><c- p="">(</c-><c- n="">d</c-><c- p="">,</c-> <c- n="">t</c-><c- p="">));</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">kmph</c-><c- p="">.</c-><c- n="">count</c-><c- p="">()</c-> <c- o="">&lt;&lt;</c-> <c- s="">" km/h</c-><c- se="">\n</c-><c- s="">"</c-><c- p="">;</c->

<c- k="">const</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">Velocity</c-> <c- k="">auto</c-> <c- n="">speed</c-> <c- o="">=</c-> <c- n="">avg_speed</c-><c- p="">(</c-><c- mf="">140.</c-><c- n="">mi</c-><c- p="">,</c-> <c- mf="">2.</c-><c- n="">h</c-><c- p="">);</c->
<c- n="">assert</c-><c- p="">(</c-><c- n="">speed</c-><c- p="">.</c-><c- n="">count</c-><c- p="">()</c-> <c- o="">==</c-> <c- mi="">70</c-><c- p="">);</c->
<c- n="">std</c-><c- o="">::</c-><c- n="">cout</c-> <c- o="">&lt;&lt;</c-> <c- n="">units</c-><c- o="">::</c-><c- n="">quantity_cast</c-><c- o="">&lt;</c-><c- n="">units</c-><c- o="">::</c-><c- n="">mile_per_hour</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">speed</c-><c- p="">).</c-><c- n="">count</c-><c- p="">()</c-> <c- o="">&lt;&lt;</c-> <c- s="">" mph</c-><c- se="">\n</c-><c- s="">"</c-><c- p="">;</c->
</pre>
   <p>This guarantees that no intermediate conversions are being made, and the output binary is as
effective as implementing the function with <code class="highlight"><c- b="">double</c-></code>s.</p>
   <p>Additionally, thanks to the extensive usage of the C++ concepts and the downcasting facility,
the library provides an excellent user experience. The error message for type aliases would
look like:</p>
<pre class="language-text highlight">[with D = units::quantity&lt;units::unit&lt;units::dimension&lt;units::exp&lt;units::base_dim_length, 1, 1&gt;,
                units::exp&lt;units::base_dim_time, 1, -1&gt; &gt;, units::ratio&lt;5, 18&gt; &gt;, double&gt;]
</pre>
   <p>Yet, thanks to downcast facility, the actual error message is:</p>
<pre class="language-text highlight">[with D = units::quantity&lt;units::kilometre_per_hour, double&gt;]
</pre>
   <p>The breakpoint in the debugger became readable as well:</p>
<pre class="language-text highlight">Breakpoint 1, avg_speed&lt;units::quantity&lt;units::kilometre, double&gt;,
                        units::quantity&lt;units::hour, double&gt; &gt;
(d=..., t=...) at velocity.cpp:31
31      return d / t;
</pre>
   <p>Moreover, it is really easy to extend the library with custom units, derived units, and
base dimensions. For example, if the user wants to provide a custom <code class="highlight"><c- n="">digital</c-> <c- n="">information</c-></code> base dimension and new units based on it, only minimal code is required:</p>
<pre class="language-cpp highlight"><c- cp="">#include</c-> &lt;units/quantity.h&gt;

<c- k="">using</c-> <c- k="">namespace</c-> <c- n="">units</c-><c- p="">;</c->

<c- c1="">// custom base dimension</c->
<c- k="">struct</c-> <c- nl="">base_dim_digital_information</c-> <c- p="">:</c-> <c- n="">base_dimension</c-><c- o="">&lt;</c-><c- s="">"digital information"</c-><c- p="">,</c-> <c- s="">"b"</c-><c- o="">&gt;</c-> <c- p="">{};</c->

<c- c1="">// custom derived dimension and its concept</c->
<c- k="">struct</c-> <c- nl="">digital_information</c-> <c- p="">:</c-> <c- n="">derived_dimension</c-><c- o="">&lt;</c-><c- n="">digital_information</c-><c- p="">,</c->
                                               <c- n="">exp</c-><c- o="">&lt;</c-><c- n="">base_dim_digital_information</c-><c- p="">,</c-> <c- mi="">1</c-><c- o="">&gt;&gt;</c-> <c- p="">{};</c->

<c- k="">template</c-><c- o="">&lt;</c-><c- k="">typename</c-> <c- n="">T</c-><c- o="">&gt;</c->
<c- n="">concept</c-> <c- n="">DigitalInformation</c-> <c- o="">=</c-> <c- n="">QuantityOf</c-><c- o="">&lt;</c-><c- n="">T</c-><c- p="">,</c-> <c- n="">digital_information</c-><c- o="">&gt;</c-><c- p="">;</c->

<c- c1="">// custom prefixes</c->
<c- k="">struct</c-> <c- n="">data_prefix</c-><c- p="">;</c->
<c- k="">struct</c-> <c- nl="">kibi</c-> <c- p="">:</c-> <c- n="">prefix</c-><c- o="">&lt;</c-><c- n="">kibi</c-><c- p="">,</c-> <c- n="">data_prefix</c-><c- p="">,</c-> <c- n="">ratio</c-><c- o="">&lt;</c->    <c- mi="">1</c->’<c- mo="">024</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- s="">"Ki"</c-><c- o="">&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">mebi</c-> <c- p="">:</c-> <c- n="">prefix</c-><c- o="">&lt;</c-><c- n="">mebi</c-><c- p="">,</c-> <c- n="">data_prefix</c-><c- p="">,</c-> <c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">1</c->’<c- mo="">04</c-><c- mi="">8</c->’<c- mi="">576</c-><c- o="">&gt;</c-><c- p="">,</c-> <c- s="">"Mi"</c-><c- o="">&gt;</c-> <c- p="">{};</c->

<c- c1="">// custom units and their literals</c->
<c- k="">struct</c-> <c- nl="">bit</c-> <c- p="">:</c-> <c- n="">coherent_derived_unit</c-><c- o="">&lt;</c-><c- n="">bit</c-><c- p="">,</c-> <c- s="">"b"</c-><c- p="">,</c-> <c- n="">digital_information</c-><c- p="">,</c-> <c- n="">data_prefix</c-><c- o="">&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">kilobit</c-> <c- p="">:</c-> <c- n="">prefixed_derived_unit</c-><c- o="">&lt;</c-><c- n="">kilobit</c-><c- p="">,</c-> <c- n="">kibi</c-><c- p="">,</c-> <c- n="">bit</c-><c- o="">&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">byte</c-> <c- p="">:</c-> <c- n="">derived_unit</c-><c- o="">&lt;</c-><c- n="">byte</c-><c- p="">,</c-> <c- s="">"B"</c-><c- p="">,</c-> <c- n="">digital_information</c-><c- p="">,</c-> <c- n="">ratio</c-><c- o="">&lt;</c-><c- mi="">8</c-><c- o="">&gt;&gt;</c-> <c- p="">{};</c->
<c- k="">struct</c-> <c- nl="">kilobyte</c-> <c- p="">:</c-> <c- n="">prefixed_derived_unit</c-><c- o="">&lt;</c-><c- n="">kilobyte</c-><c- p="">,</c-> <c- n="">kibi</c-><c- p="">,</c-> <c- n="">byte</c-><c- o="">&gt;</c-> <c- p="">{};</c->

<c- kr="">inline</c-> <c- k="">namespace</c-> <c- n="">literals</c-> <c- p="">{</c->
  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">_b</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">bit</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">_Kib</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">kilobit</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">_B</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">byte</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
  <c- k="">constexpr</c-> <c- k="">auto</c-> <c- k="">operator</c-><c- s="">""</c-><c- n="">_KiB</c-><c- p="">(</c-><c- b="">unsigned</c-> <c- b="">long</c-> <c- b="">long</c-> <c- n="">l</c-><c- p="">)</c-> <c- p="">{</c-> <c- k="">return</c-> <c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">kilobyte</c-><c- p="">,</c-> <c- n="">std</c-><c- o="">::</c-><c- b="">int64_t</c-><c- o="">&gt;</c-><c- p="">(</c-><c- n="">l</c-><c- p="">);</c-> <c- p="">}</c->
<c- p="">}</c->

<c- c1="">// unit tests</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">1</c-><c- n="">_B</c-> <c- o="">==</c-> <c- mi="">8</c-><c- n="">_b</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">1024</c-><c- n="">_b</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">_Kib</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">1024</c-><c- n="">_B</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">_KiB</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">8</c-> <c- o="">*</c-> <c- mi="">1024</c-><c- n="">_b</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">_KiB</c-><c- p="">);</c->
<c- k="">static_assert</c-><c- p="">(</c-><c- mi="">8</c-> <c- o="">*</c-> <c- mi="">1</c-><c- n="">_Kib</c-> <c- o="">==</c-> <c- mi="">1</c-><c- n="">_KiB</c-><c- p="">);</c->
</pre>
   <h2 class="heading settled" data-level="16" id="polls"><span class="secno">16. </span><span class="content">Polls</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#polls"></a></h2>
   <h3 class="heading settled" data-level="16.1" id="lewg"><span class="secno">16.1. </span><span class="content">LEWG</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#lewg"></a></h3>
   <ol>
    <li data-md="">
     <p>Do we want a physical units library in the C++ standard?</p>
    </li><li data-md="">
     <p>Do we prefer UDL, multiply, or mixed syntax for units (<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#prefixes-and-units">§ 13.1 How to represent SI prefixes and derived units?</a>)?</p>
    </li><li data-md="">
     <p>Do we like the concept-based approach to prevent truncation and intermediate conversions
(<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#generic-programming-with-concepts">§ 8.2 Generic programming with concepts</a>)?</p>
    </li><li data-md="">
     <p>Do we like a downcasting facility and would like to standardize it as a part of <code class="highlight"><c- n="">std</c-></code> (<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#downcasting">§ 7.2 Downcasting facility</a>)?</p>
    </li><li data-md="">
     <p>Do we prefer NTTP usage for <code class="highlight"><c- n="">ratio</c-></code> and <code class="highlight"><c- n="">exp</c-></code> (<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#nttp-usage">§ 13.2 NTTP usage</a>)?</p>
    </li><li data-md="">
     <p>Which option of UDLs do we prefer (<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#integral-udl">§ 13.6 Should we provide integral UDLs?</a>)?</p>
    </li><li data-md="">
     <p>Should American spelling be provided? (<code class="highlight"><c- n="">meter</c-></code> vs. <code class="highlight"><c- n="">metre</c-></code>, <code class="highlight"><c- n="">ton</c-></code> vs. <code class="highlight"><c- n="">tonne</c-></code>, ...)?</p>
    </li><li data-md="">
     <p>Should we provide <code class="highlight"><c- n="">seconds</c-><c- o="">&lt;</c-><c- b="">int</c-><c- o="">&gt;</c-></code> or stay with <code class="highlight"><c- n="">quantity</c-><c- o="">&lt;</c-><c- n="">second</c-><c- p="">,</c-> <c- b="">int</c-><c- o="">&gt;</c-></code> (<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#seconds-int">§ 13.8 Should we provide seconds&lt;int&gt; or stay with quantity&lt;second, int&gt;?</a>)?</p>
    </li><li data-md="">
     <p>What about <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">chrono</c-><c- o="">::</c-><c- n="">duration</c-></code> (<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#duration-interoperability">§ 13.5 Interoperability with std::chrono::duration</a>)?</p>
   </li></ol>
   <h3 class="heading settled" data-level="16.2" id="sg6"><span class="secno">16.2. </span><span class="content">SG6</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#sg6"></a></h3>
   <ol>
    <li data-md="">
     <p>Do we want to have built-in support for digital information <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity" id="ref-for-dimension-of-a-quantity②⑤">dimensions</a> and its <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#multiple-of-a-unit" id="ref-for-multiple-of-a-unit③">prefixes</a> in the initial version of the library?</p>
    </li><li data-md="">
     <p>Should we provide built-in support for some <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#off-system-measurement-unit" id="ref-for-off-system-measurement-unit">off-system units</a> or limit to SI units only?</p>
    </li><li data-md="">
     <p>Do we want to introduce a dedicated system type (<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#systems-support">§ 13.4 Should we support systems as a separate type?</a>)?</p>
    </li><li data-md="">
     <p>Do we want to require explicit representation casts between the same units of the same
dimension, or do we allow <code class="highlight"><c- n="">chrono</c-></code>-like implicit conversions (floating-point representation
and non-truncating integer conversions)?</p>
    </li><li data-md="">
     <p>Do we want to require explicit unit casts between different units of the same dimension,
or do we allow <code class="highlight"><c- n="">chrono</c-></code>-like implicit conversions (implicitly convert kilometre to metre)?</p>
    </li><li data-md="">
     <p>Do we agree with Kelvins only support for temperature and verbose conversion functions
for other <a data-link-type="dfn" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement" id="ref-for-unit-of-measurement③①">units</a> and absolute temperatures? Should affine types be provided
(<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#relative-vs-absolute">§ 13.3 Relative vs absolute quantity</a>)?</p>
    </li><li data-md="">
     <p>Do we want to provide support for runtime-specified conversions too (e.g. to support
currency)?</p>
    </li><li data-md="">
     <p>Should we provide support for dimensionless quantities or just use scalars (<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimensionless-quantities">§ 13.9 Should we provide support for dimensionless quantities?</a>)?</p>
    </li><li data-md="">
     <p>Do we want to standardize a Number concept (<a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#number">§ 13.10 Number concept</a>)?</p>
    </li><li data-md="">
     <p>Should constants be provided? If yes, how should updates to the constants be handled?
(Separate namespaces?)</p>
    </li><li data-md="">
     <p>Which SI standards should be supported (ISO 80000-1:2009, SI 2019) be provided? How
should updates to the ISO standard be handled? (Separate namespaces?)</p>
   </li></ol>
   <h3 class="heading settled" data-level="16.3" id="sg16"><span class="secno">16.3. </span><span class="content">SG16</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#sg16"></a></h3>
   <ol>
    <li data-md="">
     <p>Should we use strings containing characters outside the basic source character set?</p>
    </li><li data-md="">
     <p>Do we want a support for <code class="highlight"><c- n="">charN_t</c-></code> at all given the paltry support currently in the standard?</p>
    </li><li data-md="">
     <p>Should we provide different symbol presentation for <code class="highlight"><c- n="">charN_t</c-></code> vs <code class="highlight"><c- b="">char</c-></code> and <code class="highlight"><c- b="">wchar_t</c-></code>?</p>
    </li><li data-md="">
     <p>Should we provide localized unit names and symbols?</p>
    </li><li data-md="">
     <p>Should we provide <code class="highlight"><c- n="">std</c-><c- o="">::</c-><c- n="">basic_fixed_string</c-></code>?</p>
   </li></ol>
   <h2 class="heading settled" data-level="17" id="acknowledgements"><span class="secno">17. </span><span class="content">Acknowledgments</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#acknowledgements"></a></h2>
   <p>Special thanks and recognition goes to <a href="http://www.epam.com/">Epam Systems</a> for supporting my
membership in the ISO C++ Committee and the production of this proposal.</p>
   <p>I would also like to thank Jan A. Sende for his contributions to the <code class="highlight"><c- n="">mp</c-><c- o="">-</c-><c- n="">units</c-></code> library and
this document.</p>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don’t scroll to compensate for the ToC if we’re above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don’t know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn’t standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don’t have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we’re at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>
  <h2 class="no-num no-ref heading settled" id="index"><span class="content">Index</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#index"></a></h2>
  <h3 class="no-num no-ref heading settled" id="index-defined-here"><span class="content">Terms defined by this specification</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#index-defined-here"></a></h3>
  <ul class="index">
   <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension">base dimension</a><span>, in §4.2</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity">base quantity</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit">base unit</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-derived-unit">coherent derived unit</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-system-of-units">coherent system of units</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-dimension">derived dimension</a><span>, in §4.2</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-quantity">derived quantity</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-unit">derived unit</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity">dimension</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-of-dimension-one">dimensionless quantity</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity">dimension of a quantity</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-quantities">International System of Quantities</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units">International System of Units</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-quantities">ISQ</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#kind-of-quantity">kind</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#kind-of-quantity">kind of quantity</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement">measurement unit</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#multiple-of-a-unit">multiple of a unit</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#off-system-measurement-unit">off-system measurement unit</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#off-system-measurement-unit">off-system unit</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-of-dimension-one">quantities of dimension one</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity">quantity</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity">quantity dimension</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-of-dimension-one">quantity of dimension one</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-value">quantity value</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#reduced-dimension">reduced dimension</a><span>, in §4.2</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units">SI</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#submultiple-of-a-unit">submultiple of a unit</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities">system</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities">system of quantities</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units">system of units</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement">unit</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement">unit of measurement</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-value">value</a><span>, in §4.1</span>
   </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-value">value of a quantity</a><span>, in §4.1</span>
  </li></ul>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="normative"><span class="content">Normative References</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#normative"></a></h3>
  <dl>
   <dt id="biblio-iso_80000-1">[ISO_80000-1]
   </dt><dd><a href="https://www.iso.org/standard/30669.html">Quantities and units - Part 1: General</a>. URL: <a href="https://www.iso.org/standard/30669.html">https://www.iso.org/standard/30669.html</a>
  </dd></dl>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#informative"></a></h3>
  <dl>
   <dt id="biblio-benri">[BENRI]
   </dt><dd>Jan A. Sende. <a href="https://github.com/jansende/benri">benri</a>. URL: <a href="https://github.com/jansende/benri">https://github.com/jansende/benri</a>
   </dd><dt id="biblio-boostunits">[BOOST.UNITS]
   </dt><dd>Steven Watanabe; Matthias C. Schabel. <a href="https://www.boost.org/doc/libs/1_70_0/doc/html/boost_units.html">Boost.Units</a>. URL: <a href="https://www.boost.org/doc/libs/1_70_0/doc/html/boost_units.html">https://www.boost.org/doc/libs/1_70_0/doc/html/boost_units.html</a>
   </dd><dt id="biblio-bryan_units">[BRYAN_UNITS]
   </dt><dd>Bryan St. Amour. <a href="https://github.com/bstamour/units">units</a>. URL: <a href="https://github.com/bstamour/units">https://github.com/bstamour/units</a>
   </dd><dt id="biblio-clarence">[CLARENCE]
   </dt><dd>Steve Chawkins. <a href="https://www.latimes.com/archives/la-xpm-2001-feb-09-me-23253-story.html">Mismeasure for Measure</a>. URL: <a href="https://www.latimes.com/archives/la-xpm-2001-feb-09-me-23253-story.html">https://www.latimes.com/archives/la-xpm-2001-feb-09-me-23253-story.html</a>
   </dd><dt id="biblio-columbus">[COLUMBUS]
   </dt><dd><a href="https://en.wikipedia.org/wiki/Christopher_Columbus">Christopher Columbus</a>. URL: <a href="https://en.wikipedia.org/wiki/Christopher_Columbus">https://en.wikipedia.org/wiki/Christopher_Columbus</a>
   </dd><dt id="biblio-cppnow17-units">[CPPNOW17-UNITS]
   </dt><dd>Steven Watanabe. <a href="https://github.com/swatanabe/cppnow17-units">cppnow17-units</a>. URL: <a href="https://github.com/swatanabe/cppnow17-units">https://github.com/swatanabe/cppnow17-units</a>
   </dd><dt id="biblio-disney">[DISNEY]
   </dt><dd><a href="https://web.archive.org/web/20040209033827/http://www.olc.co.jp/news/20040121_01en.html">Cause of the Space Mountain Incident Determined at Tokyo Disneyland Park</a>. URL: <a href="https://web.archive.org/web/20040209033827/http://www.olc.co.jp/news/20040121_01en.html">https://web.archive.org/web/20040209033827/http://www.olc.co.jp/news/20040121_01en.html</a>
   </dd><dt id="biblio-ducharme_units">[DUCHARME_UNITS]
   </dt><dd>Vincent Ducharme. <a href="https://github.com/VincentDucharme/Units">units</a>. URL: <a href="https://github.com/VincentDucharme/Units">https://github.com/VincentDucharme/Units</a>
   </dd><dt id="biblio-flight_6316">[FLIGHT_6316]
   </dt><dd><a href="https://ntsb.gov/news/press-releases/Pages/Korean_Air_Flight_6316_MD-11_Shanghai_China_-_April_15_1999.aspx">Korean Air Flight 6316 MD-11, Shanghai, China - April 15, 1999</a>. URL: <a href="https://ntsb.gov/news/press-releases/Pages/Korean_Air_Flight_6316_MD-11_Shanghai_China_-_April_15_1999.aspx">https://ntsb.gov/news/press-releases/Pages/Korean_Air_Flight_6316_MD-11_Shanghai_China_-_April_15_1999.aspx</a>
   </dd><dt id="biblio-gimli_glider">[GIMLI_GLIDER]
   </dt><dd><a href="https://en.wikipedia.org/wiki/Gimli_Glider">Gimli Glider</a>. URL: <a href="https://en.wikipedia.org/wiki/Gimli_Glider">https://en.wikipedia.org/wiki/Gimli_Glider</a>
   </dd><dt id="biblio-mars_orbiter">[MARS_ORBITER]
   </dt><dd><a href="https://en.wikipedia.org/wiki/Mars_Climate_Orbiter">Mars Climate Orbiter</a>. URL: <a href="https://en.wikipedia.org/wiki/Mars_Climate_Orbiter">https://en.wikipedia.org/wiki/Mars_Climate_Orbiter</a>
   </dd><dt id="biblio-mikeford3_units">[MIKEFORD3_UNITS]
   </dt><dd>Michael Ford. <a href="https://github.com/mikeford3/units">units</a>. URL: <a href="https://github.com/mikeford3/units">https://github.com/mikeford3/units</a>
   </dd><dt id="biblio-mp-units">[MP-UNITS]
   </dt><dd>Mateusz Pusz. <a href="https://github.com/mpusz/units">mp-units</a>. URL: <a href="https://github.com/mpusz/units">https://github.com/mpusz/units</a>
   </dd><dt id="biblio-nic_units">[NIC_UNITS]
   </dt><dd>Nic Holthaus. <a href="https://github.com/nholthaus/units">units</a>. URL: <a href="https://github.com/nholthaus/units">https://github.com/nholthaus/units</a>
   </dd><dt id="biblio-p1930r0">[P1930R0]
   </dt><dd>Vincent Reverdy. <a href="https://wg21.link/p1930r0">Towards a standard unit systems library</a>. 7 October 2019. URL: <a href="https://wg21.link/p1930r0">https://wg21.link/p1930r0</a>
   </dd><dt id="biblio-physunits-ct-cpp11">[PHYSUNITS-CT-CPP11]
   </dt><dd>Martin Moene. <a href="https://github.com/martinmoene/PhysUnits-CT-Cpp11">PhysUnits-CT-Cpp11</a>. URL: <a href="https://github.com/martinmoene/PhysUnits-CT-Cpp11">https://github.com/martinmoene/PhysUnits-CT-Cpp11</a>
   </dd><dt id="biblio-walter_e_brown">[WALTER_E_BROWN]
   </dt><dd>Walter E. Brown. <a href="https://lss.fnal.gov/archive/1998/conf/Conf-98-328.pdf">Introduction to the SI Library of Unit-Based Computation</a>. URL: <a href="https://lss.fnal.gov/archive/1998/conf/Conf-98-328.pdf">https://lss.fnal.gov/archive/1998/conf/Conf-98-328.pdf</a>
   </dd><dt id="biblio-wild_rice">[WILD_RICE]
   </dt><dd><a href="https://www.bizjournals.com/eastbay/stories/2001/07/09/focus3.html">Manufacturers, exporters think metric</a>. URL: <a href="https://www.bizjournals.com/eastbay/stories/2001/07/09/focus3.html">https://www.bizjournals.com/eastbay/stories/2001/07/09/focus3.html</a>
  </dd></dl>
  <aside class="dfn-panel" data-for="quantity">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity">#quantity</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity">4.1. ISO 80000-1:2009(E) definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A4">(6)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A5">(7)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A6">(8)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A7">(9)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A8">(10)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0%E2%93%AA">(11)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0%E2%91%A0">(12)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0%E2%91%A1">(13)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0%E2%91%A2">(14)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0%E2%91%A3">(15)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0%E2%91%A4">(16)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0%E2%91%A5">(17)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0%E2%91%A6">(18)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0%E2%91%A7">(19)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A0%E2%91%A8">(20)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1%E2%93%AA">(21)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1%E2%91%A0">(22)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1%E2%91%A1">(23)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1%E2%91%A2">(24)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1%E2%91%A3">(25)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1%E2%91%A4">(26)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1%E2%91%A5">(27)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1%E2%91%A6">(28)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1%E2%91%A7">5.1.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A1%E2%91%A8">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2%E2%93%AA">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2%E2%91%A0">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2%E2%91%A1">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2%E2%91%A2">(6)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2%E2%91%A3">(7)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2%E2%91%A4">(8)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2%E2%91%A5">(9)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2%E2%91%A6">(10)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2%E2%91%A7">(11)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A2%E2%91%A8">(12)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3%E2%93%AA">5.4.2. Design</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3%E2%91%A0">5.5.2. Design</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3%E2%91%A1">13.3. Relative vs absolute quantity</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3%E2%91%A2">13.8. Should we provide seconds&lt;int&gt; or stay with quantity&lt;second, int&gt;?</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3%E2%91%A3">13.9. Should we provide support for dimensionless quantities?</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3%E2%91%A4">13.11. What about Unicode?</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3%E2%91%A5">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3%E2%91%A6">15.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3%E2%91%A7">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity%E2%91%A3%E2%91%A8">(3)</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="kind-of-quantity">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#kind-of-quantity">#kind-of-quantity</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-kind-of-quantity">4.1. ISO 80000-1:2009(E) definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-kind-of-quantity%E2%91%A0">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-kind-of-quantity%E2%91%A1">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-kind-of-quantity%E2%91%A2">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-kind-of-quantity%E2%91%A3">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-kind-of-quantity%E2%91%A4">(6)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-kind-of-quantity%E2%91%A5">13.9. Should we provide support for dimensionless quantities?</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="system-of-quantities">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-quantities">#system-of-quantities</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities">4.1. ISO 80000-1:2009(E) definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A1">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A2">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A3">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A4">(6)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A5">(7)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A6">(8)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A7">(9)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A8">(10)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0%E2%93%AA">(11)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0%E2%91%A0">5.1.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0%E2%91%A1">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0%E2%91%A2">5.5. benri</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0%E2%91%A3">8.2. Generic programming with concepts</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0%E2%91%A4">9. std::ratio on steroids</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0%E2%91%A5">11. Easy to use and hard to abuse</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0%E2%91%A6">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0%E2%91%A7">13.4. Should we support systems as a separate type?</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A0%E2%91%A8">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A1%E2%93%AA">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A1%E2%91%A0">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A1%E2%91%A1">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-quantities%E2%91%A1%E2%91%A2">(6)</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="base-quantity">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-quantity">#base-quantity</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity">4.1. ISO 80000-1:2009(E) definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A0">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A1">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A2">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A3">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A4">(6)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A5">(7)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A6">4.2. Other definitions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A7">6. Fundamental concerns with current solutions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A8">7.1. Type aliasing issues</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A0%E2%93%AA">10. Extensibility</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A0%E2%91%A0">13.3. Relative vs absolute quantity</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-quantity%E2%91%A0%E2%91%A1">13.6. Should we provide integral UDLs?</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="derived-quantity">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-quantity">#derived-quantity</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-quantity">4.1. ISO 80000-1:2009(E) definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-quantity%E2%91%A0">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-quantity%E2%91%A1">(3)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-quantity%E2%91%A2">4.2. Other definitions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-quantity%E2%91%A3">7.1. Type aliasing issues</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-quantity%E2%91%A4">10. Extensibility</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-quantity%E2%91%A5">13.4. Should we support systems as a separate type?</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="international-system-of-quantities">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-quantities">#international-system-of-quantities</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-quantities">4.1. ISO 80000-1:2009(E) definitions</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="dimension-of-a-quantity">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#dimension-of-a-quantity">#dimension-of-a-quantity</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity">4.1. ISO 80000-1:2009(E) definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A1">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A2">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A3">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A4">(6)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A5">(7)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A6">(8)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A7">(9)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A8">4.2. Other definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0%E2%93%AA">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0%E2%91%A0">5.4.2. Design</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0%E2%91%A1">8. Limiting intermediate quantity value conversions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0%E2%91%A2">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0%E2%91%A3">13.1. How to represent SI prefixes and derived units?</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0%E2%91%A4">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0%E2%91%A5">13.3. Relative vs absolute quantity</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0%E2%91%A6">13.4. Should we support systems as a separate type?</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0%E2%91%A7">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A0%E2%91%A8">13.5. Interoperability with std::chrono::duration</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A1%E2%93%AA">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A1%E2%91%A0">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A1%E2%91%A1">(4)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A1%E2%91%A2">13.7. quantity&lt;dim_length, metre&gt; or quantity&lt;metre&gt;?</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A1%E2%91%A3">15.2. Design</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-dimension-of-a-quantity%E2%91%A1%E2%91%A4">16.2. SG6</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="quantity-of-dimension-one">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-of-dimension-one">#quantity-of-dimension-one</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity-of-dimension-one">4.1. ISO 80000-1:2009(E) definitions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity-of-dimension-one%E2%91%A0">5.1.2. Design</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity-of-dimension-one%E2%91%A1">13.9. Should we provide support for dimensionless quantities?</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity-of-dimension-one%E2%91%A2">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity-of-dimension-one%E2%91%A3">(3)</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="unit-of-measurement">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#unit-of-measurement">#unit-of-measurement</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement">4.1. ISO 80000-1:2009(E) definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A2">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A3">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A4">(6)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A5">(7)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A6">5.1.1. Usage example</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A7">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A8">5.1.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0%E2%93%AA">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0%E2%91%A0">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0%E2%91%A1">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0%E2%91%A2">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0%E2%91%A3">(6)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0%E2%91%A4">(7)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0%E2%91%A5">5.4.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0%E2%91%A6">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0%E2%91%A7">5.5.1. Usage example</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A0%E2%91%A8">5.5.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1%E2%93%AA">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1%E2%91%A0">8. Limiting intermediate quantity value conversions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1%E2%91%A1">10. Extensibility</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1%E2%91%A2">13.1. How to represent SI prefixes and derived units?</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1%E2%91%A3">13.2. NTTP usage</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1%E2%91%A4">13.4. Should we support systems as a separate type?</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1%E2%91%A5">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1%E2%91%A6">13.8. Should we provide seconds&lt;int&gt; or stay with quantity&lt;second, int&gt;?</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1%E2%91%A7">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A1%E2%91%A8">13.11. What about Unicode?</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A2%E2%93%AA">15.2. Design</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-unit-of-measurement%E2%91%A2%E2%91%A0">16.2. SG6</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="base-unit">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-unit">#base-unit</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit">4.1. ISO 80000-1:2009(E) definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A1">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A2">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A3">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A4">(6)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A5">(7)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A6">5.1.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A7">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A8">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0%E2%93%AA">(4)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0%E2%91%A0">5.4.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0%E2%91%A1">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0%E2%91%A2">6. Fundamental concerns with current solutions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0%E2%91%A3">8. Limiting intermediate quantity value conversions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0%E2%91%A4">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0%E2%91%A5">8.1. Template arguments type deduction</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0%E2%91%A6">9. std::ratio on steroids</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0%E2%91%A7">13.1. How to represent SI prefixes and derived units?</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-unit%E2%91%A0%E2%91%A8">13.4. Should we support systems as a separate type?</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="derived-unit">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-unit">#derived-unit</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-unit">4.1. ISO 80000-1:2009(E) definitions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-unit%E2%91%A0">8.1. Template arguments type deduction</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-unit%E2%91%A1">9. std::ratio on steroids</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-unit%E2%91%A2">13.1. How to represent SI prefixes and derived units?</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-unit%E2%91%A3">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-unit%E2%91%A4">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-unit%E2%91%A5">(4)</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="coherent-derived-unit">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-derived-unit">#coherent-derived-unit</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-coherent-derived-unit">4.1. ISO 80000-1:2009(E) definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-coherent-derived-unit%E2%91%A0">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-coherent-derived-unit%E2%91%A1">5.1.1. Usage example</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-coherent-derived-unit%E2%91%A2">8. Limiting intermediate quantity value conversions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-coherent-derived-unit%E2%91%A3">13.1. How to represent SI prefixes and derived units?</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-coherent-derived-unit%E2%91%A4">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-coherent-derived-unit%E2%91%A5">(3)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-coherent-derived-unit%E2%91%A6">13.9. Should we provide support for dimensionless quantities?</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="system-of-units">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#system-of-units">#system-of-units</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-units">4.1. ISO 80000-1:2009(E) definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-units%E2%91%A0">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-units%E2%91%A1">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-units%E2%91%A2">(4)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-units%E2%91%A3">5.1.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-units%E2%91%A4">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-units%E2%91%A5">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-units%E2%91%A6">(4)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-system-of-units%E2%91%A7">13.4. Should we support systems as a separate type?</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="coherent-system-of-units">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#coherent-system-of-units">#coherent-system-of-units</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-coherent-system-of-units">4.1. ISO 80000-1:2009(E) definitions</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="off-system-measurement-unit">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#off-system-measurement-unit">#off-system-measurement-unit</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-off-system-measurement-unit">16.2. SG6</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="international-system-of-units">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#international-system-of-units">#international-system-of-units</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units">4.1. ISO 80000-1:2009(E) definitions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A0">5.1.2. Design</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A1">5.3.2. Design</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A2">5.4.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A3">(2)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A4">13.4. Should we support systems as a separate type?</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A5">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A6">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A7">(4)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A8">(5)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A0%E2%93%AA">(6)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-international-system-of-units%E2%91%A0%E2%91%A0">(7)</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="multiple-of-a-unit">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#multiple-of-a-unit">#multiple-of-a-unit</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-multiple-of-a-unit">6. Fundamental concerns with current solutions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-multiple-of-a-unit%E2%91%A0">9. std::ratio on steroids</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-multiple-of-a-unit%E2%91%A1">13.1. How to represent SI prefixes and derived units?</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-multiple-of-a-unit%E2%91%A2">16.2. SG6</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="submultiple-of-a-unit">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#submultiple-of-a-unit">#submultiple-of-a-unit</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-submultiple-of-a-unit">6. Fundamental concerns with current solutions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-submultiple-of-a-unit%E2%91%A0">9. std::ratio on steroids</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="quantity-value">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#quantity-value">#quantity-value</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-quantity-value">6. Fundamental concerns with current solutions</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="base-dimension">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#base-dimension">#base-dimension</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-dimension">4.2. Other definitions</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-dimension%E2%91%A0">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-dimension%E2%91%A1">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-dimension%E2%91%A2">(4)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-dimension%E2%91%A3">5.1.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-dimension%E2%91%A4">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-dimension%E2%91%A5">(3)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-dimension%E2%91%A6">(4)</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-base-dimension%E2%91%A7">5.5.2. Design</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="derived-dimension">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#derived-dimension">#derived-dimension</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-dimension">4.2. Other definitions</a>
    </li><li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-dimension%E2%91%A0">5.1.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-dimension%E2%91%A1">(2)</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-derived-dimension%E2%91%A2">(3)</a>
   </li></ul>
  </aside>
  <aside class="dfn-panel" data-for="reduced-dimension">
   <b><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#reduced-dimension">#reduced-dimension</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-reduced-dimension">5.1.2. Design</a> <a href="https://mpusz.github.io/wg21-papers/papers/1935_a_cpp_approach_to_physical_units.html#ref-for-reduced-dimension%E2%91%A0">(2)</a>
   </li></ul>
  </aside>
<script>/* script-dfn-panel */

document.body.addEventListener("click", function(e) {
    var queryAll = function(sel) { return [].slice.call(document.querySelectorAll(sel)); }
    // Find the dfn element or panel, if any, that was clicked on.
    var el = e.target;
    var target;
    var hitALink = false;
    while(el.parentElement) {
        if(el.tagName == "A") {
            // Clicking on a link in a <dfn> shouldn't summon the panel
            hitALink = true;
        }
        if(el.classList.contains("dfn-paneled")) {
            target = "dfn";
            break;
        }
        if(el.classList.contains("dfn-panel")) {
            target = "dfn-panel";
            break;
        }
        el = el.parentElement;
    }
    if(target != "dfn-panel") {
        // Turn off any currently "on" or "activated" panels.
        queryAll(".dfn-panel.on, .dfn-panel.activated").forEach(function(el){
            el.classList.remove("on");
            el.classList.remove("activated");
        });
    }
    if(target == "dfn" && !hitALink) {
        // open the panel
        var dfnPanel = document.querySelector(".dfn-panel[data-for='" + el.id + "']");
        if(dfnPanel) {
            dfnPanel.classList.add("on");
            var rect = el.getBoundingClientRect();
            dfnPanel.style.left = window.scrollX + rect.right + 5 + "px";
            dfnPanel.style.top = window.scrollY + rect.top + "px";
            var panelRect = dfnPanel.getBoundingClientRect();
            var panelWidth = panelRect.right - panelRect.left;
            if(panelRect.right > document.body.scrollWidth && (rect.left - (panelWidth + 5)) > 0) {
                // Reposition, because the panel is overflowing
                dfnPanel.style.left = window.scrollX + rect.left - (panelWidth + 5) + "px";
            }
        } else {
            console.log("Couldn't find .dfn-panel[data-for='" + el.id + "']");
        }
    } else if(target == "dfn-panel") {
        // Switch it to "activated" state, which pins it.
        el.classList.add("activated");
        el.style.left = null;
        el.style.top = null;
    }

});
</script></body></html>