<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>P1039R0: I got you, FAM - Flexible Array Members for C++</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) {
		/* 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;
    }
  </style>
  <meta content="Bikeshed version 7d8ce2d953ffaca8e344c0dab76f68fc292738a6" name="generator">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="ba13c31ce1d3dca428223fcf2aa95f70c2c59827" 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-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-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>
<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-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>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P1039R0<br>I got you, FAM - Flexible Array Members for C++</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2018-10-19">2018-10-19</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>Authors:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:phdofthehouse@gmail.com">JeanHeyd Meneide</a>
     <dd>
      <dd class="editor p-author h-card vcard"><span class="p-name fn">Arvid Gerstmann</span>
     <dd>
      <dd class="editor p-author h-card vcard"><span class="p-name fn">Nicole Mazzuca</span>
     <dt>Audience:
     <dd>EWG
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Latest:
     <dd><a href="https://thephd.github.io/vendor/future_cxx/blob/master/papers/d1039.html">https://thephd.github.io/vendor/future_cxx/blob/master/papers/d1039.html</a>
     <dt>Reply To:
     <dd><a href="mailto:phdofthehouse@gmail.com">JeanHeyd Meneide</a> | <a href="https://twitter.com/thephantomderp">@thephantomderp</a>
    </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>Bringing C99 Flexible Array Member (FAM) syntax into C++ in a safe, well-defined manner.</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="#changelog"><span class="secno">1</span> <span class="content">Revision History</span></a>
     <ol class="toc">
      <li><a href="#changelog-r0"><span class="secno">1.1</span> <span class="content">Revision 0 - November 26th, 2018</span></a>
     </ol>
    <li>
     <a href="#motivation"><span class="secno">2</span> <span class="content">Motivation</span></a>
     <ol class="toc">
      <li><a href="#motivation-contiguous"><span class="secno">2.1</span> <span class="content">Contiguous Fixed Header and Data</span></a>
      <li><a href="#motivation-vla"><span class="secno">2.2</span> <span class="content">Variable Length Arrays?</span></a>
      <li><a href="#motivation-rsc"><span class="secno">2.3</span> <span class="content">Runtime Sized Classes?</span></a>
      <li><a href="#motivation-uses"><span class="secno">2.4</span> <span class="content">Places of Application</span></a>
     </ol>
    <li>
     <a href="#design"><span class="secno">3</span> <span class="content">Design</span></a>
     <ol class="toc">
      <li>
       <a href="#design-features"><span class="secno">3.1</span> <span class="content">Features and Explicit Opt-in</span></a>
       <ol class="toc">
        <li><a href="#design-feature-create"><span class="secno">3.1.1</span> <span class="content">Feature: creation of FAM types is limited to certain expressions</span></a>
        <li><a href="#design-feature-traits"><span class="secno">3.1.2</span> <span class="content">Feature: Traits and Types</span></a>
        <li><a href="#design-feature-c"><span class="secno">3.1.3</span> <span class="content">Feature: C Compatibility</span></a>
        <li>
         <a href="#design-feature-special_members"><span class="secno">3.1.4</span> <span class="content">Feature: Special Members</span></a>
         <ol class="toc">
          <li><a href="#design-feature-special_members-constructor"><span class="secno">3.1.4.1</span> <span class="content">Special Member: Constructor of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-></code></span></a>
          <li><a href="#design-feature-special_members-destructor"><span class="secno">3.1.4.2</span> <span class="content">Destructor</span></a>
          <li><a href="#design-feature-special_members-copy_move"><span class="secno">3.1.4.3</span> <span class="content">Copy/Move Constructor and Assignment</span></a>
         </ol>
       </ol>
      <li>
       <a href="#design-demo"><span class="secno">3.2</span> <span class="content">Examples</span></a>
       <ol class="toc">
        <li><a href="#design-demo-simple_trivial"><span class="secno">3.2.1</span> <span class="content">Simple: Trivial</span></a>
        <li><a href="#design-demo-simple_non_trivial"><span class="secno">3.2.2</span> <span class="content">Simple: Non-Trivial</span></a>
        <li><a href="#design-demo-specialize"><span class="secno">3.2.3</span> <span class="content">Specialized Traits</span></a>
        <li><a href="#design-demo-udp"><span class="secno">3.2.4</span> <span class="content">UDP Packets</span></a>
       </ol>
     </ol>
    <li>
     <a href="#wording"><span class="secno">4</span> <span class="content">Proposed Wording</span></a>
     <ol class="toc">
      <li><a href="#wording-feature"><span class="secno">4.1</span> <span class="content">Proposed Feature Test Macro and Header</span></a>
      <li><a href="#wording-intent"><span class="secno">4.2</span> <span class="content">Intent</span></a>
      <li><a href="#wording-synopsis"><span class="secno">4.3</span> <span class="content">Synopsis</span></a>
     </ol>
    <li><a href="#acknowledgements"><span class="secno">5</span> <span class="content">Acknowledgements</span></a>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="changelog"><span class="secno">1. </span><span class="content">Revision History</span><a class="self-link" href="#changelog"></a></h2>
   <h3 class="heading settled" data-level="1.1" id="changelog-r0"><span class="secno">1.1. </span><span class="content">Revision 0 - November 26th, 2018</span><a class="self-link" href="#changelog-r0"></a></h3>
   <p>Initial release.</p>
   <h2 class="heading settled" data-level="2" id="motivation"><span class="secno">2. </span><span class="content">Motivation</span><a class="self-link" href="#motivation"></a></h2>
   <p>C99 defined Flexible Array Members (FAMs), a way of having a dynamic array of similarly typed data laid out in a contiguous, flat format beyond an initial sequence in a struct. Flexible Array Members have been used to great success to interface with many low-latency networking and binary protocols and formats, making it the go-to choice for working with large amounts of data prefixed by header values. The key in its success in high-performance systems, components and software such as Operating Systems, Financial Trading and Tracking, Networking, and Firmware is the guarantee that there will be at most one allocation for a variably-sized structure.</p>
   <p>Despite this success, nothing like this exists in C++, making its usage unspecified behavior by omission. All compilers warn or error about its usage when working with C from C++ that uses it, making it hard to confidently employ the C technique in C++ code bases. This presents a fairly painful chasm between what is possible in C and what is possible in C++, and prevents Bjarne Stroustrup’s earliest vision of making it possible to fully cover and subsume all of C with C++.</p>
   <p>This paper proposes a safe, well-reasoned extension of the C++ Language in order to accommodate and properly define FAMs for C++ that is compatible with the C99 standard.</p>
   <h3 class="heading settled" data-level="2.1" id="motivation-contiguous"><span class="secno">2.1. </span><span class="content">Contiguous Fixed Header and Data</span><a class="self-link" href="#motivation-contiguous"></a></h3>
   <p>There are many data structures in program, on disk, and on wire that are a fixed header plus a chunk of variably sized data. C++ has no way to represent this in a single allocation without the use of <code class="highlight"><c- b>char</c-></code> buffers or <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>aligned_storage</c-></code> plus a good, hefty helping of type punning/<code class="highlight"><c- k>reinterpret_cast</c-></code>. FAM types guarantee not only contiguous layout, but at most one allocation to have all of the data required. This makes them ideal in high-performance environments where multiple allocations for a single packet of data are unacceptable, and usable in the other scenarios without locking out usability and performance benefits.</p>
   <h3 class="heading settled" data-level="2.2" id="motivation-vla"><span class="secno">2.2. </span><span class="content">Variable Length Arrays?</span><a class="self-link" href="#motivation-vla"></a></h3>
   <p>This proposal is <strong>not</strong> for variable length arrays. It does <strong>not</strong> cover all of the wants or needs that the previously proposed <a data-link-type="biblio" href="#biblio-n3662">[n3662]</a> does. Variable Length Arrays also do not cover all of the things Flexible Array Members do. Notably, Flexible Array Members only cover the case where memory is explicitly allocated for it already. Variable Length Arrays also do not accommodate heterogeneous data in their structure. This FAM specification does not include allowing anything but 0-sized default construction of a FAM type when an automatic storage duration value is created. This restriction may be lifted at another time in another revision, or in another paper entirely. This paper focuses exclusively on covering the case of working with a pre-allocated buffer of space that the user has explicitly requested. (That pre-allocated buffer can be spelled <code class="highlight"><c- k>new</c-> <c- n>my_fam_type</c-><c- p>(...)</c-></code>).</p>
   <h3 class="heading settled" data-level="2.3" id="motivation-rsc"><span class="secno">2.3. </span><span class="content">Runtime Sized Classes?</span><a class="self-link" href="#motivation-rsc"></a></h3>
   <p>Classes of runtime size that also modified <code class="highlight"><c- k>sizeof</c-><c- p>()</c-></code> were explored in Jeff Snyder and Richard Smith’s <a data-link-type="biblio" href="#biblio-n4025">[n4025]</a>. This proposal believes that the paper modified too much and went too far with what it changed about the core language. In particular, this paper instead focuses on the following:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- k>sizeof</c-><c- p>()</c-></code> will continue to always be well-formed and will never be ill-formed</p>
    <li data-md>
     <p>it does not attempt to cover or replace variable length arrays, which is a divisive topic currently unable to be solved</p>
    <li data-md>
     <p>it does not allow multiple or multiply-nested runtime classes</p>
   </ul>
   <h3 class="heading settled" data-level="2.4" id="motivation-uses"><span class="secno">2.4. </span><span class="content">Places of Application</span><a class="self-link" href="#motivation-uses"></a></h3>
   <p>FAMs are used in the wild for many binary formats, particularly those that find themselves need to precisely align and pack data according to transfer formats. It is also found in operating system and  Some ripe places to use, and uses of, FAMs in the wild:</p>
   <ul>
    <li data-md>
     <p>Embedded and ARM code often use it to map regions of memory with prefixed data,</p>
    <li data-md>
     <p>Financial Bid and Transaction Protocols (such as OMX before reaching down into sub item headers, subscriber lists and set event lists),</p>
    <li data-md>
     <p>Heterogeneous Computing, such as <a data-link-type="biblio" href="#biblio-hsa-brig">HSA BRIG modules</a>,</p>
    <li data-md>
     <p>Networking protocols, such as</p>
     <ul>
      <li data-md>
       <p>the ubiquitous lower layers such as <a data-link-type="biblio" href="#biblio-tcp-ip">Internet Protocol (IP),Transmission Control Protocol (TCP)</a>, and <a data-link-type="biblio" href="#biblio-udp">User Datagram Protocol (UDP)</a>, Link and similar in both userspace and kernel "ring0" space,</p>
      <li data-md>
       <p>the increasingly popular [websockets|WebSockets],</p>
     </ul>
    <li data-md>
     <p>Operating System calls and system packages,</p>
     <ul>
      <li data-md>
       <p>Windows in several locations, including <a data-link-type="biblio" href="#biblio-usn-record-v4">USN Journals</a> and <a data-link-type="biblio" href="#biblio-file_notify_information">ReadDirectoryChangesW</a> return value,</p>
      <li data-md>
       <p>all over the Linux Kernel (including <a data-link-type="biblio" href="#biblio-linux-cgroups">CGroups</a>, variable string data, and more),</p>
     </ul>
    <li data-md>
     <p>High-performance storage solutions,</p>
     <ul>
      <li data-md>
       <p><a data-link-type="biblio" href="#biblio-redis">Redis</a> makes extensive use of them</p>
     </ul>
    <li data-md>
     <p>LLVM and Clang,</p>
     <ul>
      <li data-md>
       <p>Tail-allocated data structures are used frequently to save on the number of allocations even if they do not use the Flexible Array Member syntax directly,</p>
     </ul>
    <li data-md>
     <p>All over typical C code,</p>
     <ul>
      <li data-md>
       <p><a data-link-type="biblio" href="#biblio-sanlock-ocaml">Sanlock shared storage lock</a>,</p>
      <li data-md>
       <p><a data-link-type="biblio" href="#biblio-spirv-cross">[spirv-cross]</a>,</p>
     </ul>
    <li data-md>
     <p>and, many, many more places.</p>
   </ul>
   <p>This proposal’s Flexible Array Members cover a good portion of the use cases found above.</p>
   <h2 class="heading settled" data-level="3" id="design"><span class="secno">3. </span><span class="content">Design</span><a class="self-link" href="#design"></a></h2>
   <p>In order to provide a reasonable feature set without having to compromise the entire language, FAMs</p>
   <ul>
    <li data-md>
     <p>implicitly mark their containing <code class="highlight"><c- k>struct</c-></code>s/<code class="highlight"><c- k>class</c-></code>es as <code class="highlight"><c- k>final</c-></code>,</p>
    <li data-md>
     <p>cannot be a sub-object of an array,</p>
    <li data-md>
     <p>must be the last member of their containing type,</p>
    <li data-md>
     <p>must have their containing type be the last member of any types it is used in,</p>
    <li data-md>
     <p>and, do not contribute to the <code class="highlight"><c- k>sizeof</c-><c- p>()</c-></code> for the containing type, except for any padding necessary to reach the start of the flexible array member.</p>
   </ul>
   <p>These sets of constraints help us properly integrate FAMs into the C++ language and properly matches the constraints of the C language. Our goals for proposing Flexible Array Members is simple:</p>
   <ol>
    <li data-md>
     <p>Allow a succinct, portable way for C++ to refer to memory that is preceded by a header and laid out with its associated data payload in a contiguous manner.</p>
    <li data-md>
     <p>Ease the porting of C code into C++ for users who wish to have correct, well-specified and well-defined behavior of their code.</p>
    <li data-md>
     <p>Enable developers who must work with the data laid out in #1 to rely on standards-compliant, reasonable constructs in code.</p>
   </ol>
   <p>Furthermore, this proposal aims to provide a set of overridable traits that -- if specified for a type -- will override how member count and data size are handled in C++. If the traits are not overridden, then the compiler is allowed to continue to use implementation-defined mechanisms for managing, controlling and deleting the memory.</p>
   <p>These restrictions may seem overbearing, but they are for the good of the features laid out below. This proposal’s restrictions are also forward-compatible: they can be relaxed or enhanced later without breaking old code, much like how <code class="highlight"><c- k>constexpr</c-></code> was initially constrained and then generally relaxed later on once the power of the feature was fully understood.</p>
   <h3 class="heading settled" data-level="3.1" id="design-features"><span class="secno">3.1. </span><span class="content">Features and Explicit Opt-in</span><a class="self-link" href="#design-features"></a></h3>
   <p>Much of Flexible Array Member use will be coming from C code. It is imperative this code is well-formed, even when compiled as C++. Therefore, many of the operations that Flexible Array Members for C++ utilize must be completely defaulted. Consider the following simple FAM:</p>
<pre class="highlight"><c- k>struct</c-> <c- n>simple_fam_t</c-> <c- p>{</c->
	<c- b>int</c-> <c- n>data</c-><c- p>[];</c->
<c- p>};</c->
</pre>
   <p>This is valid code and under this proposal will continue to remain valid, without modification. This proposal does so through the application of the following features below.</p>
   <h4 class="heading settled" data-level="3.1.1" id="design-feature-create"><span class="secno">3.1.1. </span><span class="content">Feature: creation of FAM types is limited to certain expressions</span><a class="self-link" href="#design-feature-create"></a></h4>
   <p>FAM types can be created with <code class="highlight"><c- k>new</c-></code>, but may not be used with array <code class="highlight"><c- k>new</c-></code>. They can also be created with placement new.</p>
   <p>When used as an automatic storage variable (e.g. "on the stack"), the flexible array member types just have a size that includes the non-FAM members, plus any padding necessary to get to the start of the FAM. This proposal allows automatic storage duration versions of the type as it mimics exactly how C handles it: a struct with an empty Flexible Array Member.</p>
   <p>For the heap, FAMs are also still analogous with C. When allocated on the heap with <code class="highlight"><c- n>malloc</c-></code> in C, the user makes room for it explicitly then performs type-punning of the returned <code class="highlight"><c- b>void</c-><c- o>*</c-></code> data. In C++, this proposal would allow actually putting data in this type through the use of <code class="highlight"><c- k>new</c-></code> as a proper analogy.</p>
   <p>This matches C and also prevents a large myriad of cases where the type’s boundaries are not clear and would violate invariants. For example, in the case of <code class="highlight"><c- k>new</c-> <c- n>simple_fam_t</c-><c- p>[</c-><c- mi>20</c-><c- p>];</c-></code>, it is impossible to know where one flexible array member begins and the next ends without some sort of serious book keeping. The only allowed version of creating a flexible array member is with <code class="highlight"><c- k>new</c-> <c- nf>some_fam_type</c-><c- p>(...);</c-></code>.</p>
   <h4 class="heading settled" data-level="3.1.2" id="design-feature-traits"><span class="secno">3.1.2. </span><span class="content">Feature: Traits and Types</span><a class="self-link" href="#design-feature-traits"></a></h4>
   <p>The proposed Flexible Array Members in C++ will feature a set of traits a user can override for their user-defined type. It also helps anyone thinking about Flexible Array Members for C++ to visualize the trait, type and functions. There are 3 traits and 1 type contained in the header <code class="highlight"><c- o>&lt;</c-><c- n>fam</c-><c- o>></c-></code> and <code class="highlight"><c- o>&lt;</c-><c- n>type_traits</c-><c- o>></c-></code>. One of them is overridable. Here is the full set of traits:</p>
<pre class="highlight"><c- c1>// header &lt;fam></c->

<c- k>namespace</c-> <c- n>std</c-> <c- p>{</c->
	<c- k>struct</c-> <c- n>fam_size</c-> <c- p>{</c->
		<c- n>fam_size</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>element_count</c-> <c- o>=</c-> <c- mi>0</c-><c- p>)</c-> <c- k>noexcept</c-> <c- o>:</c-> <c- n>n</c-><c- p>(</c-><c- n>element_count</c-><c- p>)</c-> <c- p>{}</c->

		<c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>size</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-> <c- p>{</c->
			<c- k>return</c-> <c- n>n</c-><c- p>;</c->
		<c- p>}</c->

	<c- k>private</c-><c- o>:</c->
		<c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>n</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>></c->
	<c- k>struct</c-> <c- n>fam_traits</c-> <c- p>{</c->
		<c- k>constexpr</c-> <c- k>static</c-> <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>size</c-> <c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
	<c- p>}</c->
<c- p>}</c->
</pre>
<pre class="highlight"><c- c1>// additions to </c->
<c- c1>// header &lt;type_traits></c->

<c- k>namespace</c-> <c- n>std</c-> <c- p>{</c->
	<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
	<c- k>struct</c-> <c- nl>is_fam</c->  <c- p>:</c-> <c- n>std</c-><c- o>::</c-><c- n>integral_constant</c-><c- o>&lt;</c->
		<c- b>bool</c-><c- p>,</c-> <c- d>/* compiler intrinsic here */</c->
	<c- o>></c-> <c- p>{};</c->

	<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
	<c- k>using</c-> <c- n>is_fam_v</c-> <c- o>=</c-> <c- n>is_fam</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>value</c-><c- p>;</c->

	<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
	<c- k>struct</c-> <c- n>fam_element</c-> <c- p>{</c->
		<c- k>using</c-> <c- n>type</c-> <c- o>=</c-> <c- d>/* compiler intrinsic here */</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>></c->
	<c- k>using</c-> <c- n>fam_element_t</c-> <c- o>=</c-> <c- n>fam_element</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>type</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>The various type queries here help programmers know if a type is a flexible array member and get the element of that type. The user can also use the traits to query the number of elements of a flexible array member for a given user-defined type with which this information is overridden. For example, consider the following:</p>
<pre class="highlight"><c- cp>#include</c-> &lt;fam>
<c- cp>#include</c-> &lt;cstddef>

<c- k>struct</c-> <c- n>id_list</c-> <c- p>{</c->
	<c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>len</c-><c- p>;</c->
	<c- b>int64_t</c-> <c- n>ids</c-><c- p>[];</c->

	<c- n>id_list</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-> <c- n>fs</c-><c- p>)</c-> <c- o>:</c-> <c- n>len</c-><c- p>(</c-><c- n>fs</c-><c- p>.</c-><c- n>size</c-><c- p>())</c-> <c- p>{}</c->
<c- p>};</c->

<c- k>namespace</c-> <c- n>std</c-> <c- p>{</c->
	<c- k>template</c-> <c- o>&lt;></c->
	<c- k>struct</c-> <c- n>fam_traits</c-><c- o>&lt;</c-><c- n>id_list</c-><c- o>></c-> <c- p>{</c->
		<c- k>constexpr</c-> <c- k>static</c-> <c- n>size_type</c-> <c- n>size</c-> <c- p>(</c-><c- k>const</c-> <c- n>id_list</c-><c- o>&amp;</c-> <c- n>il</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
			<c- k>return</c-> <c- n>il</c-><c- p>.</c-><c- n>len</c-><c- p>;</c->
		<c- p>}</c->
	<c- p>}</c->
<c- p>}</c->
</pre>
   <p>What this represents is a contract between the user and the C++ implementation. You are telling the implementation that you already manage and store the size yourself: thusly, the implementation knows to not bother storing any information about the number of elements, because those users are promising to construct and initialize <code class="highlight"><c- n>len</c-></code> with the proper length and to book keep the number of created elements. This is relevant for both the automatically generated constructors and destructor in <a href="#design-feature-special_members">§3.1.4 Feature: Special Members</a>.</p>
   <h4 class="heading settled" data-level="3.1.3" id="design-feature-c"><span class="secno">3.1.3. </span><span class="content">Feature: C Compatibility</span><a class="self-link" href="#design-feature-c"></a></h4>
   <p>The size reported by the <code class="highlight"><c- n>fam_traits</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>size</c-><c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-><c- p>)</c-></code> static function can be greater than or equal to the number of elements actually used for any type <code class="highlight"><c- n>T</c-></code> where <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_trivial_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> evaluates to <code class="highlight">true</code>.</p>
   <p>"What in the world...?" Is what some people will say upon this realization, but there is an important point here. Consider the following absolutely confirming C implementation: the user asks for an object with a FAM <code class="highlight"><c- b>int</c-><c- p>[]</c-></code>, requiring 20 <code class="highlight"><c- b>int</c-></code>s worth of space: an implementation can give the user space for 30 <code class="highlight"><c- b>int</c-></code>s. Furthermore, any trivial type (every type <code class="highlight"><c- n>T</c-></code> from C has <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_trivial_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> evaluate to true) does not need destructors run, so all the system needs to do is reclaim the memory. Therefore, most implementations store _only the amount of memory allocated_, not the number of elements.</p>
   <p>Therefore, for any type which is trivial, an unspecialized <code class="highlight"><c- n>fam_traits</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>size</c-><c- p>()</c-></code> is not required to report exactly the number of elements the user asked for the FAM object, just a value greater than or equal to. This is because a valid compiler implementation of <code class="highlight"><c- n>size</c-><c- p>()</c-></code> can be <code class="highlight"><c- k>return</c-> <c- nf>_Libc_allocated_size</c-><c- p>(</c-><c- n>fam_obj</c-><c- p>)</c-> <c- o>/</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>fam_element_t</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>);</c-></code>.</p>
   <p><strong>Note that this is only for trivial types,</strong> and is only mandated for perfect backwards compatibility with C code! For any FAM type that is non-trivial or whose array elements are non-trivial, the reported <code class="highlight"><c- n>size</c-><c- p>()</c-></code> must be exactly equal to the number of successfully constructed elements so that the destructor can be run properly. The only reason to provide <code class="highlight"><c- n>size</c-><c- p>()</c-></code> is to allow the compiler to generate a destructor that properly deletes the number of elements on your behalf, or the user in a FAM type’s destructor to use it to destruct the correct number of values. If the type is trivially destructible, the user should not need to invoke the destructor on each element individually to begin with.</p>
   <h4 class="heading settled" data-level="3.1.4" id="design-feature-special_members"><span class="secno">3.1.4. </span><span class="content">Feature: Special Members</span><a class="self-link" href="#design-feature-special_members"></a></h4>
   <p>FAMs have one special constructor that can be generated. It then has the usual copy and move constructors, as well as copy and move assignment operators. The destructor is also generated (or left empty if the entire class is trivial).</p>
   <h5 class="heading settled" data-level="3.1.4.1" id="design-feature-special_members-constructor"><span class="secno">3.1.4.1. </span><span class="content">Special Member: Constructor of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-></code></span><a class="self-link" href="#design-feature-special_members-constructor"></a></h5>
   <p>To construct a FAM type within the above restrictions, a constructor that takes an argument of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-></code> as its first argument is required. It may have more arguments than this, but to be used with <code class="highlight"><c- k>new</c-> <c- n>T</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-><c- p>(),</c-> <c- n>arg0</c-><c- p>,</c-> <c- p>...,</c-> <c- n>argN</c-><c- p>)</c-></code> expressions, a constructor present must take a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-></code> as the first argument. If one is not provided and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-></code> has not been specialized, then one is generated as follows:</p>
<pre class="highlight"><c- cp>#include</c-> &lt;fam>

<c- k>struct</c-> <c- n>my_fam_t</c-> <c- p>{</c->
	<c- n>std</c-><c- o>::</c-><c- n>string</c-> <c- n>s</c-><c- p>[];</c->

	<c- n>my_fam_t</c-><c- p>()</c-> <c- o>:</c-> <c- n>my_fam_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-><c- p>(</c-><c- mi>0</c-><c- p>))</c-> <c- p>{}</c->

	<c- n>my_fam_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-> <c- n>__fs</c-><c- p>)</c-> <c- p>{</c->
		<c- k>using</c-> <c- n>__size_type</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-><c- o>&lt;</c-><c- n>my_fam_t</c-><c- o>>::</c-><c- n>size</c-><c- p>());</c->
		<c- k>using</c-> <c- n>__elem_type</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>string</c-><c- p>;</c->
		<c- n>__size_type</c-> <c- n>__constructed</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
		<c- n>__elem_type</c-><c- o>*</c-> <c- n>__elem_ptr</c-> <c- o>=</c-> <c- k>reinterpret_cast</c-><c- o>&lt;</c-><c- n>__elem_type</c-><c- o>*></c-><c- p>(</c-><c- k>this</c-> <c- o>+</c-> <c- mi>1</c-><c- p>);</c->
		<c- n>__size_type</c-> <c- n>__sz</c-> <c- o>=</c-> <c- k>static_cast</c-><c- o>&lt;</c-><c- n>__size_type</c-><c- o>></c-><c- p>(</c-><c- n>__fs</c-><c- p>.</c-><c- n>size</c-><c- p>());</c->
		<c- k>try</c-> <c- p>{</c->
			<c- k>for</c-> <c- p>(;</c-> <c- n>__constructed</c-> <c- o>&lt;</c-> <c- n>__sz</c-><c- p>;</c-> <c- o>++</c-><c- n>__constructed</c-><c- p>,</c-> <c- o>++</c-><c- n>__elem_ptr</c-><c- p>)</c-> <c- p>{</c->
				<c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_constructible_v</c-><c- o>&lt;</c-><c- n>__elem_type</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
					<c- c1>// default-init</c->
				<c- p>}</c->
				<c- k>else</c-> <c- p>{</c->
					<c- k>new</c-> <c- p>(</c-><c- n>__elem_ptr</c-><c- p>)</c-> <c- n>__elem_type</c-><c- p>();</c->
				<c- p>}</c->
				<c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_destructible_v</c-><c- o>&lt;</c-><c- n>__elem_type</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
					<c- c1>// exposition only</c->
					<c- c1>// update constructed size, </c->
					<c- c1>// so destructor of member can run properly</c->
					<c- n>_Libc_stored_size</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>,</c-> <c- n>__constructed</c-><c- p>);</c->
				<c- p>}</c->
			<c- p>}</c->
		<c- p>}</c->
		<c- k>catch</c-> <c- p>(...)</c-> <c- p>{</c->
			<c- k>for</c-> <c- p>(</c-><c- o>--</c-><c- n>__elem_ptr</c-><c- p>;</c-> <c- n>__constructed</c-> <c- o>!=</c-> <c- mi>0</c-><c- p>;</c-> <c- o>--</c-><c- n>__constructed</c-><c- p>,</c-> <c- o>--</c-><c- n>__elem_ptr</c-><c- p>)</c-> <c- p>{</c->
				<c- n>__elem_ptr</c-><c- o>->~</c-><c- n>__elem_type</c-><c- p>();</c->
			<c- p>}</c->
			<c- c1>// rethrow</c->
			<c- k>throw</c-><c- p>;</c->
		<c- p>}</c->
		<c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_destructible_v</c-><c- o>&lt;</c-><c- n>__elem_type</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
			<c- c1>// exposition only</c->
			<c- c1>// update constructed size, </c->
			<c- c1>// so destructor can run properly</c->
			<c- n>_Libc_stored_size</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>,</c-> <c- n>__constructed</c-><c- p>);</c->
		<c- p>}</c->
	<c- p>}</c->
<c- p>}</c->
</pre>
   <p>If <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-></code> has been specialized, then the compiler will not generate this constructor for the type and the program is ill-formed. If there are other members in this type that are not default constructible, then this constructor will not be written for the type and the program will be ill-formed. The default, no-argument constructor will simply call the deferred constructor as if defined like <code class="highlight"><c- n>type_name</c-><c- p>()</c-> <c- o>:</c-> <c- n>type_name</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-><c- p>(</c-><c- mi>0</c-><c- p>))</c-> <c- p>{}</c-></code>.</p>
   <h5 class="heading settled" data-level="3.1.4.2" id="design-feature-special_members-destructor"><span class="secno">3.1.4.2. </span><span class="content">Destructor</span><a class="self-link" href="#design-feature-special_members-destructor"></a></h5>
   <p>The destructor is also automatically generated for FAM types. An exemplary implementation is as follows:</p>
<pre class="highlight"><c- k>struct</c-> <c- n>my_fam_t</c-> <c- p>{</c->
	<c- n>std</c-><c- o>::</c-><c- n>string</c-> <c- n>s</c-><c- p>[];</c->

	<c- o>~</c-><c- n>my_fam_t</c-><c- p>()</c-> <c- p>{</c->
		<c- k>using</c-> <c- n>__elem_type</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>string</c-><c- p>;</c->
		<c- k>using</c-> <c- n>__size_type</c-> <c- o>=</c-> <c- k>decltype</c-><c- p>(</c->
			<c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-><c- o>&lt;</c-><c- n>my_fam_t</c-><c- o>>::</c-><c- n>size</c-><c- p>(</c->
				<c- n>std</c-><c- o>::</c-><c- n>declval</c-><c- o>&lt;</c-><c- n>__elem_type</c-><c- o>></c-><c- p>()</c->
			<c- p>)</c->
		<c- p>);</c->
		<c- k>if</c-> <c- nf>constexpr</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_destructible_v</c-><c- o>&lt;</c-><c- n>__elem_type</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
			<c- c1>// no-op</c->
		<c- p>}</c->
		<c- k>else</c-> <c- p>{</c->
			<c- n>__size_type</c-> <c- n>__sz</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-><c- o>&lt;</c-><c- n>my_fam_t</c-><c- o>>::</c-><c- n>size</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>);</c->
			<c- n>__elem_type</c-><c- o>*</c-> <c- n>__elem_ptr</c-> <c- o>=</c-> <c- k>reinterpret_cast</c-><c- o>&lt;</c-><c- n>__elem_type</c-><c- o>*></c-><c- p>(</c-><c- k>this</c-> <c- o>+</c-> <c- mi>1</c-><c- p>);</c->
			<c- n>__elem_type</c-><c- o>*</c-> <c- n>__elem_ptr_end</c-> <c- o>=</c-> <c- n>__elem_ptr</c-><c- p>;</c->
			<c- n>__elem_ptr</c-> <c- o>+=</c-> <c- n>__sz</c-><c- p>;</c->
			<c- k>for</c-> <c- p>(;</c-> <c- n>__elem_ptr</c-> <c- o>!=</c-> <c- n>__elem_ptr_end</c-><c- p>;</c-> <c- o>--</c-><c- n>__elem_ptr</c-><c- p>)</c-> <c- p>{</c->
				<c- n>__elem_ptr</c-><c- o>->~</c-><c- n>__elem_type</c-><c- p>();</c->
			<c- p>}</c->
		<c- p>}</c->
	<c- p>}</c->
<c- p>}</c->
</pre>
   <p>A user does not ever have to write a destructor for their FAM type: one will always be generated that is correct for dealing with all of the members, plus the flexible array member’s data. When a FAM type is destructed, the elements of the FAM are destroyed in reverse order, and then the other elements of the class are destroyed as normal. See the <a href="#design-demo-simple_non_trivial">§3.2.2 Simple: Non-Trivial</a> for an example of the default construction and destruction orders.</p>
   <h5 class="heading settled" data-level="3.1.4.3" id="design-feature-special_members-copy_move"><span class="secno">3.1.4.3. </span><span class="content">Copy/Move Constructor and Assignment</span><a class="self-link" href="#design-feature-special_members-copy_move"></a></h5>
   <p>Copy/move constructors and copy/move assignment all follow the same pattern as the constructor and destructor in this case. They are seen as if invoking a constructor with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-></code>, and then copy/move constructing each element of the array (that is, it performs a by-value copy of each element). The sizes of both FAMs will compare equal after copy and move operations (modulo any insane <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-></code> specializations).</p>
   <h3 class="heading settled" data-level="3.2" id="design-demo"><span class="secno">3.2. </span><span class="content">Examples</span><a class="self-link" href="#design-demo"></a></h3>
   <p>Here are some examples of the syntax and some of its invariants.</p>
   <h4 class="heading settled" data-level="3.2.1" id="design-demo-simple_trivial"><span class="secno">3.2.1. </span><span class="content">Simple: Trivial</span><a class="self-link" href="#design-demo-simple_trivial"></a></h4>
   <p>Here is a very simple FAM type:</p>
<pre class="highlight"><c- cp>#include</c-> &lt;fam>

<c- k>struct</c-> <c- n>easy_fam_t</c-> <c- p>{</c->
	<c- b>int</c-> <c- n>ids</c-><c- p>[];</c->
<c- p>};</c->

<c- cp>#include</c-> &lt;cassert>

<c- b>int</c-> <c- nf>main</c-> <c- p>()</c-> <c- p>{</c->
	<c- k>using</c-> <c- n>my_traits</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-><c- o>&lt;</c-><c- n>easy_fam_t</c-><c- o>></c-><c- p>;</c->

	<c- n>easy_fam_t</c-> <c- n>automatic_fam_object</c-><c- p>;</c->
	<c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>automatic_len</c-> 
		<c- o>=</c-> <c- n>my_traits</c-><c- o>::</c-><c- n>size</c-><c- p>(</c-><c- n>automatic_fam_object</c-><c- p>);</c->
	<c- n>assert</c-><c- p>(</c-><c- n>automatic_len</c-> <c- o>==</c-> <c- mi>0</c-><c- p>);</c->
	<c- c1>// following is ill-formed: </c->
	<c- c1>// fam_t other(std::fam_size(1));</c->
	<c- c1>// error: cannot create flexible array </c->
	<c- c1>// member of varying size in automatic storage</c->

	<c- n>easy_fam_t</c-><c- o>*</c-> <c- n>dynamic_fam_object_raw</c-> <c- o>=</c-> <c- k>new</c-> <c- n>easy_fam_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-><c- p>(</c-><c- mi>24</c-><c- p>));</c->
	<c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>dynamic_raw_len</c->
		<c- o>=</c-> <c- n>my_traits</c-><c- o>::</c-><c- n>size</c-><c- p>(</c-><c- o>*</c-><c- n>dynamic_fam_object_raw</c-><c- p>);</c->
	<c- c1>// !! IMPORTANT</c->
	<c- c1>// reported raw size can be</c->
	<c- c1>// 24, or GREATER than for trivial types!!</c->
	<c- n>assert</c-><c- p>(</c-><c- n>dynamic_raw_len</c-> <c- o>>=</c-> <c- mi>24</c-><c- p>);</c->
	<c- k>delete</c-> <c- n>dynamic_fam_object</c-><c- p>;</c->

	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <h4 class="heading settled" data-level="3.2.2" id="design-demo-simple_non_trivial"><span class="secno">3.2.2. </span><span class="content">Simple: Non-Trivial</span><a class="self-link" href="#design-demo-simple_non_trivial"></a></h4>
   <p>Here is a FAM type with a non-trivial element that prints its id on construction and destruction:</p>
<pre class="highlight"><c- cp>#include</c-> &lt;iostream>
<c- cp>#include</c-> &lt;fam>

<c- k>struct</c-> <c- n>tracer</c-> <c- p>{</c->
	<c- k>static</c-> <c- b>int</c-> <c- n>x</c-><c- p>;</c->

	<c- b>int</c-> <c- n>id</c-> <c- o>=</c-> <c- o>++</c-><c- n>x</c-><c- p>;</c->

	<c- n>tracer</c-><c- p>()</c-> <c- p>{</c->
		<c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"constructed "</c-> <c- o>&lt;&lt;</c-> <c- n>id</c-> <c- o>&lt;&lt;</c-> <c- n>std</c-><c- o>::</c-><c- n>endl</c-><c- p>;</c->
	<c- p>}</c->

	<c- o>~</c-><c- n>tracer</c-><c- p>()</c-> <c- p>{</c->
		<c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"destructed "</c-> <c- o>&lt;&lt;</c-> <c- n>id</c-> <c- o>&lt;&lt;</c-> <c- n>std</c-><c- o>::</c-><c- n>endl</c-><c- p>;</c->
	<c- p>}</c->
<c- p>};</c->
<c- b>int</c-> <c- n>tracer</c-><c- o>::</c-><c- n>x</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->

<c- k>struct</c-> <c- n>tracing_fam_t</c-> <c- p>{</c->
	<c- n>tracer</c-> <c- n>tracers</c-><c- p>[];</c->
<c- p>};</c->

<c- b>int</c-> <c- nf>main</c-> <c- p>()</c-> <c- p>{</c->
	<c- k>using</c-> <c- n>my_traits</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-><c- o>&lt;</c-><c- n>tracing_fam_t</c-><c- o>></c-><c- p>;</c->

	<c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>tracing_fam_t</c-><c- o>></c-> <c- n>dynamic_fam_object</c-> 
		<c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>make_unique</c-><c- o>&lt;</c-><c- n>tracing_fam_t</c-><c- o>></c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-><c- p>(</c-><c- mi>5</c-><c- p>));</c->
	<c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>dynamic_len</c->
		<c- o>=</c-> <c- n>my_traits</c-><c- o>::</c-><c- n>size</c-><c- p>(</c-><c- o>*</c-><c- n>dynamic_fam_object</c-><c- p>);</c->
	<c- n>assert</c-><c- p>(</c-><c- n>dynamic_raw_len</c-> <c- o>==</c-> <c- mi>5</c-><c- p>);</c->

	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>This will print:</p>
<pre class="highlight"><c- n>constructed</c-> <c- mi>1</c->
<c- n>constructed</c-> <c- mi>2</c->
<c- n>constructed</c-> <c- mi>3</c->
<c- n>constructed</c-> <c- mi>4</c->
<c- n>constructed</c-> <c- mi>5</c->
<c- n>destructed</c-> <c- mi>5</c->
<c- n>destructed</c-> <c- mi>4</c->
<c- n>destructed</c-> <c- mi>3</c->
<c- n>destructed</c-> <c- mi>2</c->
<c- n>destructed</c-> <c- mi>1</c->
</pre>
   <p>Note that arrays are constructed in forward-linear order by default, and destructs in reverse-linear order by default. If a user wants to override the constructor or destructor to behave differently, they are more than welcome to change the semantics of destruction order.</p>
   <h4 class="heading settled" data-level="3.2.3" id="design-demo-specialize"><span class="secno">3.2.3. </span><span class="content">Specialized Traits</span><a class="self-link" href="#design-demo-specialize"></a></h4>
   <p>The below example shows off a specialized traits class with a custom constructor. Note that in this example there is no destructor definition: it is generated for us and properly uses <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-><c- o>&lt;</c-><c- p>...</c-><c- o>>::</c-><c- n>size</c-><c- p>(</c-><c- n>obj</c-><c- p>);</c-></code> to get the element count to destroy.</p>
<pre class="highlight"><c- cp>#include</c-> &lt;iostream>
<c- cp>#include</c-> &lt;fam>

<c- k>struct</c-> <c- n>tracer_2</c-> <c- p>{</c->
	<c- k>static</c-> <c- b>int</c-> <c- n>x</c-><c- p>;</c->

	<c- b>int</c-> <c- n>id</c-><c- p>;</c->

	<c- n>tracer_2</c-><c- p>(</c-><c- b>int</c-> <c- n>id_boost</c-><c- p>)</c-> <c- o>:</c-> <c- n>id</c-><c- p>(</c-><c- o>++</c-><c- n>x</c-> <c- o>+</c-> <c- n>id_boost</c-><c- p>)</c-> <c- p>{</c->
		<c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"constructed "</c-> <c- o>&lt;&lt;</c-> <c- n>id</c-> <c- o>&lt;&lt;</c-> <c- n>std</c-><c- o>::</c-><c- n>endl</c-><c- p>;</c->
	<c- p>}</c->

	<c- o>~</c-><c- n>tracer_2</c-><c- p>()</c-> <c- p>{</c->
		<c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"destructed "</c-> <c- o>&lt;&lt;</c-> <c- n>id</c-> <c- o>&lt;&lt;</c-> <c- n>std</c-><c- o>::</c-><c- n>endl</c-><c- p>;</c->
	<c- p>}</c->
<c- p>};</c->
<c- b>int</c-> <c- n>tracer_2</c-><c- o>::</c-><c- n>x</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->

<c- k>struct</c-> <c- n>tracing_fam_2_t</c-> <c- p>{</c->
	<c- b>int</c-> <c- n>len</c-><c- p>;</c->
	<c- n>tracer_2</c-> <c- n>tracers</c-><c- p>[];</c->

	<c- n>tracing_fam_2_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-> <c- n>fs</c-><c- p>,</c-> <c- b>int</c-> <c- n>id_boost</c-><c- p>)</c-> <c- o>:</c-> <c- n>len</c-><c- p>(</c-><c- n>fs</c-><c- p>.</c-><c- n>size</c-><c- p>())</c-> <c- p>{</c->
		<c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"manually constructing fam type"</c-> <c- o>&lt;&lt;</c-> <c- n>std</c-><c- o>::</c-><c- n>endl</c-><c- p>;</c->
		<c- k>for</c-> <c- p>(</c-><c- b>int</c-> <c- n>i</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c-> <c- n>i</c-> <c- o>&lt;</c-> <c- n>len</c-><c- p>;</c-> <c- o>++</c-><c- n>i</c-><c- p>)</c-> <c- p>{</c->
			<c- k>new</c-> <c- p>(</c-><c- o>&amp;</c-><c- n>tracers</c-><c- p>[</c-><c- n>i</c-><c- p>])</c-> <c- n>tracer_2</c-><c- p>(</c-><c- n>id_boost</c-><c- p>);</c->
		<c- p>}</c->
	<c- p>}</c->
<c- p>};</c->

<c- k>template</c-> <c- o>&lt;></c->
<c- k>struct</c-> <c- n>fam_traits</c-> <c- p>{</c->
	<c- k>constexpr</c-> <c- k>static</c-> <c- b>int</c-> <c- n>size</c-><c- p>(</c-><c- k>const</c-> <c- n>tracing_fam_2_t</c-><c- o>&amp;</c-> <c- n>tf2</c-><c- p>)</c-> <c- k>noexcept</c-> <c- p>{</c->
		<c- k>return</c-> <c- n>tf2</c-><c- p>.</c-><c- n>len</c-><c- p>;</c->
	<c- p>}</c->
<c- p>};</c->

<c- b>int</c-> <c- nf>main</c-> <c- p>()</c-> <c- p>{</c->
	<c- k>using</c-> <c- n>my_traits</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-><c- o>&lt;</c-><c- n>tracing_fam_2_t</c-><c- o>></c-><c- p>;</c->

	<c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>tracing_fam_2_t</c-><c- o>></c-> <c- n>dynamic_fam_object</c-> 
		<c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>make_unique</c-><c- o>&lt;</c-><c- n>tracing_fam_2_t</c-><c- o>></c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-><c- p>(</c-><c- mi>3</c-><c- p>),</c-> <c- mi>2</c-><c- p>);</c->
	<c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>dynamic_len</c->
		<c- o>=</c-> <c- n>my_traits</c-><c- o>::</c-><c- n>size</c-><c- p>(</c-><c- o>*</c-><c- n>dynamic_fam_object</c-><c- p>);</c->
	<c- n>assert</c-><c- p>(</c-><c- n>dynamic_fam_object</c-><c- o>-></c-><c- n>len</c-> <c- o>==</c-> <c- n>dynamic_raw_len</c-><c- p>);</c->
	<c- n>assert</c-><c- p>(</c-><c- n>dynamic_fam_object</c-><c- o>-></c-><c- n>len</c-> <c- o>==</c-> <c- mi>3</c-><c- p>);</c->

	<c- c1>// ill-formed</c->
	<c- c1>// tracing_fam_2_t auto_tf2;</c->
	<c- c1>// error: cannot call default </c->
	<c- c1>// constructor tracing_fam_2_t(std::fam_size(0))</c->

	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>This will print:</p>
<pre class="highlight"><c- n>manually</c-> <c- n>constructing</c-> <c- n>fam</c-> <c- n>type</c->
<c- n>constructed</c-> <c- mi>3</c->
<c- n>constructed</c-> <c- mi>4</c->
<c- n>constructed</c-> <c- mi>5</c->
<c- n>destructed</c-> <c- mi>5</c->
<c- n>destructed</c-> <c- mi>4</c->
<c- n>destructed</c-> <c- mi>3</c->
</pre>
   <p>Note here that <code class="highlight"><c- n>tracing_fam_2_t</c-></code> has more than just <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-></code> as an argument for its special constructor. Therefore, a generated default constructor that takes 0 arguments and defers to a constructor as if <code class="highlight"><c- n>tracing_fam_2_t</c-><c- p>()</c-> <c- o>:</c-> <c- n>tracing_fam_2_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-><c- p>(</c-><c- mi>0</c-><c- p>))</c-></code> is ill-formed. Therefore, it is not generated and attempt to default-construct this type would result in an error.</p>
   <h4 class="heading settled" data-level="3.2.4" id="design-demo-udp"><span class="secno">3.2.4. </span><span class="content">UDP Packets</span><a class="self-link" href="#design-demo-udp"></a></h4>
   <p>This extension is also a natural fit for many on-the-wire and on-disk data types. Here is an example for UDP packets.</p>
<pre class="highlight"><c- cp>#include</c-> &lt;cstddef>
<c- cp>#include</c-> &lt;cstdint>
<c- cp>#include</c-> &lt;fam>

<c- k>struct</c-> <c- n>udp</c-> <c- p>{</c->
	<c- n>std</c-><c- o>::</c-><c- b>uint16_t</c-> <c- n>source_port</c-><c- p>;</c->
	<c- n>std</c-><c- o>::</c-><c- b>uint16_t</c-> <c- n>destination_port</c-><c- p>;</c->
	<c- n>std</c-><c- o>::</c-><c- b>uint16_t</c-> <c- n>data_size</c-><c- p>;</c->
	<c- n>std</c-><c- o>::</c-><c- b>uint16_t</c-> <c- n>checksum</c-><c- p>;</c->
	<c- n>std</c-><c- o>::</c-><c- n>byte</c->     <c- n>data</c-><c- p>[];</c->

	<c- n>udp</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-> <c- n>fs</c-><c- p>)</c-> 
		<c- o>:</c-> <c- n>source_port</c-><c- p>(</c-><c- mi>0</c-><c- p>),</c-> 
		<c- n>destination_port</c-><c- p>(</c-><c- mi>0</c-><c- p>),</c-> 
		<c- n>data_size</c-><c- p>(</c-><c- k>static_cast</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- b>uint16_t</c-><c- o>></c-><c- p>(</c-><c- n>fs</c-><c- p>.</c-><c- n>size</c-><c- p>())),</c->
		<c- n>checksum</c-><c- p>(</c-><c- mi>0</c-><c- p>)</c-> <c- p>{}</c->

	<c- b>int</c-> <c- n>packet_size</c-><c- p>()</c-> <c- k>const</c-> <c- p>{</c->
		<c- k>static_assert</c-><c- p>((</c-><c- k>sizeof</c-><c- p>(</c-><c- n>udp</c-><c- p>)</c-> <c- o>*</c-> <c- n>CHAR_BIT</c-><c- p>)</c-> <c- o>==</c-> <c- p>(</c-><c- mi>8</c-> <c- o>*</c-> <c- mi>8</c-><c- p>),</c-> 
			<c- s>"compiler did not lay out 4 unint16_t’s in exactly 8 bytes"</c-><c- p>);</c->
		<c- k>return</c-> <c- k>static_cast</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-><c- p>(</c-><c- n>data_size</c-> <c- o>+</c-> <c- mi>8</c-><c- p>);</c->
	<c- p>}</c->

	<c- k>const</c-> <c- b>char</c-><c- o>*</c-> <c- n>packet_data</c-> <c- p>()</c-> <c- k>const</c-> <c- p>{</c->
		<c- k>return</c-> <c- k>reinterpret_cast</c-><c- o>&lt;</c-><c- k>const</c-> <c- b>char</c-><c- o>*></c-><c- p>(</c-><c- k>this</c-><c- p>);</c->
	<c- p>}</c->

	<c- b>char</c-><c- o>*</c-> <c- n>packet_data</c-> <c- p>()</c-> <c- p>{</c->
		<c- k>return</c-> <c- k>reinterpret_cast</c-><c- o>&lt;</c-><c- b>char</c-><c- o>*></c-><c- p>(</c-><c- k>this</c-><c- p>);</c->
	<c- p>}</c->
<c- p>};</c->

<c- k>template</c-> <c- o>&lt;></c->
<c- k>struct</c-> <c- n>fam_traits</c-><c- o>&lt;</c-><c- n>udp</c-><c- o>></c-> <c- p>{</c->
	<c- k>constexpr</c-> <c- k>static</c-> <c- n>std</c-><c- o>::</c-><c- b>uint16_t</c-> <c- n>size</c-> <c- p>(</c-><c- k>const</c-> <c- n>udp</c-><c- o>&amp;</c-> <c- n>u</c-><c- p>)</c-> <c- p>{</c->
		<c- k>return</c-> <c- n>u</c-><c- p>.</c-><c- n>data_size</c-><c- p>;</c->
	<c- p>}</c->
<c- p>};</c->

<c- cp>#include</c->&lt;iostream>
<c- cp>#include</c->&lt;cstring> 
<c- cp>#include</c->&lt;cstdlib>

<c- cp>#include</c->&lt;arpa/inet.h>
<c- cp>#include</c->&lt;sys/socket.h>

<c- k>typedef</c-> <c- k>struct</c-> <c- n>sockaddr</c-> <c- n>base_socket_address</c-><c- p>;</c->
<c- k>typedef</c-> <c- k>struct</c-> <c- n>sockaddr_in</c-> <c- n>socket_address</c-><c- p>;</c->

<c- k>struct</c-> <c- n>socket_t</c-> <c- p>{</c->
	<c- b>int</c-> <c- n>handle</c-><c- p>;</c->

	<c- n>socket_t</c-> <c- p>(</c-><c- b>int</c-> <c- n>h</c-><c- p>)</c-> <c- o>:</c-> <c- n>handle</c-><c- p>(</c-><c- n>h</c-><c- p>)</c-> <c- p>{}</c->
	<c- n>socket_t</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>nullptr_t</c-><c- p>)</c-> <c- o>:</c-> <c- n>handle</c-><c- p>(</c-><c- o>-</c-><c- mi>1</c-><c- p>)</c-> <c- p>{}</c->
	<c- k>operator</c-> <c- b>int</c-><c- p>()</c-> <c- k>const</c-> <c- p>{</c->
		<c- k>return</c-> <c- n>handle</c-><c- p>;</c->
	<c- p>}</c->

	<c- b>bool</c-> <c- k>operator</c-><c- o>==</c-><c- p>(</c-><c- k>const</c-> <c- n>socket_t</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>)</c-> <c- k>const</c-> <c- p>{</c->
		<c- k>return</c-> <c- n>handle</c-> <c- o>==</c-> <c- n>rhs</c-><c- p>.</c-><c- n>handle</c-><c- p>;</c->
	<c- p>}</c->

	<c- b>bool</c-> <c- k>operator</c-><c- o>!=</c-><c- p>(</c-><c- k>const</c-> <c- n>socket_t</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>)</c-> <c- k>const</c-> <c- p>{</c->
		<c- k>return</c-> <c- n>handle</c-> <c- o>!=</c-> <c- n>rhs</c-><c- p>.</c-><c- n>handle</c-><c- p>;</c->
	<c- p>}</c->

	<c- b>bool</c-> <c- k>operator</c-><c- o>==</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>nullptr_t</c-><c- p>)</c-> <c- k>const</c-> <c- p>{</c->
		<c- k>return</c-> <c- n>handle</c-> <c- o>==</c-> <c- o>-</c-><c- mi>1</c-><c- p>;</c->
	<c- p>}</c->

	<c- b>bool</c-> <c- k>operator</c-><c- o>!=</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>nullptr_t</c-><c- p>)</c-> <c- k>const</c-> <c- p>{</c->
		<c- k>return</c-> <c- n>handle</c-> <c- o>!=</c-> <c- o>-</c-><c- mi>1</c-><c- p>;</c->
	<c- p>}</c->
<c- p>};</c->

<c- k>struct</c-> <c- n>socket_deleter</c-> <c- p>{</c->
	<c- b>void</c-> <c- k>operator</c-><c- p>()(</c-><c- n>socket_t</c-> <c- n>s</c-><c- p>)</c-> <c- k>const</c-> <c- p>{</c->
		<c- n>close</c-><c- p>(</c-><c- n>s</c-><c- p>.</c-><c- n>handle</c-><c- p>);</c->
	<c- p>}</c->
<c- p>};</c->

<c- b>int</c-> <c- nf>main</c-> <c- p>()</c-> <c- p>{</c->

	<c- c1>//create a UDP socket</c->
	<c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>socket_t</c-><c- p>,</c-> <c- n>socket_deleter</c-><c- o>></c-> <c- n>s</c-><c- p>(</c->
		<c- n>socket</c-><c- p>(</c-><c- n>AF_INET</c-><c- p>,</c-> <c- n>SOCK_DGRAM</c-><c- p>,</c-> <c- n>IPPROTO_UDP</c-><c- p>));</c->

	<c- k>if</c-> <c- p>(</c-><c- o>!</c-><c- n>s</c-><c- p>)</c-> <c- p>{</c->
		<c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"Couldn’t open a UDP socket!"</c-> <c- o>&lt;&lt;</c-> <c- n>std</c-><c- o>::</c-><c- n>endl</c-><c- p>;</c->
		<c- k>return</c-> <c- o>-</c-><c- mi>1</c-><c- p>;</c->
	<c- p>}</c->

	<c- n>socket_address</c-> <c- n>address_out</c-><c- p>;</c->
	<c- n>std</c-><c- o>::</c-><c- n>memset</c-><c- p>(</c-><c- n>reinterpet_cast</c-><c- o>&lt;</c-><c- b>char</c-><c- o>*></c-><c- p>(</c-><c- o>&amp;</c-><c- n>address_out</c-><c- p>),</c-> 
		<c- mi>0</c-><c- p>,</c-> 
		<c- k>sizeof</c-><c- p>(</c-><c- n>address_out</c-><c- p>));</c->
	<c- n>address_out</c-><c- p>.</c-><c- n>sin_family</c-> <c- o>=</c-> <c- n>AF_INET</c-><c- p>;</c->
	<c- n>address_out</c-><c- p>.</c-><c- n>sin_port</c-> <c- o>=</c-> <c- n>htons</c-><c- p>(</c-><c- mi>8888</c-><c- p>);</c->
	<c- n>address_out</c-><c- p>.</c-><c- n>sin_addr</c-><c- p>.</c-><c- n>s_addr</c-> <c- o>=</c-> <c- n>htonl</c-><c- p>(</c-><c- mi>3456</c-><c- p>);</c->

	<c- c1>// create UDP packet of 460 bytes</c->
	<c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>udp</c-><c- o>></c-> <c- n>packet</c-> 
		<c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>make_unique</c-><c- o>&lt;</c-><c- n>udp</c-><c- o>></c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-><c- p>(</c-><c- mi>460</c-><c- p>));</c->
	<c- d>/* Super Cool Serialization Here */</c->
	<c- c1>// Send it over!</c->
	<c- b>int</c-> <c- n>result</c-> <c- o>=</c-> <c- n>sendto</c-><c- p>(</c-><c- o>*</c-><c- n>s</c-><c- p>,</c-> 
		<c- n>udp</c-><c- o>-></c-><c- n>packet_data</c-><c- p>(),</c-> 
		<c- n>udp</c-><c- o>-></c-><c- n>packet_size</c-><c- p>(),</c-> 
		<c- mi>0</c-><c- p>,</c-> 
		<c- k>reinterpret_cast</c-><c- o>&lt;</c-><c- n>base_socket_address</c-><c- o>></c-><c- p>(</c-><c- o>&amp;</c-><c- n>address_out</c-><c- p>),</c-> 
		<c- k>sizeof</c-><c- p>(</c-><c- n>address_out</c-><c- p>));</c->
	<c- k>if</c-> <c- p>(</c-><c- n>result</c-> <c- o>==</c-> <c- o>-</c-><c- mi>1</c-><c- p>)</c-> <c- p>{</c->
		<c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"Could not send a UDP packet!"</c-> <c- o>&lt;&lt;</c-> <c- n>std</c-><c- o>::</c-><c- n>endl</c-><c- p>;</c->
		<c- k>return</c-> <c- o>-</c-><c- mi>1</c-><c- p>;</c->
	<c- p>}</c->
	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>Tail-allocated structures now become very easy to specify, creation of them saves on additional allocations and avoids type punning shenanigans, and can easily match programmer intent while keeping the strong type safety built into C++.</p>
   <h2 class="heading settled" data-level="4" id="wording"><span class="secno">4. </span><span class="content">Proposed Wording</span><a class="self-link" href="#wording"></a></h2>
   <p><strong>The wording for this proposal is incomplete.</strong> The author is working on it, and suggestions as to what clauses should be modified are welcome!</p>
   <p>Any attempts at wording would be relative to <a data-link-type="biblio" href="#biblio-n4762">[n4762]</a>.</p>
   <h3 class="heading settled" data-level="4.1" id="wording-feature"><span class="secno">4.1. </span><span class="content">Proposed Feature Test Macro and Header</span><a class="self-link" href="#wording-feature"></a></h3>
   <p>The proposed feature test macro is <code class="highlight"><c- n>__cpp_flexible_array_members</c-></code> with a value of <code class="highlight"><c- mi>201811LL</c-></code>. The added header is <code class="highlight"><c- o>&lt;</c-><c- n>fam</c-><c- o>></c-></code>, and the additional traits go in <code class="highlight"><c- o>&lt;</c-><c- n>type_traits</c-><c- o>></c-></code> as specified.</p>
   <h3 class="heading settled" data-level="4.2" id="wording-intent"><span class="secno">4.2. </span><span class="content">Intent</span><a class="self-link" href="#wording-intent"></a></h3>
   <p>The intent of this wording is to create a new type in the C++ language called a Flexible Array Member (FAM) type (FAM type). FAM types:</p>
   <ul>
    <li data-md>
     <p>shall be implicitly final,</p>
    <li data-md>
     <p>shall have the flexible array member type come last,</p>
    <li data-md>
     <p>shall be of the form <code class="highlight"><c- n>type</c-><c- o>-</c-><c- n>identifier</c-> <c- n>variable</c-><c- o>-</c-><c- n>name</c-> <c- p>[</c-> <c- p>]</c-></code>,</p>
    <li data-md>
     <p>shall only be created with a variable size through placement new or new syntax,</p>
    <li data-md>
     <p>shall not be an object or sub-object of an array,</p>
    <li data-md>
     <p>shall have a special constructor that takes at least 1 argument of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-></code> as the first argument with any number of additional arguments,</p>
    <li data-md>
     <p>shall either specialize <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-></code> with the required <code class="highlight"><c- n>size</c-></code> function and write a constructor following the above restriction or have one generated,</p>
    <li data-md>
     <p>may have a default constructor generated which defers to another constructor with only the argument <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-><c- p>(</c-><c- mi>0</c-><c- p>)</c-></code>,</p>
    <li data-md>
     <p>shall not contribute to the <code class="highlight"><c- k>sizeof</c-><c- p>()</c-></code> value for the type except for any necessary implementation-defined padding to reach the flexible array member,</p>
    <li data-md>
     <p>and if either the type of the flexible array member’s element type evaluates <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_trivial</c-><c- o>&lt;</c-><c- n>element_type</c-><c- o>></c-></code> or <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-></code> is specialized by the program to true then the FAM type is not required to report the exact element count requested by the use of a std::fam_size constructor.</p>
   </ul>
   <p>Additionally, the wording is meant to create 1 new type -- std::fam_size -- whose type references a compiler-defined type that is only named in the program through inclusion of the header <code class="highlight"><c- o>&lt;</c-><c- n>fam</c-><c- o>></c-></code> with the type identifier <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-></code>. It will also created 1 new program-specializable trait -- <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-></code> -- that is also available in the <code class="highlight"><c- o>&lt;</c-><c- n>fam</c-><c- o>></c-></code> header. If the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_traits</c-></code> template type is not specialized, then it is only required that the implementation report exactly the element count passed in through <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fam_size</c-></code>, modulo the exception for trivial types above.</p>
   <h3 class="heading settled" data-level="4.3" id="wording-synopsis"><span class="secno">4.3. </span><span class="content">Synopsis</span><a class="self-link" href="#wording-synopsis"></a></h3>
<pre class="highlight"><c- c1>// &lt;fam></c->

<c- k>namespace</c-> <c- n>std</c-> <c- p>{</c->
	<c- k>struct</c-> <c- n>fam_size</c-> <c- p>{</c->
		<c- n>fam_size</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>element_count</c-> <c- o>=</c-> <c- mi>0</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
		<c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>size</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</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>></c->
	<c- k>struct</c-> <c- n>fam_traits</c-> <c- p>{</c->
		<c- k>constexpr</c-> <c- k>static</c-> <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>size</c-> <c- p>(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
	<c- p>}</c->
<c- p>}</c->
</pre>
<pre class="highlight"><c- c1>// &lt;type_traits></c->

<c- k>namespace</c-> <c- n>std</c-> <c- p>{</c->
	<c- c1>// ...</c->

	<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
	<c- k>struct</c-> <c- n>is_fam</c-><c- p>;</c->

	<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
	<c- k>using</c-> <c- n>is_fam_v</c-> <c- o>=</c-> <c- n>is_fam</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>value</c-><c- p>;</c->

	<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
	<c- k>struct</c-> <c- n>fam_element</c-><c- p>;</c->

	<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
	<c- k>using</c-> <c- n>fam_element_t</c-> <c- o>=</c-> <c- n>fam_element</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>type</c-><c- p>;</c->

	<c- c1>// ...</c->
<c- p>}</c->
</pre>
   <h2 class="heading settled" data-level="5" id="acknowledgements"><span class="secno">5. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h2>
   <p>A big thank you to Agustín Bergé for helping to hammer down this initial idea before the group of us spiraled off into the weeds!</p>
   <p>Thank you to Simon Brand for providing a few example use cases and telling us about HSA BRIG modules.</p>
   <p>Thank you to Matt Godbolt for his small chat during a C++Now dinner about the ways in which people use what are essentially Flexible Array Members with gratuitous type punning in High Frequency Trade network programs.</p>
   <p>Thank you to Jeff Snyder for his insights with his previous papers and his wisdom sharing at C++Now, and Chandler Carruth for pointing me in his direction.</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="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-file_notify_information">[FILE_NOTIFY_INFORMATION]
   <dd>Microsoft. <a href="https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_file_notify_information">_FILE_NOTIFY_INFORMATION structure</a>. September 27th, 2018. URL: <a href="https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_file_notify_information">https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_file_notify_information</a>
   <dt id="biblio-hsa-brig">[HSA-BRIG]
   <dd>HSA Foundation. <a href="http://www.hsafoundation.com/html/Content/PRM/Topics/18_BRIG/BRIG_module.htm">HSA Specification Library: BRIG Modules</a>. 2015. URL: <a href="http://www.hsafoundation.com/html/Content/PRM/Topics/18_BRIG/BRIG_module.htm">http://www.hsafoundation.com/html/Content/PRM/Topics/18_BRIG/BRIG_module.htm</a>
   <dt id="biblio-linux-cgroups">[LINUX-CGROUPS]
   <dd>Linus Torvalds et. al.. <a href="https://github.com/torvalds/linux/blob/2ce7135adc9ad081aa3c49744144376ac74fea60/include/linux/cgroup-defs.h#L450">Linux CGroups</a>. October 4th, 2018. URL: <a href="https://github.com/torvalds/linux/blob/2ce7135adc9ad081aa3c49744144376ac74fea60/include/linux/cgroup-defs.h#L450">https://github.com/torvalds/linux/blob/2ce7135adc9ad081aa3c49744144376ac74fea60/include/linux/cgroup-defs.h#L450</a>
   <dt id="biblio-n3662">[N3662]
   <dd>Lawrence Crowl; Matt Austern. <a href="https://wg21.link/n3662">C++ Dynamic Arrays</a>. April 19th, 2013. URL: <a href="https://wg21.link/n3662">https://wg21.link/n3662</a>
   <dt id="biblio-n4025">[N4025]
   <dd>Jeff Snyder; Richard Smith. <a href="https://wg21.link/n4025">C++ Dynamic Arrays</a>. May 23rd, 2014. URL: <a href="https://wg21.link/n4025">https://wg21.link/n4025</a>
   <dt id="biblio-n4762">[N4762]
   <dd>ISO/IEC JTC1/SC22/WG21 - The C++ Standards Committee; Richard Smith. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4762.pdf">N4762 - Working Draft, Standard for Programming Language C++</a>. May 7th, 2018. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4762.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4762.pdf</a>
   <dt id="biblio-redis">[REDIS]
   <dd>Salvatore Sanfilippo; redislabs. <a href="https://github.com/antirez/sds/blob/master/sds.h#L47">Redis Source</a>. Auguest 29th, 2018. URL: <a href="https://github.com/antirez/sds/blob/master/sds.h#L47">https://github.com/antirez/sds/blob/master/sds.h#L47</a>
   <dt id="biblio-sanlock-ocaml">[SANLOCK-OCAML]
   <dd>Si Beaumont. <a href="http://simonjbeaumont.com/posts/ocaml-ctypes-flexible-array-member/">OCaml ctypes: support for Flexible Array members</a>. March 30th, 2016. URL: <a href="http://simonjbeaumont.com/posts/ocaml-ctypes-flexible-array-member/">http://simonjbeaumont.com/posts/ocaml-ctypes-flexible-array-member/</a>
   <dt id="biblio-spirv-cross">[SPIRV-CROSS]
   <dd>Khronos Group. <a href="https://github.com/KhronosGroup/SPIRV-Cross/issues/10">Flexible array member in CPP output</a>. November 2nd, 2018. URL: <a href="https://github.com/KhronosGroup/SPIRV-Cross/issues/10">https://github.com/KhronosGroup/SPIRV-Cross/issues/10</a>
   <dt id="biblio-tcp-ip">[TCP-IP]
   <dd>Information Sciences Institute, University of Southern California. <a href="https://tools.ietf.org/html/rfc793">Transmission Control Protocol</a>. October 17th, 2018. URL: <a href="https://tools.ietf.org/html/rfc793">https://tools.ietf.org/html/rfc793</a>
   <dt id="biblio-udp">[UDP]
   <dd>J. Postel; ISI. <a href="https://tools.ietf.org/html/rfc768">User Datagram Protocol</a>. August 28th, 1980. URL: <a href="https://tools.ietf.org/html/rfc768">https://tools.ietf.org/html/rfc768</a>
   <dt id="biblio-usn-record-v4">[USN-RECORD-V4]
   <dd>Microsoft. <a href="https://docs.microsoft.com/en-us/windows/desktop/api/winioctl/ns-winioctl-usn_record_v4">USN Records</a>. October 17th, 2018. URL: <a href="https://docs.microsoft.com/en-us/windows/desktop/api/winioctl/ns-winioctl-usn_record_v4">https://docs.microsoft.com/en-us/windows/desktop/api/winioctl/ns-winioctl-usn_record_v4</a>
  </dl>