<!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>P0986R0: Comparison of Modules Proposals</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 li { font-size:   85%;    }

	.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 li li li .secno {
		font-size: 85%;
	}
	.toc > li li li li li .secno {
		font-size: 100%;
	}

	: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; }
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) :not(li) > .toc              { margin-left:  4rem; }
		body:not(.toc-inline) .toc .secno                  { margin-left: -4rem; }
		body:not(.toc-inline) .toc > li li li              { margin-left:  1rem; }
		body:not(.toc-inline) .toc > li li li .secno       { margin-left: -5rem; }
		body:not(.toc-inline) .toc > li li li li .secno    { margin-left: -6rem; }
		body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
	}
	body.toc-sidebar #toc :not(li) > .toc              { margin-left:  4rem; }
	body.toc-sidebar #toc .toc .secno                  { margin-left: -4rem; }
	body.toc-sidebar #toc .toc > li li li              { margin-left:  1rem; }
	body.toc-sidebar #toc .toc > li li li .secno       { margin-left: -5rem; }
	body.toc-sidebar #toc .toc > li li li li .secno    { margin-left: -6rem; }
	body.toc-sidebar #toc .toc > li li li li li .secno { margin-left: -7rem; }

	.toc li {
		clear: both;
	}


/** 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 a6f3456a9bb025e0d80ba8bd36ecc4cd6461925d" name="generator">
  <link href="http://wg21.link/p0986r0" rel="canonical">
<style>
body {
  // override 50em width from bikeshed to make Tony tables a bit less cramped
  max-width: 60em;
}
.tony {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
  width: 100%;
}
.tony div {
  margin: 0 0.5em 0 0.5em;
  width: calc(50% - 1em);
  min-width: min-content;
}
.modts::before { content: "Modules TS"; }
.atom::before { content: "P0947R0"; }
.modts::before, .atom::before {
  color: #827017;
  display: block;
  text-align: center;
  font-style: italic;
}
@media print {

}
</style>
<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; }
.highlight .c { color: #708090 } /* Comment */
.highlight .k { color: #990055 } /* Keyword */
.highlight .l { color: #000000 } /* Literal */
.highlight .n { color: #0077aa } /* Name */
.highlight .o { color: #999999 } /* Operator */
.highlight .p { color: #999999 } /* Punctuation */
.highlight .cm { color: #708090 } /* Comment.Multiline */
.highlight .cp { color: #708090 } /* Comment.Preproc */
.highlight .c1 { color: #708090 } /* Comment.Single */
.highlight .cs { color: #708090 } /* Comment.Special */
.highlight .kc { color: #990055 } /* Keyword.Constant */
.highlight .kd { color: #990055 } /* Keyword.Declaration */
.highlight .kn { color: #990055 } /* Keyword.Namespace */
.highlight .kp { color: #990055 } /* Keyword.Pseudo */
.highlight .kr { color: #990055 } /* Keyword.Reserved */
.highlight .kt { color: #990055 } /* Keyword.Type */
.highlight .ld { color: #000000 } /* Literal.Date */
.highlight .m { color: #000000 } /* Literal.Number */
.highlight .s { color: #a67f59 } /* Literal.String */
.highlight .na { color: #0077aa } /* Name.Attribute */
.highlight .nc { color: #0077aa } /* Name.Class */
.highlight .no { color: #0077aa } /* Name.Constant */
.highlight .nd { color: #0077aa } /* Name.Decorator */
.highlight .ni { color: #0077aa } /* Name.Entity */
.highlight .ne { color: #0077aa } /* Name.Exception */
.highlight .nf { color: #0077aa } /* Name.Function */
.highlight .nl { color: #0077aa } /* Name.Label */
.highlight .nn { color: #0077aa } /* Name.Namespace */
.highlight .py { color: #0077aa } /* Name.Property */
.highlight .nt { color: #669900 } /* Name.Tag */
.highlight .nv { color: #222222 } /* Name.Variable */
.highlight .ow { color: #999999 } /* Operator.Word */
.highlight .mb { color: #000000 } /* Literal.Number.Bin */
.highlight .mf { color: #000000 } /* Literal.Number.Float */
.highlight .mh { color: #000000 } /* Literal.Number.Hex */
.highlight .mi { color: #000000 } /* Literal.Number.Integer */
.highlight .mo { color: #000000 } /* Literal.Number.Oct */
.highlight .sb { color: #a67f59 } /* Literal.String.Backtick */
.highlight .sc { color: #a67f59 } /* Literal.String.Char */
.highlight .sd { color: #a67f59 } /* Literal.String.Doc */
.highlight .s2 { color: #a67f59 } /* Literal.String.Double */
.highlight .se { color: #a67f59 } /* Literal.String.Escape */
.highlight .sh { color: #a67f59 } /* Literal.String.Heredoc */
.highlight .si { color: #a67f59 } /* Literal.String.Interpol */
.highlight .sx { color: #a67f59 } /* Literal.String.Other */
.highlight .sr { color: #a67f59 } /* Literal.String.Regex */
.highlight .s1 { color: #a67f59 } /* Literal.String.Single */
.highlight .ss { color: #a67f59 } /* Literal.String.Symbol */
.highlight .vc { color: #0077aa } /* Name.Variable.Class */
.highlight .vg { color: #0077aa } /* Name.Variable.Global */
.highlight .vi { color: #0077aa } /* Name.Variable.Instance */
.highlight .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">P0986R0<br>Comparison of Modules Proposals</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2018-03-09">9 March 2018</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="http://wg21.link/p0986r0">http://wg21.link/p0986r0</a>
     <dt>Authors:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:richard@metafoo.co.uk">Richard Smith</a> (<span class="p-org org">Google</span>)
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:dlj@google.com">David Jones</a> (<span class="p-org org">Google</span>)
     <dt>Audience:
     <dd>EWG
     <dt>Project:
     <dd>ISO JTC1/SC22/WG21: Programming Language C++
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>This paper provides a comparison of the modules design in P0947R0 to the Modules TS.</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="#overview"><span class="secno">1</span> <span class="content">Overview</span></a>
     <ol class="toc">
      <li><a href="#textual"><span class="secno">1.1</span> <span class="content">The textual inclusion problem</span></a>
     </ol>
    <li><a href="#layout"><span class="secno">2</span> <span class="content">Source file layout</span></a>
    <li>
     <a href="#export"><span class="secno">3</span> <span class="content">Semantic export</span></a>
     <ol class="toc">
      <li><a href="#decl-reachability"><span class="secno">3.1</span> <span class="content">Reachability of exports</span></a>
      <li><a href="#decl-export"><span class="secno">3.2</span> <span class="content">Exporting just a declaration</span></a>
      <li><a href="#small-bmi"><span class="secno">3.3</span> <span class="content">Avoiding writing unnecessary data</span></a>
     </ol>
    <li>
     <a href="#lookup"><span class="secno">4</span> <span class="content">Name lookup</span></a>
     <ol class="toc">
      <li><a href="#adl"><span class="secno">4.1</span> <span class="content">Two-phase lookup and ADL</span></a>
     </ol>
    <li><a href="#partitions"><span class="secno">5</span> <span class="content">Module partitions</span></a>
    <li>
     <a href="#p0955r0"><span class="secno">6</span> <span class="content">Of Modules and Macros</span></a>
     <ol class="toc">
      <li><a href="#p0955r0-updates"><span class="secno">6.1</span> <span class="content">Proposal updates</span></a>
      <li><a href="#p0955r0-modularity"><span class="secno">6.2</span> <span class="content">Modularity</span></a>
      <li><a href="#p0955-representing"><span class="secno">6.3</span> <span class="content">Representing modules</span></a>
      <li><a href="#p0955-exporting"><span class="secno">6.4</span> <span class="content">Exporting macros</span></a>
     </ol>
    <li><a href="#splitting"><span class="secno">7</span> <span class="content">Splitting the Atom</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="overview"><span class="secno">1. </span><span class="content">Overview</span><a class="self-link" href="#overview"></a></h2>
   <p>This companion paper to <a data-link-type="biblio" href="#biblio-p0947r0">[P0947R0]</a> ("<strong>A</strong>nother <strong>t</strong>ake <strong>o</strong>n <strong>m</strong>odules", hereafter called the Atom proposal) provides a comparison of the design in that paper to the design of the Modules TS (<a data-link-type="biblio" href="#biblio-n4719">[N4719]</a>), focusing on examples and concerns that have been raised with the Modules TS and showing how the design in <a data-link-type="biblio" href="#biblio-p0947r0">[P0947R0]</a> might address them.</p>
   <h3 class="heading settled" data-level="1.1" id="textual"><span class="secno">1.1. </span><span class="content">The textual inclusion problem</span><a class="self-link" href="#textual"></a></h3>
   <p>Most of the problems we would like to see solved by modules are fundamentally caused by textual inclusion: lack of interface isolation, interface fragility, slow builds, ODR violations, and so on, are unintended consequences of the fact that interfaces are made visible by textually including the contents of a header file.</p>
   <p>However, we would be remiss to ignore the likelihood that legacy headers will continue to be common for several versions of the C++ standard after a modules system is adopted -- at least a decade. In some cases, we expect they will continue to exist for the foreseeable future of the C++ language. A modules system -- at least, one that seeks to fully solve the problems resulting from textual inclusion -- must provide some way to use the interfaces provided by legacy headers, without reprising the unintended consequences of textual inclusion.</p>
   <p>The Modules TS goes a long way towards solving the textual inclusion problem. However, because the Modules TS’s only solution for use of legacy headers is textual inclusion, it does not completely solve the problem. The Atom proposal extends modular semantics to legacy headers, without exposing modular code to the unintended consequences of textual inclusion. This is achieved by extracting the interface provided by the header and making it available for semantic import, allowing new code to have a complete solution to the textual inclusion problem.</p>
   <div class="example" id="example-2697cda8">
    <a class="self-link" href="#example-2697cda8"></a> 
    <div class="tony">
     <div class="modts">
<pre class="highlight"><span class="c1">// textual header, expanded</span>
<span class="c1">// by preprocessor</span>
<span class="c1"></span><span class="cp">#include</span> "legacy-header.h"<span class="cp"></span>
<span class="cp"></span><span class="n">module</span> <span class="n">Foo</span><span class="p">;</span>
</pre>
     </div>
     <div class="atom">
<pre class="highlight"><span class="n">module</span> <span class="n">Foo</span><span class="p">;</span>
<span class="c1">// semantic import of interface provided</span>
<span class="c1">// by the textual header, as if by</span>
<span class="c1">// 1) #including it in a separate context</span>
<span class="c1">// 2) extracting the interface</span>
<span class="c1">// 3) importing that interface</span>
<span class="c1"></span><span class="n">import</span> <span class="s">"legacy-header.h"</span><span class="p">;</span>
</pre>
     </div>
    </div>
   </div>
   <p>The use of textual inclusion for legacy headers in the Modules TS results in a number of issues. For instance:</p>
   <ul>
    <li data-md="">
     <p>Compile time problems are not fully solved. For as long as legacy headers remain common, we will continue to repeatedly parse and compile the same interfaces over and over again within a build. And worse, in highly parallel builds, we now need to wait for N levels of module interface parsing before we can start building leaf code; if each such level is doing a comparable amount of textual inclusion to today’s compilations, our highly-parallel build is now N times slower. Previous attempts to address this cost, such as Precompiled Headers (PCH), still have drawbacks that would not be addressed by modules.</p>
    <li data-md="">
     <p>Macro and name leakage problems remain. Without the rules and semantics required for modular interfaces, names (including macro names) would continue to leak between legacy headers, even within new, modular code. As a result, there would still be a risk of ODR violations in modular code, due to interfaces textually included from legacy headers. Additionally, the design of the Modules TS forces all legacy header inclusions to be before the module declaration, so that even the <em>module-declaration</em> and <em>import-declaration</em>s risk being modified by macros from legacy header. Correctly determining the dependencies of a source file, and even the module name, requires a full preprocessing step. The Atom proposal implicitly forms a modular interface boundary around the header itself, so that the import of the legacy header has a semantic effect, rather than a textual one, on the new, modular code, and isolates the <em>module-declaration</em> and <em>import-declaration</em>s from macros in legacy headers.</p>
    <li data-md="">
     <p>Faithfully exporting the complete contents of a module interface unit that textually includes legacy headers could still become prohibitively expensive for large volumes of transitive textual inclusion. An implementation must therefore be selective in which portions of a legacy header it writes to its Binary Module Interface (BMI) file -- blindly emitting all declarations would result in BMIs containing highly-redundant duplicate information from legacy header files. This circles back to the leakage problem of textual inclusion, and forces compromises to be made regarding visibility of names and semantic effects.</p>
   </ul>
   <p>The Atom proposal avoids these problems by excising textual inclusion of legacy headers from modular code, instead providing synthesized modules for textual headers, which are directly usable by its module system. Under the Atom proposal, legacy (but nonetheless modular) headers need be parsed only once in a complete compilation, and their modular representation can be shared by all compilations making use of the legacy header’s interfaces. The interface provided by the legacy header is completely isolated from undesirable macro and name leakage problems.</p>
   <div class="example" id="example-7d7983ca">
    <a class="self-link" href="#example-7d7983ca"></a> To see some of the differences in how the Modules TS and the Atom proposal handle code in textual headers, consider a program with three translation units -- two modules and one main file -- expressed in a form compatible with the Modules TS, and a form compatible with the Atom proposal: 
    <div class="tony">
     <div class="modts">
<pre class="highlight"><span class="cp">#include</span> "logging.h"<span class="cp"></span>
<span class="cp"></span><span class="k">export</span> <span class="n">module</span> <span class="n">Foo</span><span class="p">;</span>
<span class="k">export</span> <span class="kt">void</span> <span class="nf">f</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">LOG</span><span class="p">(</span><span class="n">INFO</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"..."</span><span class="p">;</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="cp">#include</span> "other.h"<span class="cp"></span>
<span class="cp">#include</span> "logging.h"<span class="cp"></span>
<span class="cp"></span><span class="k">export</span> <span class="n">module</span> <span class="n">Bar</span><span class="p">;</span>
<span class="n">import</span> <span class="n">Foo</span><span class="p">;</span>
<span class="k">export</span> <span class="kt">void</span> <span class="nf">g</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">LOG</span><span class="p">(</span><span class="n">INFO</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"..."</span><span class="p">;</span>
  <span class="n">f</span><span class="p">();</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="cp">#include</span> "logging.h"<span class="cp"></span>
<span class="cp"></span><span class="n">import</span> <span class="n">Bar</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">LOG</span><span class="p">(</span><span class="n">INFO</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"..."</span><span class="p">;</span>
  <span class="n">g</span><span class="p">();</span>
<span class="p">}</span>
</pre>
     </div>
     <div class="atom">
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">Foo</span><span class="p">;</span>
<span class="n">import</span> <span class="s">"logging.h"</span><span class="p">;</span>
<span class="k">export</span> <span class="kt">void</span> <span class="nf">f</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">LOG</span><span class="p">(</span><span class="n">INFO</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"..."</span><span class="p">;</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">Bar</span><span class="p">;</span>
<span class="n">import</span> <span class="s">"other.h"</span><span class="p">;</span>
<span class="n">import</span> <span class="s">"logging.h"</span><span class="p">;</span>
<span class="n">import</span> <span class="n">Foo</span><span class="p">;</span>
<span class="k">export</span> <span class="kt">void</span> <span class="nf">g</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">LOG</span><span class="p">(</span><span class="n">INFO</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"..."</span><span class="p">;</span>
  <span class="n">f</span><span class="p">();</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="n">import</span> <span class="n">Bar</span><span class="p">;</span>
<span class="n">import</span> <span class="s">"logging.h"</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">LOG</span><span class="p">(</span><span class="n">INFO</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"..."</span><span class="p">;</span>
  <span class="n">g</span><span class="p">();</span>
<span class="p">}</span>
</pre>
     </div>
    </div>
    <p>In the Modules TS version of this example, some problems are evident:</p>
    <ul>
     <li data-md="">
      <p>In order to compile the main translation unit, we must wait for <code class="highlight"><span class="n">logging</span><span class="p">.</span><span class="n">h</span></code> to be textually included and parsed three times, sequentially, potentially increasing the time between a developer initiating a build and getting back a binary.</p>
     <li data-md="">
      <p>The result of including, preprocessing, and semantically analyzing the <code class="highlight"><span class="n">logging</span><span class="p">.</span><span class="n">h</span></code> header in module <code class="highlight"><span class="n">Bar</span></code> may be different than in module <code class="highlight"><span class="n">Foo</span></code>, because names and macros from <code class="highlight"><span class="n">other</span><span class="p">.</span><span class="n">h</span></code> are visible when <code class="highlight"><span class="n">logging</span><span class="p">.</span><span class="n">h</span></code> is parsed in <code class="highlight"><span class="n">Bar</span></code>.</p>
    </ul>
    <p>Under the Atom proposal, these problems are avoided. The header <code class="highlight"><span class="n">logging</span><span class="p">.</span><span class="n">h</span></code> is notionally only <code class="highlight"><span class="cp">#include</span></code>d once, into a separate translation unit, from which its interface is extracted and then made available to <code class="highlight"><span class="n">Foo</span></code>, <code class="highlight"><span class="n">Bar</span></code>, and the main source file.</p>
   </div>
   <h2 class="heading settled" data-level="2" id="layout"><span class="secno">2. </span><span class="content">Source file layout</span><a class="self-link" href="#layout"></a></h2>
   <p>Under the Modules TS, the <em>module-declaration</em> specifying that source file is in fact part of a module may appears arbitrarily far through the file. This makes it hard, for example, for a human reader or for a tool (such as a build system) to determine essential facts about a source file, such as whether it is part of a module and what other modules it depends on  (see <a data-link-type="biblio" href="#biblio-p0273r0">[P0273R0]</a>, <a data-link-type="biblio" href="#biblio-p0629r0">[P0629R0]</a>, <a data-link-type="biblio" href="#biblio-p0713r1">[P0713R1]</a> for prior discussion). Under the Atom proposal, the <em>module-declaration</em> and all <em>import-declarations</em> appear in a <em>preamble</em>, at the beginning of the implementation file, prior to any other top-level declarations.</p>
   <div class="example" id="example-f3465188">
    <a class="self-link" href="#example-f3465188"></a> 
    <div class="tony">
     <div class="modts">
<pre class="highlight"><span class="cp">#include</span> "foo.h"<span class="cp"></span>
<span class="cp">#include</span> "bar.h"<span class="cp"></span>
<span class="cp"></span><span class="cm">/* global module declarations */</span>
<span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="cm">/* implementation */</span>
<span class="n">import</span> <span class="n">frog</span><span class="p">;</span>
<span class="n">import</span> <span class="n">badger</span><span class="p">;</span>
<span class="cm">/* more implementation */</span>
</pre>
     </div>
     <div class="atom">
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="n">import</span> <span class="s">"foo.h"</span><span class="p">;</span>
<span class="n">import</span> <span class="s">"bar.h"</span><span class="p">;</span>
<span class="n">import</span> <span class="n">frog</span><span class="p">;</span>
<span class="n">import</span> <span class="n">badger</span><span class="p">;</span>
<span class="cm">/* implementation */</span>
</pre>
     </div>
    </div>
   </div>
   <p>The ability to delay the <em>module-declaration</em> is necessary only to support textual inclusion of legacy headers and the injection of "prefix headers" -- such constructs are written prior to the <em>module-declaration</em>, outside the "purview" of the module. Under the Atom proposal, all interface importation, whether from modularized code or from legacy headers, is expected to be performed by semantic import, so the <em>module-declaration</em> can simply be required to appear first; by excising textual inclusion and preprocessing from new modular code, there is no need for a notion of "purview."</p>
   <p>The Atom proposal’s <em>preamble</em> is not only useful for human readers to determine the imports of a file, but also for tools to automatically insert and manage imports, and for build systems to infer module dependencies and form a correct dependency graph and build module interfaces in the correct order. Under the Modules TS, the entirety of a source file must be examined to correctly handle such cases.</p>
   <p>This source file layout choice allows us to avoid a problem that the Modules TS has run into: the introduction of the <code class="highlight"><span class="n">module</span></code> and <code class="highlight"><span class="n">import</span></code> keyword is a major breaking change for several codebases that use these keywords as identifiers. For example:</p>
   <ul>
    <li data-md="">
     <p>In Google’s codebase, there are around 10 uses of <code class="highlight"><span class="n">import</span></code> and 30 uses of <code class="highlight"><span class="n">module</span></code> per million lines of code.</p>
    <li data-md="">
     <p>In the LLVM codebase, there are uses of the identifier <code class="highlight"><span class="n">module</span></code> in interfaces with hard API stability guarantees.</p>
    <li data-md="">
     <p><a data-link-type="biblio" href="#biblio-p0795r0">[P0795R0]</a> identifies the public API of the Vulkan library and many others as being broken by the <code class="highlight"><span class="n">module</span></code> keyword.</p>
   </ul>
   <p>As the <code class="highlight"><span class="n">module</span></code> and <code class="highlight"><span class="n">import</span></code> keywords are only used in the preamble portion of a source file under the Atom proposal, they can be (and are) made context sensitive keywords that are only recognized within the preamble. It is thought that it might be possible to make at least the <code class="highlight"><span class="n">module</span></code> keyword be context-sensitive in the Modules TS (<a data-link-type="biblio" href="#biblio-p0924r0">[P0924R0]</a>), but doing so introduces a need for disambiguation rules and attendant language complexity.</p>
   <h2 class="heading settled" data-level="3" id="export"><span class="secno">3. </span><span class="content">Semantic export</span><a class="self-link" href="#export"></a></h2>
   <p>The problems associated with textual inclusion can be viewed in terms of how much is exported by an interface -- or, more saliently, how much extra is exported that is only ancillary to the interface itself. Under textual inclusion, this volume is often simply too much. A workable modules system should be precise in what it exports: we want to avoid pollution of names, so the module should limit the names it exposes; however, interpreting these names generally requires additional semantics.</p>
   <h3 class="heading settled" data-level="3.1" id="decl-reachability"><span class="secno">3.1. </span><span class="content">Reachability of exports</span><a class="self-link" href="#decl-reachability"></a></h3>
   <p>When a name is exported, we need to know which of its semantic properties (and those of any other names reachable through it) are also exported. The set of semantic properties considered here is broad, and includes, for example:</p>
   <ul>
    <li data-md="">
     <p>whether a class is defined,</p>
    <li data-md="">
     <p>whether a function parameter has a default argument</p>
    <li data-md="">
     <p>whether an array variable has a declared bound,</p>
   </ul>
   <p>and so on. The rules in the Modules TS for specifying which semantic properties are exported by an <em>export-declaration</em> will be briefly summarized below. (Note that this summary is not complete, by any means; the actual wording for these rules is more complex, comprising around 20% of the full text of the TS document by page count.)</p>
   <p>The central notion in use by the Modules TS is that of reachability at the point of export: when a declaration is exported, all semantic properties that can be found by starting at that declaration and walking through the entities referenced by it are also exported (regardless of whether those referenced entities are themselves explicitly exported). There is also a consistency rule: if two exports result in two different sets of semantic properties being considered reachable for the same entity, the program is ill-formed.</p>
   <div class="example" id="example-8e21f6dd">
    <a class="self-link" href="#example-8e21f6dd"></a> 
    <div class="modts">
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">A</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">B</span> <span class="p">{</span> <span class="n">A</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> <span class="p">};</span>  <span class="c1">// definition implicitly exported by export of A</span>
<span class="c1"></span><span class="k">export</span> <span class="k">struct</span> <span class="n">A</span> <span class="p">{</span> <span class="n">B</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="p">};</span>
</pre>
     Here, the export of <code class="highlight"><span class="k">struct</span> <span class="n">A</span></code> results in the definition of <code class="highlight"><span class="k">struct</span> <span class="n">B</span></code> being "reachable" from importers of module <code class="highlight"><span class="n">M</span></code>: 
<pre class="highlight"><span class="n">import</span> <span class="n">M</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">f</span><span class="p">(</span><span class="n">A</span> <span class="o">*</span><span class="n">a</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">a</span><span class="o">-></span><span class="n">p</span><span class="o">-></span><span class="n">n</span><span class="p">;</span> <span class="p">}</span>  <span class="c1">// OK, definition of B reachable</span>
</pre>
     <p>However, the name <code class="highlight"><span class="n">B</span></code> is not visible to importers of module <code class="highlight"><span class="n">M</span></code>, because it is not exported.</p>
    </div>
   </div>
   <p>This rule creates a readability and maintenance problem: the semantics of the program depend deeply and subtly on the source file order, and an innocent-looking source reordering can have unexpected effects on the interface exported by a module, by increasing or reducing the set of exported semantic properties or by rendering the program ill-formed.</p>
   <div class="example" id="example-7eb9d294">
    <a class="self-link" href="#example-7eb9d294"></a> 
    <div class="modts">
      A maintenance programmer may decide to rearrange the contents of the module interface unit from the previous example as follows: 
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">A</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">B</span><span class="p">;</span> <span class="c1">// state of B at this point exported by export of A</span>
<span class="c1"></span><span class="k">export</span> <span class="k">struct</span> <span class="n">A</span> <span class="p">{</span> <span class="n">B</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="p">};</span>
<span class="k">struct</span> <span class="n">B</span> <span class="p">{</span> <span class="n">A</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> <span class="p">};</span>  <span class="c1">// definition no longer implicitly exported by A</span>
</pre>
     <p>This appears to be an innocent change. The module interface unit still compiles. But the client code is now broken, because the definition of <code class="highlight"><span class="k">struct</span> <span class="n">B</span></code> is no longer reachable at the point of the <code class="highlight"><span class="k">export</span></code>.</p>
    </div>
   </div>
   <p>And seemingly-irrelevant changes can have surprising effects on the program. Notably, the rule for consistency of exports may render a program ill-formed simply due to the order in which declarations appear in the modular file.</p>
   <div class="example" id="example-f0e6b343">
    <a class="self-link" href="#example-f0e6b343"></a> 
    <div class="modts">
      Suppose after further development work, the module interface looks like this: 
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">A</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">B</span><span class="p">;</span> <span class="c1">// state of B at this point exported by export of A</span>
<span class="c1"></span>
<span class="k">export</span> <span class="k">struct</span> <span class="n">A</span> <span class="p">{</span> <span class="n">B</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="p">};</span>
<span class="k">struct</span> <span class="n">B</span> <span class="p">{</span> <span class="n">A</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> <span class="p">};</span>  <span class="c1">// state of B at this point exported by X::make</span>
<span class="c1"></span><span class="k">export</span> <span class="k">class</span> <span class="nc">X</span> <span class="p">{</span>
  <span class="n">X</span><span class="p">(...);</span>
<span class="k">private</span><span class="o">:</span>
  <span class="n">B</span> <span class="o">*</span><span class="n">make</span><span class="p">()</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
<span class="p">};</span>
</pre>
     <p>Because struct <code class="highlight"><span class="n">B</span></code> had no definition when referenced from the definition of exported class <code class="highlight"><span class="n">A</span></code>, the later implicit implicit export of the definition of struct <code class="highlight"><span class="n">B</span></code> by the private member function <code class="highlight"><span class="n">X</span><span class="o">::</span><span class="n">make</span></code> results in <code class="highlight"><span class="n">M</span></code> being ill-formed.</p>
     <p>Presuming that the intent is to not export the definition of <code class="highlight"><span class="n">B</span></code>, <code class="highlight"><span class="n">M</span></code> would need to be carefully restructured; for example, like this:</p>
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">A</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">B</span><span class="p">;</span>  <span class="c1">// state of B at this point exported by A and X::make</span>
<span class="c1"></span>
<span class="k">export</span> <span class="k">struct</span> <span class="n">A</span> <span class="p">{</span> <span class="n">B</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="p">};</span>
<span class="k">export</span> <span class="k">class</span> <span class="nc">X</span> <span class="p">{</span>
  <span class="n">X</span><span class="p">(...);</span>
<span class="k">private</span><span class="o">:</span>
  <span class="n">B</span> <span class="o">*</span><span class="n">make</span><span class="p">();</span>
<span class="p">};</span>
<span class="k">struct</span> <span class="n">B</span> <span class="p">{</span> <span class="n">A</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> <span class="p">};</span>
<span class="kr">inline</span> <span class="n">B</span> <span class="o">*</span><span class="n">X</span><span class="o">::</span><span class="n">make</span><span class="p">()</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
</pre>
     <p>Note that this adds another source-layout constraint: now the <code class="highlight"><span class="n">X</span><span class="o">::</span><span class="n">make</span></code> function must be moved out of line.</p>
    </div>
   </div>
   <p>The Atom proposal uses a different rule for visibility that does not rely on source ordering:</p>
   <ul>
    <li data-md="">
     <p>name visibility is restricted to those names exported by the module</p>
    <li data-md="">
     <p>all semantic effects within the module interface unit are visible to a direct importer of that translation unit</p>
   </ul>
   <p>This tradeoff affords module authors precise control over which parts of the module interface can be accessed by an importer -- a notion of narrowed reachability -- while also ensuring that uses of the exported interface are uniform and unambiguous.</p>
   <div class="example" id="example-926ccfcc">
    <a class="self-link" href="#example-926ccfcc"></a> 
    <div class="atom">
      In the Atom proposal, the module interface from the prior example can be represented as follows: 
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="nl">M</span><span class="p">:</span><span class="n">BImpl</span><span class="p">;</span>  <span class="c1">// partition BImpl of module M</span>
<span class="c1"></span><span class="k">struct</span> <span class="n">A</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">B</span> <span class="p">{</span> <span class="n">A</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> <span class="p">};</span>
</pre>
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="nl">import</span> <span class="p">:</span><span class="n">BImpl</span><span class="p">;</span>  <span class="c1">// import of partition BImpl, without re-export</span>
<span class="c1"></span><span class="k">export</span> <span class="k">struct</span> <span class="n">A</span> <span class="p">{</span> <span class="n">B</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="p">};</span>
<span class="k">export</span> <span class="k">class</span> <span class="nc">X</span> <span class="p">{</span>
  <span class="n">X</span><span class="p">(...);</span>
<span class="k">private</span><span class="o">:</span>
  <span class="n">B</span> <span class="o">*</span><span class="n">make</span><span class="p">()</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
<span class="p">};</span>
</pre>
     <p>Note that the relative order of declarations has no effect on which names and semantic effects are exported. The definition of <code class="highlight"><span class="n">B</span></code> is not exported from <code class="highlight"><span class="n">M</span></code> because <code class="highlight"><span class="n">M</span></code> does not export the partition <code class="highlight"><span class="nl">M</span><span class="p">:</span><span class="n">BImpl</span></code> in which it is defined.</p>
    </div>
   </div>
   <h3 class="heading settled" data-level="3.2" id="decl-export"><span class="secno">3.2. </span><span class="content">Exporting just a declaration</span><a class="self-link" href="#decl-export"></a></h3>
   <p>One of the goals of the Modules TS' reachability model is to permit control over whether a definition or merely a declaration of an entity is exported, but as shown, the technique used is fragile in the presence of source reordering. The module partitions feature in the Atom proposal provides a mechanism to control which semantic effects are exported in a clear way that is robust against source reordering.</p>
   <div class="example" id="example-fa7306a9">
    <a class="self-link" href="#example-fa7306a9"></a> Suppose we wish module <code class="highlight"><span class="n">M</span></code> to export an opaque type <code class="highlight"><span class="n">Handle</span></code>, which is a pointer to some implementation type <code class="highlight"><span class="n">Impl</span></code>, along with some inline functions that access the <code class="highlight"><span class="n">Impl</span></code> object. 
    <div class="tony">
     <div class="modts">
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="c1">// Export Handle as a typedef</span>
<span class="c1">// for a pointer to incomplete</span>
<span class="c1">// type Impl</span>
<span class="c1"></span><span class="k">struct</span> <span class="n">Impl</span><span class="p">;</span>
<span class="k">export</span> <span class="k">using</span> <span class="n">Handle</span> <span class="o">=</span> <span class="n">Impl</span><span class="o">*</span><span class="p">;</span>

<span class="c1">// The definition of Impl must</span>
<span class="c1">// appear after the export of</span>
<span class="c1">// Handle or the definition will</span>
<span class="c1">// also be exported</span>
<span class="c1"></span><span class="k">struct</span> <span class="n">Impl</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> <span class="p">};</span>
<span class="k">export</span> <span class="kr">inline</span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="n">Handle</span> <span class="n">h</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="n">h</span><span class="o">-></span><span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// ...</span>
</pre>
     </div>
     <div class="atom">
<pre class="highlight"><span class="c1">// Definition of struct Impl is</span>
<span class="c1">// owned by the Impl partition</span>
<span class="c1">// of module M</span>
<span class="c1"></span><span class="k">export</span> <span class="n">module</span> <span class="nl">M</span><span class="p">:</span><span class="n">Impl</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">Impl</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> <span class="p">};</span>
</pre>
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="c1">// Semantic effect of defining</span>
<span class="c1">// struct Impl is not re-exported</span>
<span class="c1"></span><span class="nl">import</span> <span class="p">:</span><span class="n">Impl</span><span class="p">;</span>

<span class="c1">// Export Handle as a typedef</span>
<span class="c1">// for a pointer to type Impl,</span>
<span class="c1">// which is incomplete outside</span>
<span class="c1">// module M</span>
<span class="c1"></span><span class="k">export</span> <span class="k">using</span> <span class="n">Handle</span> <span class="o">=</span> <span class="n">Impl</span><span class="o">*</span><span class="p">;</span>
<span class="k">export</span> <span class="kr">inline</span> <span class="kt">int</span> <span class="nf">get</span><span class="p">(</span><span class="n">Handle</span> <span class="n">h</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="n">h</span><span class="o">-></span><span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// ...</span>
</pre>
     </div>
    </div>
    <p>In the Atom approach, the non-exported semantic properties are in a distinct source file. (The downside is that this level of control requires at least one additional source file to exist, but the presence of module partitions is, by design, not visible outside the module.)</p>
    <p>Note that the name of struct <code class="highlight"><span class="n">Impl</span></code> is visible within <code class="highlight"><span class="n">M</span></code> despite not being exported from <code class="highlight"><span class="nl">M</span><span class="p">:</span><span class="n">Impl</span></code>. An import of a translation unit in the same module makes available all names from that translation unit, whether exported or not. The definition of <code class="highlight"><span class="k">struct</span> <span class="n">Impl</span></code> is visible within <code class="highlight"><span class="n">M</span></code> because the translation unit <code class="highlight"><span class="nl">M</span><span class="p">:</span><span class="n">Impl</span></code> containing its definition is imported. However, it is not visible to translation units outside module <code class="highlight"><span class="n">M</span></code> that import <code class="highlight"><span class="n">M</span></code>, because <code class="highlight"><span class="n">M</span></code> does not re-export <code class="highlight"><span class="nl">M</span><span class="p">:</span><span class="n">Impl</span></code>. Further, <code class="highlight"><span class="nl">M</span><span class="p">:</span><span class="n">Impl</span></code> cannot be directly imported into translation units outside module <code class="highlight"><span class="n">M</span></code>.</p>
   </div>
   <h3 class="heading settled" data-level="3.3" id="small-bmi"><span class="secno">3.3. </span><span class="content">Avoiding writing unnecessary data</span><a class="self-link" href="#small-bmi"></a></h3>
   <p>A desirable property present in the Modules TS rule is that it allows an implementation to be more frugal with the set of data it exports to the BMI: it can start at the set of exported declarations and recurse through its internal representation, writing out only those things that are reachable, and not need to emit any other data. This is still possible under the Atom proposal, but it is now a quality-of-implementation optimization, rather than forming part of the language semantics and being included in the user model. An implementation wishing to perform this optimization would need wait until the end of the translation unit to perform the traversal of its internal representation, to ensure it does not miss semantic properties added after the point of export.</p>
   <h2 class="heading settled" data-level="4" id="lookup"><span class="secno">4. </span><span class="content">Name lookup</span><a class="self-link" href="#lookup"></a></h2>
   <h3 class="heading settled" data-level="4.1" id="adl"><span class="secno">4.1. </span><span class="content">Two-phase lookup and ADL</span><a class="self-link" href="#adl"></a></h3>
   <p>Name visibility is complicated by deferred forms of name lookup. There are two widely-used techniques: two-phase lookup of class (and enumeration) member names, and argument-dependent name lookup (ADL). In both cases, the binding of a name can be deferred from the point of template definition until to the point of instantiation, and the programmer may intend for names from either context (or an intervening context) to be visible.</p>
   <p>In the Modules TS, names from the following sources are considered when template instantiation requires name lookup:</p>
   <ul>
    <li data-md="">
     <p>names from the (outermost) point of instantiation and from the (innermost) point of definition (names from translation units containing intervening instantiations are ignored)</p>
    <li data-md="">
     <p>for ADL involving an associated type owned by a named module, names from the module interface unit owning the type</p>
   </ul>
   <p>The Atom proposal considers these sources:</p>
   <ul>
    <li data-md="">
     <p>names from the (outermost) point of instantiation, names from the (innermost) point of definition, and names from every intervening module interface along the path of instantiation</p>
   </ul>
   <p>ADL involving an associated type owned by a named module is not treated as a special case. We are open to revisiting this, but the motivating examples for the rule in the Modules TS involve a type that is visible along the path of instantiation, so it is unclear that motivation for a special case rule remains when using the lookup rule from the Atom proposal.</p>
   <p>The following examples, taken from <strong>[temp.dep.res]</strong> in the Modules TS, illustrate the difference:</p>
   <div class="example" id="example-14fd98e2">
    <a class="self-link" href="#example-14fd98e2"></a> 
    <div class="tony">
     <div class="modts">
<pre class="highlight"><span class="c1">// Header file X.h</span>
<span class="c1"></span><span class="k">namespace</span> <span class="n">Q</span> <span class="p">{</span>
  <span class="k">struct</span> <span class="n">X</span> <span class="p">{</span> <span class="p">};</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="c1">// Interface unit of M1</span>
<span class="c1"></span><span class="cp">#include</span> "X.h" // global module<span class="cp"></span>
<span class="cp"></span><span class="k">namespace</span> <span class="n">Q</span> <span class="p">{</span>
  <span class="kt">void</span> <span class="n">g_impl</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">X</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">export</span> <span class="n">module</span> <span class="n">M1</span><span class="p">;</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="kt">void</span> <span class="n">g</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">g_impl</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">Q</span><span class="o">::</span><span class="n">X</span><span class="p">{</span> <span class="p">});</span> <span class="c1">// #1</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<pre class="highlight"><span class="c1">// Interface unit of M2</span>
<span class="c1"></span><span class="cp">#include</span> "X.h"<span class="cp"></span>
<span class="cp"></span><span class="n">import</span> <span class="n">M1</span><span class="p">;</span>
<span class="k">export</span> <span class="n">module</span> <span class="n">M2</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">h</span><span class="p">(</span><span class="n">Q</span><span class="o">::</span><span class="n">X</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">g</span><span class="p">(</span><span class="n">x</span><span class="p">);</span> <span class="c1">// OK</span>
<span class="c1"></span><span class="p">}</span>
</pre>
     </div>
     <div class="atom">
<pre class="highlight"><span class="c1">// Header file X.h</span>
<span class="c1"></span><span class="k">namespace</span> <span class="n">Q</span> <span class="p">{</span>
<span class="k">struct</span> <span class="n">X</span> <span class="p">{</span> <span class="p">};</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M1</span><span class="p">;</span>
<span class="n">import</span> <span class="s">"X.h"</span><span class="p">;</span>
<span class="k">namespace</span> <span class="n">Q</span> <span class="p">{</span>
  <span class="k">extern</span> <span class="s">"C++"</span> <span class="kt">void</span> <span class="n">g_impl</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">X</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="kt">void</span> <span class="n">g</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">g_impl</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">Q</span><span class="o">::</span><span class="n">X</span><span class="p">{</span> <span class="p">});</span> <span class="c1">// #1</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M2</span><span class="p">;</span>
<span class="n">import</span> <span class="s">"X.h"</span><span class="p">;</span>
<span class="n">import</span> <span class="n">M1</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">h</span><span class="p">(</span><span class="n">Q</span><span class="o">::</span><span class="n">X</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">g</span><span class="p">(</span><span class="n">x</span><span class="p">);</span> <span class="c1">// OK</span>
<span class="c1"></span><span class="p">}</span>
</pre>
     </div>
    </div>
    <p>In this example, the Modules TS and the Atom proposal give the same outcome for different reasons. In the Modules TS, we rely on lookup at #1 in the template definition context to find <code class="highlight"><span class="n">Q</span><span class="o">::</span><span class="n">g_impl</span></code> despite it not being visible to normal lookup. In the Atom proposal, <code class="highlight"><span class="n">Q</span><span class="o">::</span><span class="n">g_impl</span></code> is also visible to lookup in the instantiation context, because <code class="highlight"><span class="n">M1</span></code> is in the path of instantiation.</p>
   </div>
   <p>The Modules TS creates an asymmetry between types owned by modules, and those from legacy headers. In some cases, this results in a failure to find names that were intended to be found. Fixing this is problematic in the Modules TS: because legacy headers are textually included at every point of use (see <a href="#textual">§1.1 The textual inclusion problem</a>), it would be prohibitively expensive to retain duplicate copies of all declarations from all legacy headers in case they are reached by a template instantiation.</p>
   <p>Because the Atom proposal performs separate modular compilation even for legacy header files, sufficient information can be cheaply retained to permit a consistent semantic model even when mixing legacy code with modular code. The same rules apply to the availability of semantic properties, such as type completeness, which the Modules TS does not appear to address.</p>
   <div class="example" id="example-4fd0669a">
    <a class="self-link" href="#example-4fd0669a"></a> 
    <div class="tony">
     <div class="modts">
<pre class="highlight"><span class="c1">// Module interface unit of A</span>
<span class="c1"></span><span class="k">export</span> <span class="n">module</span> <span class="n">A</span><span class="p">;</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">t</span> <span class="o">+</span> <span class="n">t</span><span class="p">;</span> <span class="c1">// #1</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<pre class="highlight"><span class="c1">// Module interface unit of B</span>
<span class="c1"></span><span class="k">export</span> <span class="n">module</span> <span class="n">B</span><span class="p">;</span>
<span class="n">import</span> <span class="n">A</span><span class="p">;</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span> <span class="n">U</span><span class="o">></span>
<span class="kt">void</span> <span class="n">g</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">,</span> <span class="n">U</span> <span class="n">u</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">f</span><span class="p">(</span><span class="n">t</span><span class="p">);</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="c1">// Module interface unit of C</span>
<span class="c1"></span><span class="cp">#include</span> &lt;string><span class="cp"></span>
<span class="cp"></span><span class="n">import</span> <span class="n">B</span><span class="p">;</span>
<span class="k">export</span> <span class="n">module</span> <span class="n">C</span><span class="p">;</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="kt">void</span> <span class="n">h</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">g</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">{</span> <span class="p">},</span> <span class="n">t</span><span class="p">);</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="c1">// Translation unit of main()</span>
<span class="c1"></span><span class="n">import</span> <span class="n">C</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">i</span><span class="p">()</span> <span class="p">{</span>
  <span class="c1">// ill-formed: ’+’ not found at #1</span>
<span class="c1"></span>  <span class="c1">// nor at point of instantiation of</span>
<span class="c1"></span>  <span class="c1">// f&lt;std::string> (just before 'i()')</span>
<span class="c1"></span>  <span class="n">h</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</pre>
     </div>
     <div class="atom">
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">A</span><span class="p">;</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">t</span> <span class="o">+</span> <span class="n">t</span><span class="p">;</span> <span class="c1">// #1</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">B</span><span class="p">;</span>
<span class="n">import</span> <span class="n">A</span><span class="p">;</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span> <span class="n">U</span><span class="o">></span>
<span class="kt">void</span> <span class="n">g</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">,</span> <span class="n">U</span> <span class="n">u</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">f</span><span class="p">(</span><span class="n">t</span><span class="p">);</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">C</span><span class="p">;</span>
<span class="n">import</span> <span class="o">&lt;</span><span class="n">string</span><span class="o">></span><span class="p">;</span>
<span class="n">import</span> <span class="n">B</span><span class="p">;</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="kt">void</span> <span class="n">h</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">g</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">{</span> <span class="p">},</span> <span class="n">t</span><span class="p">);</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="c1">// Translation unit of main()</span>
<span class="c1"></span><span class="n">import</span> <span class="n">C</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">i</span><span class="p">()</span> <span class="p">{</span>
  <span class="c1">// OK: path of instantiation includes</span>
<span class="c1"></span>  <span class="c1">// module interface units of A, B, C,</span>
<span class="c1"></span>  <span class="c1">// and point of instantiation of</span>
<span class="c1"></span>  <span class="c1">// h&lt;int> (just before ’i()’);</span>
<span class="c1"></span>  <span class="c1">// operator+(string, string) visible</span>
<span class="c1"></span>  <span class="c1">// in C</span>
<span class="c1"></span>  <span class="n">h</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</pre>
     </div>
    </div>
    <p>The Atom proposal accepts this example that the Modules TS rejects. Under the Modules TS, it would be prohibitively expensive to retain a full copy of <code class="highlight"><span class="o">&lt;</span><span class="n">string</span><span class="o">></span></code> as part of the BMI for module <code class="highlight"><span class="n">C</span></code>, and there is no hint in the definition of <code class="highlight"><span class="n">C</span></code> that <code class="highlight"><span class="n">string</span></code>'s <code class="highlight"><span class="k">operator</span><span class="o">+</span></code> will be needed. As such, it is not available, although no translation unit in this example did anything unreasonable.</p>
    <p>Under the Atom proposal, an external modular representation of <code class="highlight"><span class="o">&lt;</span><span class="n">string</span><span class="o">></span></code> is available, independent of module <code class="highlight"><span class="n">C</span></code>, and the compiler can reference that when performing the instantiation of <code class="highlight"><span class="n">f</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span></code> with <code class="highlight"><span class="n">C</span></code> in the path of instantiation.</p>
   </div>
   <p>ADL idioms, such as <code class="highlight"><span class="k">using</span> <span class="n">std</span><span class="o">::</span><span class="n">min</span><span class="p">;</span> <span class="n">min</span><span class="p">(...)</span></code>, would be affected when the set of scopes considered for lookup is changed. Consider this example:</p>
   <div class="example" id="example-594732e5">
    <a class="self-link" href="#example-594732e5"></a> Suppose module <code class="highlight"><span class="n">M1</span></code> exports a template function. Further, suppose module <code class="highlight"><span class="n">M2</span></code> imports <code class="highlight"><span class="n">M1</span></code>, and exports a different template function which calls <code class="highlight"><span class="n">M1</span></code>'s exported function: 
    <div class="tony">
     <div class="modts">
<pre class="highlight"><span class="c1">// Module interface unit of M1</span>
<span class="c1"></span><span class="cp">#include</span> &lt;algorithm><span class="cp"></span>
<span class="cp"></span><span class="k">export</span> <span class="n">module</span> <span class="n">M1</span><span class="p">;</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span> <span class="n">U</span><span class="o">></span>
<span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span> <span class="n">t</span><span class="p">,</span> <span class="n">U</span><span class="o">&amp;</span> <span class="n">u</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">min</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">u</span><span class="p">);</span> <span class="c1">// #1</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<pre class="highlight"><span class="c1">// Module interface unit of M2</span>
<span class="c1"></span><span class="cp">#include</span> &lt;locale><span class="cp"></span>
<span class="cp"></span><span class="k">struct</span> <span class="nl">Aux</span> <span class="p">:</span> <span class="n">std</span><span class="o">::</span><span class="n">ctype_base</span> <span class="p">{</span>
  <span class="k">operator</span> <span class="kt">int</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
<span class="kt">void</span> <span class="nf">min</span><span class="p">(</span><span class="n">Aux</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">Aux</span><span class="o">&amp;</span><span class="p">);</span> <span class="c1">// #2</span>
<span class="c1"></span><span class="k">export</span> <span class="n">module</span> <span class="n">M2</span><span class="p">;</span>
<span class="n">import</span> <span class="n">M1</span><span class="p">;</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="kt">void</span> <span class="n">g</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">Aux</span> <span class="n">aux</span><span class="p">;</span>
  <span class="n">f</span><span class="p">(</span><span class="n">aux</span><span class="p">,</span> <span class="n">aux</span><span class="p">);</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="c1">// Elsewhere, translation unit</span>
<span class="c1">// of global module</span>
<span class="c1"></span><span class="n">import</span> <span class="n">M2</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">h</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">g</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</pre>
     </div>
     <div class="atom">
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M1</span><span class="p">;</span>
<span class="n">import</span> <span class="o">&lt;</span><span class="n">algorithm</span><span class="o">></span><span class="p">;</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span> <span class="n">U</span><span class="o">></span>
<span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span> <span class="n">t</span><span class="p">,</span> <span class="n">U</span><span class="o">&amp;</span> <span class="n">u</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">min</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">u</span><span class="p">);</span> <span class="c1">// #1</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<pre class="highlight"><span class="k">export</span> <span class="n">module</span> <span class="n">M2</span><span class="p">;</span>
<span class="n">import</span> <span class="n">M1</span><span class="p">;</span>
<span class="n">import</span> <span class="o">&lt;</span><span class="n">locale</span><span class="o">></span><span class="p">;</span>
<span class="c1">// Note: extern "C++" denotes</span>
<span class="c1">// non-modular ownership semantics</span>
<span class="c1"></span><span class="k">extern</span> <span class="s">"C++"</span> <span class="p">{</span>
  <span class="k">struct</span> <span class="nl">Aux</span> <span class="p">:</span> <span class="n">std</span><span class="o">::</span><span class="n">ctype_base</span> <span class="p">{</span>
    <span class="k">operator</span> <span class="kt">int</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
  <span class="p">};</span>
  <span class="kt">void</span> <span class="nf">min</span><span class="p">(</span><span class="n">Aux</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">Aux</span><span class="o">&amp;</span><span class="p">);</span> <span class="c1">// #2</span>
<span class="c1"></span><span class="p">}</span>
<span class="k">export</span> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="kt">void</span> <span class="n">g</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">Aux</span> <span class="n">aux</span><span class="p">;</span>
  <span class="n">f</span><span class="p">(</span><span class="n">aux</span><span class="p">,</span> <span class="n">aux</span><span class="p">);</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="c1">// Elsewhere, not in</span>
<span class="c1">// a module</span>
<span class="c1"></span><span class="n">import</span> <span class="n">M2</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">h</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">g</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</pre>
     </div>
    </div>
    <p>As described in <strong>[temp.dep.res]p5</strong> of the Modules TS, the Modules TS version of this program has undefined behavior. The behavior in the Atom proposal is defined: when the call to <code class="highlight"><span class="n">min</span></code> within <code class="highlight"><span class="n">f</span><span class="o">&lt;</span><span class="n">Aux</span><span class="p">,</span> <span class="n">Aux</span><span class="o">></span></code> at <code class="highlight"><span class="cp">#1</span></code> is instantiated, the path of instantiation starts in <code class="highlight"><span class="n">h</span></code>, includes the module interface unit of <code class="highlight"><span class="n">M2</span></code>, and ends in <code class="highlight"><span class="n">f</span></code> (which considers the module interface unit of <code class="highlight"><span class="n">M1</span></code>). For this path of instantiation, the <code class="highlight"><span class="n">min</span></code> declared at <code class="highlight"><span class="cp">#2</span></code> is a candidate and is selected.</p>
   </div>
   <h2 class="heading settled" data-level="5" id="partitions"><span class="secno">5. </span><span class="content">Module partitions</span><a class="self-link" href="#partitions"></a></h2>
   <p>The desire for a module partition system has been explored in <a data-link-type="biblio" href="#biblio-p0273r0">[P0273R0]</a>, <a data-link-type="biblio" href="#biblio-p0584r0">[P0584R0]</a>, and <a data-link-type="biblio" href="#biblio-p0775r0">[P0775R0]</a>. The module partition system in the Atom proposal is derived from the system proposed in <a data-link-type="biblio" href="#biblio-p0775r0">[P0775R0]</a>, which saw strong support at Albuquerque. We believe this partition system would be equally effective as an addition to the Modules TS.</p>
   <h2 class="heading settled" data-level="6" id="p0955r0"><span class="secno">6. </span><span class="content">Of Modules and Macros</span><a class="self-link" href="#p0955r0"></a></h2>
   <p>The paper <a data-link-type="biblio" href="#biblio-p0955r0">[P0955R0]</a> provides valuable insights into the notion of modularity and what a modules system for C++ should provide, and we would like to analyze its arguments and compare how they apply to the Modules TS and to the Atom proposal.</p>
   <h3 class="heading settled" data-level="6.1" id="p0955r0-updates"><span class="secno">6.1. </span><span class="content">Proposal updates</span><a class="self-link" href="#p0955r0-updates"></a></h3>
   <p>In response to the commentary in <a data-link-type="biblio" href="#biblio-p0955r0">[P0955R0]</a>, as well as private feedback, we have made two changes to the direction in <a data-link-type="biblio" href="#biblio-p0947r0">[P0947R0]</a>:</p>
   <ul>
    <li data-md="">
     <p>When a legacy module unit is re-exported by a module interface unit, only its names and semantic effects are re-exported; its macros are not. This makes it trivial to form a "macro-free" modular version of a legacy header:</p>
<pre class="highlight">    <span class="k">export</span> <span class="n">module</span> <span class="n">my</span><span class="p">.</span><span class="n">module</span><span class="p">;</span>
    <span class="k">export</span> <span class="n">import</span> <span class="s">"my/header.h"</span><span class="p">;</span>
</pre>
    <li data-md="">
     <p>The <code class="highlight"><span class="cp">#export</span></code> syntax is explictily noted as being a separable part of the proposal, on which no other part depends. We still believe this functionality is important for the medium-term future of C++ (until the use cases requiring macros as part of interfaces are addressed in other ways), but its acceptance or otherwise need not be coupled to the rest of the proposal.</p>
   </ul>
   <p>The consequence of these two changes is that, in the case where <code class="highlight"><span class="cp">#export</span></code> is not adopted, only legacy modules can contain macros and only legacy module imports can import macros, allowing a user to visually distinguish between an import-with-macros and an import-without-macros. Compared to the Modules TS, the only places where an <code class="highlight"><span class="n">import</span></code> provides macros would be the same places where the Modules TS would require a <code class="highlight"><span class="cp">#include</span></code>.</p>
   <h3 class="heading settled" data-level="6.2" id="p0955r0-modularity"><span class="secno">6.2. </span><span class="content">Modularity</span><a class="self-link" href="#p0955r0-modularity"></a></h3>
   <p>As <a data-link-type="biblio" href="#biblio-p0955r0">[P0955R0]</a> explains, code hygiene requires that we avoid textual inclusion for interface import, specifically because earlier names and macros "leak" into later textually-included interfaces. Semantic import, such as that offered by the <code class="highlight"><span class="n">import</span></code> facilities of the Atom proposal or the Modules TS, avoids these problems by defining the interface of the imported component independent of the accumulated state at the point of import.</p>
   <p>Because the Modules TS relies on textual inclusion for legacy headers, the non-modularity problems inherent to textual inclusion will still occur for as long as legacy headers remain.</p>
   <div class="example" id="example-6b798f9a">
    <a class="self-link" href="#example-6b798f9a"></a> 
    <div class="tony">
     <div class="modts">
<pre class="highlight"><span class="cp">#include</span> "legacy1.h"<span class="cp"></span>
<span class="cp">#include</span> "legacy2.h"<span class="cp"></span>
<span class="cp"></span><span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="n">import</span> <span class="n">canines</span><span class="p">.</span><span class="n">sam</span><span class="p">;</span>
<span class="n">import</span> <span class="n">lagomorphs</span><span class="p">.</span><span class="n">max</span><span class="p">;</span>
</pre>
     </div>
     <div class="atom">
<pre class="highlight"><span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="n">import</span> <span class="s">"legacy1.h"</span><span class="p">;</span>
<span class="n">import</span> <span class="s">"legacy2.h"</span><span class="p">;</span>
<span class="n">import</span> <span class="n">canines</span><span class="p">.</span><span class="n">sam</span><span class="p">;</span>
<span class="n">import</span> <span class="n">lagomorphs</span><span class="p">.</span><span class="n">max</span><span class="p">;</span>
</pre>
     </div>
    </div>
    <p>In the Modules TS, names and macros from <code class="highlight"><span class="s">"legacy1.h"</span></code> still leak into <code class="highlight"><span class="s">"legacy2.h"</span></code>. In the Atom proposal, because each legacy header is (notionally) compiled in isolation, names and macros from the importing translation unit cannot leak from one legacy header to another.</p>
    <p>In the Modules TS, macros from <code class="highlight"><span class="s">"legacy1.h"</span></code> and <code class="highlight"><span class="s">"legacy2.h"</span></code> can even affect the interpretation of later <code class="highlight"><span class="n">import</span></code>s: if <code class="highlight"><span class="s">"legacy1.h"</span></code> exports an object-like macro named <code class="highlight"><span class="n">max</span></code>, this macro will intrude upon the <code class="highlight"><span class="n">import</span> <span class="n">lagomorphs</span><span class="p">.</span><span class="n">max</span><span class="p">;</span></code> line later and alter the imported module name. This means that a build system needs to perform a full preprocessing step (including textual inclusion of legacy headers) to determine the build dependencies for <code class="highlight"><span class="n">M</span></code>. Under the Atom proposal, this cannot happen: expansion of macros from legacy headers is disallowed within the preamble of the source file. In order to make this possible, imported macros are distinguished from those on the command line, and a natural source ordering of imports is enforced. (Under the current proposal, such expansion is ill-formed, as we find that to be the more obvious behavior, but we could equally specify that such macro expansion simply does not occur.)</p>
   </div>
   <h3 class="heading settled" data-level="6.3" id="p0955-representing"><span class="secno">6.3. </span><span class="content">Representing modules</span><a class="self-link" href="#p0955-representing"></a></h3>
   <p>The description in <a data-link-type="biblio" href="#biblio-p0955r0">[P0955R0]</a> of macros describes a concern with macros whose definitions differ between translation units:</p>
   <blockquote>
    <p><strong>file 1:</strong></p>
<pre class="highlight"><span class="cp">#define Foo 1</span>
<span class="cp"></span><span class="c1">// define module M</span>
</pre>
    <p><strong>file 2:</strong></p>
<pre class="highlight"><span class="cp">#define Foo 2</span>
<span class="cp"></span><span class="n">import</span> <span class="n">M</span><span class="p">;</span>
<span class="c1">// use M and Foo</span>
</pre>
   </blockquote>
   <p><a data-link-type="biblio" href="#biblio-p0955r0">[P0955R0]</a> observes that the code in file 1 and file 2 will see a different value of <code class="highlight"><span class="n">Foo</span></code> (perhaps <code class="highlight"><span class="n">Foo</span></code> is <code class="highlight"><span class="n">NDEBUG</span></code>), and suggests that this will lead to disaster if, for example, a <code class="highlight"><span class="k">struct</span></code> used by both file 1 and file 2 (say, <code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span></code>) depends on the value of <code class="highlight"><span class="n">Foo</span></code>.</p>
   <p>However, this argument has an implicit, intervening step: in order for file 1 and file 2 to see different versions of the <code class="highlight"><span class="k">struct</span></code>, the <code class="highlight"><span class="k">struct</span></code> definition must have been compiled twice, (presumably) by textual inclusion. That is: the problem highlighted here is a consequence of the use of textual inclusion to provide a definition of the <code class="highlight"><span class="k">struct</span></code>. Under the Atom proposal, the disaster scenario outlined by <a data-link-type="biblio" href="#biblio-p0955r0">[P0955R0]</a> does not occur:</p>
   <div class="example" id="example-b99a002c">
    <a class="self-link" href="#example-b99a002c"></a> For the purpose of this example, let us assume that the standard library has not yet been modularized, and is being treated as a legacy header. Obviously, even once the standard library is provided as a set of modules, the same situation will continue to arise with other legacy headers. 
    <div class="tony">
     <div class="modts">
<pre class="highlight"><span class="cp">#undef NDEBUG</span>
<span class="cp">#include</span> &lt;vector><span class="cp"></span>
<span class="cp"></span><span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="k">export</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span> <span class="n">f</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">};</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="cp">#define NDEBUG 1</span>
<span class="cp">#include</span> &lt;vector><span class="cp"></span>
<span class="cp">#include</span> &lt;iostream><span class="cp"></span>
<span class="cp"></span><span class="n">import</span> <span class="n">M</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">n</span> <span class="p">:</span> <span class="n">f</span><span class="p">())</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
</pre>
     </div>
     <div class="atom">
<pre class="highlight"><span class="cp">#undef NDEBUG</span>
<span class="cp"></span><span class="k">export</span> <span class="n">module</span> <span class="n">M</span><span class="p">;</span>
<span class="k">public</span> <span class="n">import</span> <span class="o">&lt;</span><span class="n">vector</span><span class="o">></span><span class="p">;</span>
<span class="k">export</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span> <span class="n">f</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">};</span>
<span class="p">}</span>
</pre>
<pre class="highlight"><span class="cp">#define NDEBUG 1</span>
<span class="cp"></span><span class="n">import</span> <span class="o">&lt;</span><span class="n">vector</span><span class="o">></span><span class="p">;</span>
<span class="n">import</span> <span class="o">&lt;</span><span class="n">iostream</span><span class="o">></span><span class="p">;</span>
<span class="n">import</span> <span class="n">M</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">n</span> <span class="p">:</span> <span class="n">f</span><span class="p">())</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
</pre>
     </div>
    </div>
    <p>Let us suppose that <code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">vector</span></code> uses a different representation when <code class="highlight"><span class="n">NDEBUG</span></code> is defined. Under the Modules TS, the program will likely crash, due to differing definitions of the <code class="highlight"><span class="n">vector</span></code> type. Under the Atom proposal, the program is valid -- the legacy header <code class="highlight"><span class="o">&lt;</span><span class="n">vector</span><span class="o">></span></code> is processed in an environment that is independent from its point of import, and so both translation units share the same semantic model for <code class="highlight"><span class="o">&lt;</span><span class="n">vector</span><span class="o">></span></code> and thus the same representation for <code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span></code>.</p>
   </div>
   <p>This problem can be solved without making the sacrifices that <a data-link-type="biblio" href="#biblio-p0955r0">[P0955R0]</a> warns us about (switching between different module interfaces based on macros defined prior to the import, or bifurcating the BMI for a module at points affected by macros), and indeed those approaches do not solve the problem in the above example. The problem is caused by repeated textual inclusion of the same legacy header into environments where it is interpreted in different ways, and is solved by avoiding that textual inclusion.</p>
   <h3 class="heading settled" data-level="6.4" id="p0955-exporting"><span class="secno">6.4. </span><span class="content">Exporting macros</span><a class="self-link" href="#p0955-exporting"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-p0955r0">[P0955R0]</a> presents a question. Given:</p>
<pre class="highlight"><span class="n">import</span> <span class="n">M</span><span class="p">;</span>
<span class="c1">// …</span>
</pre>
   <p>If <code class="highlight"><span class="n">M</span></code> can export macros, then how are those macros to be discovered when later code mentions them? How would the compiler know to look into M? (Would this mean that import is no longer "free"?)</p>
   <p>It should be noted that an analogous question applies for non-macro names exported for modules. How is a compiler to know whether <em>any</em> identifier it sees after a module import should resolve to a name from within that imported module? The answer is the same in both cases: when a compiler sees an identifier, it must check (ideally with some caching) whether that identifier is declared in an imported module. This requirement is not unique to macro export.</p>
   <p>As noted in <a data-link-type="biblio" href="#biblio-p0955r0">[P0955R0]</a>, macro export and import requires preprocessor changes. However, much like the question of lookup, the question of import and export is analogous to imports and exports of modular declarations.</p>
   <p>Because modules are <code class="highlight"><span class="n">import</span></code>ed, and not <code class="highlight"><span class="cp">#include</span></code>d, it follows directly from the phases of translation that recursive preprocessing is not performed at import time -- the <code class="highlight"><span class="n">import</span></code> declaration is not a preprocessor directive. Instead, because the Atom proposal limits <code class="highlight"><span class="n">import</span></code>s to the preamble, the preprocessor can simply load the macro definitions exported by each of the imported modules, and there can be no interaction between the imports. The preprocessor can later emit any exported macros at the same time as the Binary Module Interface. (Note that macro definitions do not necessarily need to be stored in the BMI, and could equally be stored as a separate file alongside the BMI.)</p>
   <p>Also of note: as described above, the order-dependence problem mentioned in <a data-link-type="biblio" href="#biblio-p0955r0">[P0955R0]</a> is a problem under the Modules TS when using its support for legacy headers. It is not a problem under the Atom proposal, as we can detect and diagnose uses of imported macros within <em>import-declaration</em>s.</p>
   <h2 class="heading settled" data-level="7" id="splitting"><span class="secno">7. </span><span class="content">Splitting the Atom</span><a class="self-link" href="#splitting"></a></h2>
   <p>The Atom proposal provides a coherent modules design that is some distance from the Modules TS along various axes. It is natural to ask whether we can incrementally add some of these features to the Modules TS, or whether adopting them would reasonably need to be a "step change".</p>
   <p>There are various dependencies between these changes; some of these are:</p>
   <ul>
    <li data-md="">
     <p>The Atom proposal’s name visibility rule depends on module partitions (in order to provide a mechanism for controlling which semantic effects are imported), and also -- to some extent -- on legacy header units (in order to allow that control to extend to declarations from legacy headers)</p>
    <li data-md="">
     <p>Making <code class="highlight"><span class="n">import</span></code> and <code class="highlight"><span class="n">module</span></code> context-sensitive depends, at least partially, on the required source file order change.</p>
    <li data-md="">
     <p>The required source file order change depends on the ability to acquire the interface of legacy headers after the <em>module-declaration</em>; in the Atom proposal, this is made possible by legacy header import.</p>
    <li data-md="">
     <p>The ability to correctly build legacy header units from existing code depends on the ability of other legacy header units to export macros.</p>
   </ul>
   <p>However, several parts of this proposal are separable:</p>
   <ul>
    <li data-md="">
     <p>Support for module partitions does not depend on any other part of this proposal, and could be directly adopted by the Modules TS. This has already been proposed separately (<a data-link-type="biblio" href="#biblio-p0775r0">[P0775R0]</a>).</p>
    <li data-md="">
     <p>The ability for translation units (other than legacy header units) to export macros is a separable feature. Macro export for legacy header units is necessary in order to retain functionality parity with current C++ and the Modules TS, and to support <code class="highlight"><span class="cp">#include</span></code> translation.</p>
    <li data-md="">
     <p>It would be possible to change the Modules TS "reachability" rule to apply only to entities outside the purview of the module -- that is, we could use the Atom rule ("every semantic effect in the (purview of the) module is exported") for declarations below the <em>module-declaration</em> and the Modules TS rule ("only reachable semantic effects are exported") for declarations above the <em>module-declaration</em>.</p>
   </ul>
  </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-n4719">[N4719]
   <dd>Gabriel Dos Reis. <a href="https://wg21.link/n4719">Programming Languages — Extensions to C++ for Modules</a>. URL: <a href="https://wg21.link/n4719">https://wg21.link/n4719</a>
   <dt id="biblio-p0273r0">[P0273R0]
   <dd>Richard Smith, Chandler Carruth, David Jones. <a href="https://wg21.link/p0273r0">Proposed modules changes from implementation and deployment experience</a>. 12 February 2016. URL: <a href="https://wg21.link/p0273r0">https://wg21.link/p0273r0</a>
   <dt id="biblio-p0584r0">[P0584R0]
   <dd>Gabriel Dos Reis. <a href="https://wg21.link/p0584r0">Module Interface and Preamble</a>. URL: <a href="https://wg21.link/p0584r0">https://wg21.link/p0584r0</a>
   <dt id="biblio-p0629r0">[P0629R0]
   <dd>Gabriel Dos Reis, Jason Merrill, Nathan Sidwell. <a href="https://wg21.link/p0629r0">Module interface vs. imiplementation</a>. URL: <a href="https://wg21.link/p0629r0">https://wg21.link/p0629r0</a>
   <dt id="biblio-p0713r1">[P0713R1]
   <dd>Daveed Vandevoorde. <a href="https://wg21.link/p0713r1">Identifying Module Source</a>. URL: <a href="https://wg21.link/p0713r1">https://wg21.link/p0713r1</a>
   <dt id="biblio-p0775r0">[P0775R0]
   <dd>Nathan Sidwell. <a href="https://wg21.link/p0775r0">module partitions</a>. URL: <a href="https://wg21.link/p0775r0">https://wg21.link/p0775r0</a>
   <dt id="biblio-p0795r0">[P0795R0]
   <dd>Simon Brand, Neil Henning, Michael Wong, Christopher Di Bella, Kenneth Benzie. <a href="https://wg21.link/p0795r0">From Vulkan with love: a plea to reconsider the Module Keyword to be contextual</a>. URL: <a href="https://wg21.link/p0795r0">https://wg21.link/p0795r0</a>
   <dt id="biblio-p0924r0">[P0924R0]
   <dd>Nathan Sidwell. <a href="https://wg21.link/p0924r0">Modules: Context-Sensitive Keyword</a>. URL: <a href="https://wg21.link/p0924r0">https://wg21.link/p0924r0</a>
   <dt id="biblio-p0947r0">[P0947R0]
   <dd>Richard Smith. <a href="https://wg21.link/p0947r0">Another take on Modules</a>. URL: <a href="https://wg21.link/p0947r0">https://wg21.link/p0947r0</a>
   <dt id="biblio-p0955r0">[P0955R0]
   <dd>Bjarne Stroustrup. <a href="https://wg21.link/p0955r0">Modules and macros</a>. URL: <a href="https://wg21.link/p0955r0">https://wg21.link/p0955r0</a>
  </dl>
