<!DOCTYPE html>
<!-- Sources at https://github.com/cplusplus/fundamentals-ts -->
<html lang="en"><head>

<!--[if lte IE 8]><script>document.createElement("nav");document.createElement("section");document.createElement("time");document.createElement("CXX-TITLEPAGE");document.createElement("CXX-DOCNUM");document.createElement("CXX-REVISES");document.createElement("CXX-EDITOR");document.createElement("CXX-EMAIL");document.createElement("CXX-TOC");document.createElement("CXX-CLAUSE");document.createElement("CXX-SECTION");document.createElement("CXX-REF");document.createElement("CXX-FOREIGN-INDEX");document.createElement("CXX-EXAMPLE");document.createElement("CXX-NOTE");document.createElement("CXX-FUNCTION");document.createElement("CXX-SIGNATURE");document.createElement("CXX-REMARKS");document.createElement("CXX-EFFECTS");document.createElement("CXX-RETURNS");document.createElement("CXX-REQUIRES");document.createElement("CXX-TERM");document.createElement("W-BR");document.createElement("CXX-EDNOTE");document.createElement("CXX-POSTCONDITIONS");document.createElement("CXX-THROWS");document.createElement("CXX-COMPLEXITY");document.createElement("CXX-GRAMMARTERM");document.createElement("CXX-PUBLISH-BUTTON");</script><![endif]-->

<style>
  p {text-align:justify}
  li {text-align:justify}
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
</style>

<style>template {display: none !important;} /* injected by platform.js */</style>

<style>body {transition: opacity ease-in 0.2s; }

body[unresolved] {opacity: 0; display: block; overflow: hidden; position: relative; }
</style><style shim-shadowdom-css="">style { display: none !important; }
cxx-function {
	display: block; page-break-inside: avoid;
}

cxx-function:not(:last-child) {
	margin-bottom: 3ex;
}

cxx-function > dl {
	margin: 0px 0px 0px 2em;
}

cxx-function > pre {
	margin: 0px;
}cxx-signature {
	padding-left: 2em; display: block; text-indent: -2em;
}

cxx-signature.formatted {
	text-indent: 0px;
}cxx-attribute {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-attribute dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-attribute dd {
	margin-left: 0em;
}

cxx-attribute dd > ul, cxx-attribute dd > ol {
	clear: left;
}cxx-requires {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-requires dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-requires dd {
	margin-left: 0em;
}

cxx-requires dd > ul, cxx-requires dd > ol {
	clear: left;
}cxx-preconditions {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-preconditions dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-preconditions dd {
	margin-left: 0em;
}

cxx-preconditions dd > ul, cxx-preconditions dd > ol {
	clear: left;
}cxx-effects {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-effects dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-effects dd {
	margin-left: 0em;
}

cxx-effects dd > ul, cxx-effects dd > ol {
	clear: left;
}cxx-synchronization {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-synchronization dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-synchronization dd {
	margin-left: 0em;
}

cxx-synchronization dd > ul, cxx-synchronization dd > ol {
	clear: left;
}cxx-postconditions {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-postconditions dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-postconditions dd {
	margin-left: 0em;
}

cxx-postconditions dd > ul, cxx-postconditions dd > ol {
	clear: left;
}cxx-returns {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-returns dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-returns dd {
	margin-left: 0em;
}

cxx-returns dd > ul, cxx-returns dd > ol {
	clear: left;
}cxx-throws {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-throws dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-throws dd {
	margin-left: 0em;
}

cxx-throws dd > ul, cxx-throws dd > ol {
	clear: left;
}cxx-complexity {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-complexity dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-complexity dd {
	margin-left: 0em;
}

cxx-complexity dd > ul, cxx-complexity dd > ol {
	clear: left;
}cxx-exception-safety {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-exception-safety dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-exception-safety dd {
	margin-left: 0em;
}

cxx-exception-safety dd > ul, cxx-exception-safety dd > ol {
	clear: left;
}cxx-remarks {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-remarks dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-remarks dd {
	margin-left: 0em;
}

cxx-remarks dd > ul, cxx-remarks dd > ol {
	clear: left;
}cxx-error-conditions {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-error-conditions dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-error-conditions dd {
	margin-left: 0em;
}

cxx-error-conditions dd > ul, cxx-error-conditions dd > ol {
	clear: left;
}cxx-notes {
	display: block; margin-top: 0.5em; margin-bottom: 0.5em;
}

cxx-notes dt {
	float: left; font-style: italic; font-weight: normal; padding-right: 1ex;
}

cxx-notes dd {
	margin-left: 0em;
}

cxx-notes dd > ul, cxx-notes dd > ol {
	clear: left;
}cxx-section {
	display: block;
}

cxx-section:target {
	background-color: inherit;
}

cxx-section:target > section > h1 {
	background-color: rgb(255, 238, 221);
}

cxx-section header > h1 {
	display: inline; font-size: 100%;
}

cxx-section header {
	font-weight: bold; margin-top: 20px; margin-bottom: 20px; page-break-inside: avoid; page-break-after: avoid;
}

cxx-section header::after {
	clear: both; display: block; content: " "; height: 0px;
}cxx-clause {
	display: block;
}

cxx-clause:target {
	background-color: inherit;
}

cxx-clause:target > section > h1 {
	background-color: rgb(255, 238, 221);
}

cxx-clause header > h1 {
	display: inline; font-size: 100%;
}

cxx-clause header {
	font-weight: bold; margin-top: 20px; margin-bottom: 20px; page-break-inside: avoid; page-break-after: avoid;
}

cxx-clause header::after {
	clear: both; display: block; content: " "; height: 0px;
}[is=cxx-table] {
	margin-left: auto; margin-right: auto; border-collapse: collapse; border: thin solid black;
}

[is=cxx-table] caption {
	white-space: nowrap;
}

[is=cxx-table] caption caption {
	display: inline;
}

[is=cxx-table] th, [is=cxx-table] td {
	border-style: solid none; border-color: black; border-width: thin; padding: 0px 0.25em;
}

[is=cxx-table].column-rules th, [is=cxx-table].column-rules td {
	border-left-style: solid; border-right-style: solid;
}

[is=cxx-table] th {
	border-bottom: medium double;
}

[is=cxx-table].single-border th {
	border-bottom: thin solid;
}

[is=cxx-table].center td {
	text-align: center;
}

[is=cxx-table].list td {
	border: medium none; vertical-align: top;
}

[is=cxx-table].list ul {
	padding-left: 0px; margin: 0px;
}

[is=cxx-table].list ul li::before {
	content: "";
}cxx-figure {
	margin-left: auto; margin-right: auto;
}

cxx-figure figcaption {
	white-space: nowrap; text-align: center;
}

cxx-figure figcaption figcaption {
	display: inline;
}[is=cxx-definition-section] dt {
	font-weight: bold;
}

[is=cxx-definition-section] dd {
	margin-left: 0px;
}cxx-toc {
	display: block;
}

cxx-toc nav > ol {
	font-weight: bold;
}

cxx-toc ol {
	font-weight: normal; padding-left: 0px; margin-left: 0px;
}

cxx-toc li {
	list-style-type: none;
}

cxx-toc .marker {
	display: inline-block;
}

cxx-toc li .marker {
	width: 2em; text-align: left;
}

cxx-toc ol ol {
	margin-left: 2em;
}

cxx-toc li li .marker {
	width: 3em;
}

cxx-toc ol ol ol {
	margin-left: 3em;
}

cxx-toc li li li .marker {
	width: 3.5em;
}

cxx-toc ol ol ol ol {
	margin-left: 3.5em;
}

cxx-toc li li li li .marker {
	width: 4.5em;
}cxx-get-element-by-id {
	display: none;
}cxx-foreign-index {
	display: none;


cxx-foreword {
	page-break-before: always; page-break-after: always; min-height: 100vh; margin-bottom: 2em;
}

cxx-forewordbody.cxx-draft cxx-foreword -no-combinator, body.cxx-draft cxx-foreword cxx-foreword -no-combinator {
	display: none;
}cxx-ednote {
	display: none;
}

cxx-ednotebody.cxx-draft, body.cxx-draft cxx-ednote {
	display: block;
}

cxx-ednote aside {
	float: right; max-width: 40%; margin: 1ex; border: 1px dashed rgb(136, 136, 136); padding: 1ex; background-color: rgb(238, 238, 238);
}

cxx-ednote.para aside {
	float: none; max-width: none;
}cxx-note .nowrap {
	white-space: nowrap;
}cxx-footnote {
	font-family: serif; white-space: normal; text-indent: initial;textIndent: initial; text-indent: initial;
}

@media screen {
cxx-footnote aside {
	float: right; max-width: 30%; margin-left: 1em;
}


}

@media print {
cxx-footnote sup, cxx-footnote .marker {
	display: none;
}

cxx-footnote aside {
	
}


}cxx-example {
	display: block;
}

cxx-example.inline {
	display: inline;
}

cxx-example .nowrap {
	white-space: nowrap;
}cxx-publish-button {
	display: block;
}cxx-codeblock {
	display: block;
}bnf-grammar {
	display: block; font-style: italic; margin-left: 0.35in;
}bnf-rule {
	display: block; margin-left: 0.6in;
}bnf-alt {
	display: block; margin-left: 1.2in;
}bnf-terminal {
	font-style: normal;
}w-br {
	white-space: normal;
}

w-br::after {
	content: "​";
}</style>
  <meta charset="utf-8">

  <style shim-shadowdom-css="">/* Copyright 2014 Google Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

@page {
    margin: 10%;
}
@page :left {
    @top-left { content: string(docname); font-weight: bold; font-size: 10pt; }
    @top-right { content: normal; }
    @bottom-left { content: counter(page); font-size: 10pt; }
    @bottom-right { content: "© ISO/IEC " string(pubyear) " — All rights reserved";
                    font-size: 10pt; }
}
@page :right {
    @top-left { content: normal; }
    @top-right { content: string(docname); font-weight: bold; font-size: 10pt; }
    @bottom-left { content: "© ISO/IEC " string(pubyear) " — All rights reserved";
                   font-size: 10pt; }
    @bottom-right { content: counter(page); font-size: 10pt; }
}
@page :first {
    @top-left { content: normal; }
    @top-right { content: normal; }
    @bottom-left { content: normal; }
    @bottom-right { content: normal; }
}

body { margin: 0; }

@media screen {
    body { max-width: 7in;
           /* Make room for paragraph numbers. */
           margin-left: 2em }
}

@media print {
    html { font-size: 10pt; }
    *   code { font-size: 80%; }
    /* Note that only Prince generates clickable links. */
    *   a[href] { text-decoration:none; }
}

@media screen {
    /* Needed to make the <cxx-titlepage>'s vertical spacing work.
       For print see the <cxx-titlepage> definition. */
    html, body {height: 100%}
}

*   .docname { string-set: docname content(); }
*   .pubyear { string-set: pubyear content(); }

cxx-clause, cxx-foreword { page-break-before: always; }
@media screen {
    cxx-clause, cxx-toc, cxx-foreword { margin-top: 3em; }
}

cxx-clause  header, cxx-foreword  h1 { font-size: 150%; }
cxx-toc  h1 { font-size: 150%; }
cxx-clause cxx-section  header { font-size: 117%; }
cxx-clause cxx-section cxx-section  header { font-size: 100%; }

[data-bookmark-label] { bookmark-label: attr(data-bookmark-label); }
h1 { bookmark-level: 1; }
cxx-toc  h1 { bookmark-level: 2; }
cxx-clause h1, cxx-foreword h1 { bookmark-level: 2; }
cxx-clause cxx-section h1 { bookmark-level: 3; }
cxx-clause cxx-section cxx-section h1 { bookmark-level: 4; }
/* The <h2> is a subtitle, which shouldn't get a PDF bookmark. */

*  .section-number { string-set: current-section "§ " content(); }

p {margin-top: .5em; margin-bottom: .5em}
p:first-child, ul, ol {margin-top: 0}

[para_num]::before { content: attr(para_num); float: left;
                     font-size: 70%; margin-left: -2.5em; width: 1.5em; text-align: right; }

del {text-decoration: line-through; color: #8B0040;}
ins {text-decoration: underline; color: #005100;}

pre {
    margin-left: 1em;
    margin-top: .5em;
    margin-bottom: .5em;
}

*   wbr::after {
    white-space: normal;
    content: '\200B';
}
*   code {
    /* Make inline code avoid line wraps unless we override it with <wbr>. */
    white-space: nowrap;
}
*   pre code {
    /* Keep block-code wrapping according to its context. */
    white-space: inherit;
}

*   table {
    border-collapse: collapse;
}
*   td, th {
    padding-left: .2em;
    padding-right: .2em;
    border: thin solid black;
}

/* Use an em-dash for the list bullet.
   'print' is a proxy for supporting ::marker. */
@media screen {
    ul {
        list-style: none;
        /* Relative positioning on the 'ul' lets the absolutely-positioned
           marker align relative to it.*/
        position: relative;
    }
    ul li:before {
        content: "\2014";
        position: absolute; left: 10px;
    }
}
@media print {
    ul li::marker {
        content: "\2014";
    }
    [is=cxx-table].list ul li::marker {
        content: none;
    }
}

/* This is here rather than inside elements/toc.html because browsers
   don't understand leader() or target-counter(), so they drop them
   inside the CSSOM. */
@media print {
    /* Generate page numbers in the table of contents. */
    cxx-toc  a[href]::after { content: leader(" . ") target-counter(attr(href), page); }

    cxx-footnote  aside { float: footnote; footnote-policy: line; }
}</style><style shim-shadowdom-css="">/*******************************
          Flex Layout
*******************************/

html   [layout][horizontal], html   [layout][vertical] {
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
}

html   [layout][horizontal][inline], html   [layout][vertical][inline] {
  display: -ms-inline-flexbox;
  display: -webkit-inline-flex;
  display: inline-flex;
}

html   [layout][horizontal] {
  -ms-flex-direction: row;
  -webkit-flex-direction: row;
  flex-direction: row;
}

html   [layout][horizontal][reverse] {
  -ms-flex-direction: row-reverse;
  -webkit-flex-direction: row-reverse;
  flex-direction: row-reverse;
}

html   [layout][vertical] {
  -ms-flex-direction: column;
  -webkit-flex-direction: column;
  flex-direction: column;
}

html   [layout][vertical][reverse] {
  -ms-flex-direction: column-reverse;
  -webkit-flex-direction: column-reverse;
  flex-direction: column-reverse;
}

html   [layout][wrap] {
  -ms-flex-wrap: wrap;
  -webkit-flex-wrap: wrap;
  flex-wrap: wrap;
}

html   [layout][wrap-reverse] {
  -ms-flex-wrap: wrap-reverse;
  -webkit-flex-wrap: wrap-reverse;
  flex-wrap: wrap-reverse;
}

html   [flex] {
  -ms-flex: 1 1 0.000000001px;
  -webkit-flex: 1;
  flex: 1;
  -webkit-flex-basis: 0.000000001px;
  flex-basis: 0.000000001px;
}

html   [vertical][layout] > [flex][auto-vertical], html   [vertical][layout]  [flex][auto-vertical] {
  -ms-flex: 1 1 auto;
  -webkit-flex-basis: auto;
  flex-basis: auto;
}

html   [flex][auto] {
  -ms-flex: 1 1 auto;
  -webkit-flex-basis: auto;
  flex-basis: auto;
}

html   [flex][none] {
  -ms-flex: none;
  -webkit-flex: none;
  flex: none;
}

html   [flex][one] {
  -ms-flex: 1;
  -webkit-flex: 1;
  flex: 1;
}

html   [flex][two] {
  -ms-flex: 2;
  -webkit-flex: 2;
  flex: 2;
}

html   [flex][three] {
  -ms-flex: 3;
  -webkit-flex: 3;
  flex: 3;
}

html   [flex][four] {
  -ms-flex: 4;
  -webkit-flex: 4;
  flex: 4;
}

html   [flex][five] {
  -ms-flex: 5;
  -webkit-flex: 5;
  flex: 5;
}

html   [flex][six] {
  -ms-flex: 6;
  -webkit-flex: 6;
  flex: 6;
}

html   [flex][seven] {
  -ms-flex: 7;
  -webkit-flex: 7;
  flex: 7;
}

html   [flex][eight] {
  -ms-flex: 8;
  -webkit-flex: 8;
  flex: 8;
}

html   [flex][nine] {
  -ms-flex: 9;
  -webkit-flex: 9;
  flex: 9;
}

html   [flex][ten] {
  -ms-flex: 10;
  -webkit-flex: 10;
  flex: 10;
}

html   [flex][eleven] {
  -ms-flex: 11;
  -webkit-flex: 11;
  flex: 11;
}

html   [flex][twelve] {
  -ms-flex: 12;
  -webkit-flex: 12;
  flex: 12;
}

/* alignment in cross axis */

html   [layout][start] {
  -ms-flex-align: start;
  -webkit-align-items: flex-start;
  align-items: flex-start;
}

html   [layout][center], html   [layout][center-center] {
  -ms-flex-align: center;
  -webkit-align-items: center;
  align-items: center;
}

html   [layout][end] {
  -ms-flex-align: end;
  -webkit-align-items: flex-end;
  align-items: flex-end;
}

/* alignment in main axis */

html   [layout][start-justified] {
  -ms-flex-pack: start;
  -webkit-justify-content: flex-start;
  justify-content: flex-start;
}

html   [layout][center-justified], html   [layout][center-center] {
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
}

html   [layout][end-justified] {
  -ms-flex-pack: end;
  -webkit-justify-content: flex-end;
  justify-content: flex-end;
}

html   [layout][around-justified] {
  -ms-flex-pack: distribute;
  -webkit-justify-content: space-around;
  justify-content: space-around;
}

html   [layout][justified] {
  -ms-flex-pack: justify;
  -webkit-justify-content: space-between;
  justify-content: space-between;
}

/* self alignment */

html   [self-start] {
  -ms-align-self: flex-start;
  -webkit-align-self: flex-start;
  align-self: flex-start;
}

html   [self-center] {
  -ms-align-self: center;
  -webkit-align-self: center;
  align-self: center;
}

html   [self-end] {
  -ms-align-self: flex-end;
  -webkit-align-self: flex-end;
  align-self: flex-end;
}

html   [self-stretch] {
  -ms-align-self: stretch;
  -webkit-align-self: stretch;
  align-self: stretch;
}

/*******************************
          Other Layout
*******************************/

html   [block] {
  display: block;
}

/* ie support for hidden */
html   [hidden] {
  display: none !important;
}

html   [relative] {
  position: relative;
}

html   [fit] {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

body[fullbleed] {
  margin: 0;
  height: 100vh;
}

/*******************************
            Other
*******************************/

html   [segment], html   segment {
  display: block;
  position: relative;
  -webkit-box-sizing: border-box;
  -ms-box-sizing: border-box;
  box-sizing: border-box;
  margin: 1em 0.5em;
  padding: 1em;
  background-color: white;
  -webkit-box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
  box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
  border-radius: 5px 5px 5px 5px;
}</style>


<title>Completing the Rebase of Library Fundamentals, Version 3, Working Draft</title>
</head>


<body>
<h1>Completing the Rebase of Library Fundamentals, Version 3, Working Draft</h1>

<table>
<tr>
  <td align="left">Doc. no.</td>
  <td align="left">P1210R0</td>
</tr>
<tr>
  <td align="left">Date:</td>
  <td align="left">2018-09-30</td>
</tr>
<tr>
  <td align="left">Project:</td>
  <td align="left">Programming Language C++</td>
</tr>
<tr>
  <td align="left">Reply to:</td>
  <td align="left">Alisdair Meredith &lt;<a href="mailto:ameredith1@bloomberg.net">ameredith1@bloomberg.net</a>&gt;</td>
</tr>
<tr>
  <td align="left">Audience:</td>
  <td align="left">LEWG, Library</td>
</tr>
</table>

<h2>Table of Contents</h2>
<ol start="0">
<li><a href="#0.0">Revision History</a></li>
  <ul>
  <li><a href="#0.1">Revision 0</a></li>
  </ul>
<li><a href="#1.0">Introduction</a></li>
<li><a href="#2.0">Problems to be addressed</a></li>
<li><a href="#3.0">Proposed Resolution</a></li>
<li><a href="#4.0">Alternatives Considered</a></li>
<li><a href="#5.0">Formal Wording</a></li>
<li><a href="#6.0">Acknowledgements</a></li>
<li><a href="#7.0">References</a></li>
</ol>


<h2><a name="1.0">1. Introduction</a></h2>
<p>
There were a few small issues applying
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0996r1">P0996R1</a>
to the Library Fundamentals TS working draft, to rebase it onto C++17.  This
paper resolves any outstanding issues cleaning up from the rebase.
</p>


<h2><a name="2.0">2. Introduction</a></h2>
<p>
When
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0996r1">P0996R1</a>
was adopted to update the Library Fundamentals TS for C++17, there was a clear
intent to remove all the variable templates for type traits that has already
landed in C++17.  Indeed, the feature macro for the variable template traits is
removed from the set of feature macros associated with this TS.  However, the
actual wording change to remove the variable templates was missing.
</p>

<p>
In addition, it was not noticed that several new variable templates are added
to support new type traits proposed by the TS.  C++17 added the notion of
inline variables, and variable template for type traits are consistently
specified using the <tt>inline</tt> keyword in C++17.
</p>


<h2><a name="3.0">3. Proposed Resolution</a></h2>
<p>
There are two parts to the proposed resolution.  First, remove all the variable
templates for traits that have landed in the main standard, ISO 14882:2017.
Secondly, apply the <tt>inline</tt> keyword to variable templates defined in
the fundamentals TS, consistent with the usage for variable template traits in
ISO 14882:2017.
</p>


<h2><a name="4.0">4. Alternatives Considered</a></h2>
<p>
We could just leave the variable templates as part of the experimental
namespace, as they would remain just as valid.  However, apart from adding
noise for a feature that has already landed in the main standard, the set of
variable templates is incomplete, as new features continue to land in the main
standard and would not be backported into the <tt>experimental</tt> namespace.
The original intent was to remove features from the TS once they were no longer
experimental, and we see no reason to be selectively different in this case.
</p>


<h2><a name="5.0">5. Formal Wording</a></h2>
<p>
Apply the following changes to the (proposed) Library Fundamentals V3 TS
working draft.  These changes are relative to
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4758">N4758</a>
.
</p>

<cxx-clause id="utilities">
  <section>
    <header><span class="section-number">3</span> <h1 data-bookmark-label="3 General utilities library">General utilities library</h1> <span style="float:right"><a href="#utilities">[utilities]</a></span></header>

  <cxx-section id="meta">
    <section>
      <header><span class="section-number">3.3</span> <h1 data-bookmark-label="3.3 Metaprogramming and type traits">Metaprogramming and type traits</h1> <span style="float:right"><a href="#meta">[meta]</a></span></header>

    <cxx-section id="meta.type.synop">
      <section>
        <header><span class="section-number">3.3.1</span> <h1 data-bookmark-label="3.3.1 Header <experimental/type_traits> synopsis">Header &lt;experimental/type_traits&gt; synopsis</h1> <span style="float:right"><a href="#meta.type.synop">[meta.type.synop]</a></span></header>

<pre><code>#include &lt;type_traits&gt;

namespace std::experimental {
inline namespace fundamentals_v3 {
<del>
  // See <cxx-ref in="cxx" to="meta.unary.cat">C++17 <span title="meta.unary.cat">§23.15.4.1</span></cxx-ref>, primary type categories
  template &lt;class T&gt; constexpr bool is_void_v
    = is_void&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_null_pointer_v
    = is_null_pointer&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_integral_v
    = is_integral&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_floating_point_v
    = is_floating_point&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_array_v
    = is_array&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_pointer_v
    = is_pointer&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_lvalue_reference_v
    = is_lvalue_reference&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_rvalue_reference_v
    = is_rvalue_reference&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_member_object_pointer_v
    = is_member_object_pointer&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_member_function_pointer_v
    = is_member_function_pointer&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_enum_v
    = is_enum&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_union_v
    = is_union&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_class_v
    = is_class&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_function_v
    = is_function&lt;T&gt;::value;

  // See <cxx-ref in="cxx" to="meta.unary.comp">C++17 <span title="meta.unary.comp">§23.15.4.2</span></cxx-ref>, composite type categories
  template &lt;class T&gt; constexpr bool is_reference_v
    = is_reference&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_arithmetic_v
    = is_arithmetic&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_fundamental_v
    = is_fundamental&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_object_v
    = is_object&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_scalar_v
    = is_scalar&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_compound_v
    = is_compound&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_member_pointer_v
    = is_member_pointer&lt;T&gt;::value;

  // See <cxx-ref in="cxx" to="meta.unary.prop">C++17 <span title="meta.unary.prop">§23.15.4.3</span></cxx-ref>, type properties
  template &lt;class T&gt; constexpr bool is_const_v
    = is_const&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_volatile_v
    = is_volatile&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_trivial_v
    = is_trivial&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_trivially_copyable_v
    = is_trivially_copyable&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_standard_layout_v
    = is_standard_layout&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_pod_v
    = is_pod&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_literal_type_v
    = is_literal_type&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_empty_v
    = is_empty&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_polymorphic_v
    = is_polymorphic&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_abstract_v
    = is_abstract&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_final_v
    = is_final&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_signed_v
    = is_signed&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_unsigned_v
    = is_unsigned&lt;T&gt;::value;
  template &lt;class T, class... Args&gt; constexpr bool is_constructible_v
    = is_constructible&lt;T, Args...&gt;::value;
  template &lt;class T&gt; constexpr bool is_default_constructible_v
    = is_default_constructible&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_copy_constructible_v
    = is_copy_constructible&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_move_constructible_v
    = is_move_constructible&lt;T&gt;::value;
  template &lt;class T, class U&gt; constexpr bool is_assignable_v
    = is_assignable&lt;T, U&gt;::value;
  template &lt;class T&gt; constexpr bool is_copy_assignable_v
    = is_copy_assignable&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_move_assignable_v
    = is_move_assignable&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_destructible_v
    = is_destructible&lt;T&gt;::value;
  template &lt;class T, class... Args&gt; constexpr bool is_trivially_constructible_v
    = is_trivially_constructible&lt;T, Args...&gt;::value;
  template &lt;class T&gt; constexpr bool is_trivially_default_constructible_v
    = is_trivially_default_constructible&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_trivially_copy_constructible_v
    = is_trivially_copy_constructible&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_trivially_move_constructible_v
    = is_trivially_move_constructible&lt;T&gt;::value;
  template &lt;class T, class U&gt; constexpr bool is_trivially_assignable_v
    = is_trivially_assignable&lt;T, U&gt;::value;
  template &lt;class T&gt; constexpr bool is_trivially_copy_assignable_v
    = is_trivially_copy_assignable&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_trivially_move_assignable_v
    = is_trivially_move_assignable&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_trivially_destructible_v
    = is_trivially_destructible&lt;T&gt;::value;
  template &lt;class T, class... Args&gt; constexpr bool is_nothrow_constructible_v
    = is_nothrow_constructible&lt;T, Args...&gt;::value;
  template &lt;class T&gt; constexpr bool is_nothrow_default_constructible_v
    = is_nothrow_default_constructible&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_nothrow_copy_constructible_v
    = is_nothrow_copy_constructible&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_nothrow_move_constructible_v
    = is_nothrow_move_constructible&lt;T&gt;::value;
  template &lt;class T, class U&gt; constexpr bool is_nothrow_assignable_v
    = is_nothrow_assignable&lt;T, U&gt;::value;
  template &lt;class T&gt; constexpr bool is_nothrow_copy_assignable_v
    = is_nothrow_copy_assignable&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_nothrow_move_assignable_v
    = is_nothrow_move_assignable&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool is_nothrow_destructible_v
    = is_nothrow_destructible&lt;T&gt;::value;
  template &lt;class T&gt; constexpr bool has_virtual_destructor_v
    = has_virtual_destructor&lt;T&gt;::value;

  // See <cxx-ref in="cxx" to="meta.unary.prop.query">C++17 <span title="meta.unary.prop.query">§23.15.5</span></cxx-ref>, type property queries
  template &lt;class T&gt; constexpr size_t alignment_of_v
    = alignment_of&lt;T&gt;::value;
  template &lt;class T&gt; constexpr size_t rank_v
    = rank&lt;T&gt;::value;
  template &lt;class T, unsigned I = 0&gt; constexpr size_t extent_v
    = extent&lt;T, I&gt;::value;

  // See <cxx-ref in="cxx" to="meta.rel">C++17 <span title="meta.rel">§23.15.6</span></cxx-ref>, type relations
  template &lt;class T, class U&gt; constexpr bool is_same_v
    = is_same&lt;T, U&gt;::value;
  template &lt;class Base, class Derived&gt; constexpr bool is_base_of_v
    = is_base_of&lt;Base, Derived&gt;::value;
  template &lt;class From, class To&gt; constexpr bool is_convertible_v
    = is_convertible&lt;From, To&gt;::value;
</del>
  <cxx-ref insynopsis="" to="meta.trans.other">// <i><a title="meta.trans.other" href="#meta.trans.other">3.3.2</a>, Other type transformations</i></cxx-ref>
  template &lt;class&gt; class invocation_type; // <i>not defined</i>
  template &lt;class F, class... ArgTypes&gt; class invocation_type&lt;F(ArgTypes...)&gt;;
  template &lt;class&gt; class raw_invocation_type; // <i>not defined</i>
  template &lt;class F, class... ArgTypes&gt; class raw_invocation_type&lt;F(ArgTypes...)&gt;;

  template &lt;class T&gt;
    using invocation_type_t = typename invocation_type&lt;T&gt;::type;
  template &lt;class T&gt;
    using raw_invocation_type_t = typename raw_invocation_type&lt;T&gt;::type;

  <cxx-ref insynopsis="" to="meta.detect">// <i><a title="meta.detect" href="#meta.detect">3.3.3</a>, Detection idiom</i></cxx-ref>
  <del>template &lt;class...&gt; using void_t = void;</del>

  struct nonesuch {
    nonesuch() = delete;
    ~nonesuch() = delete;
    nonesuch(nonesuch const&amp;) = delete;

    void operator=(nonesuch const&amp;) = delete;
  };

  template &lt;template&lt;class...&gt; class Op, class... Args&gt;
    using is_detected = <i>see below</i>;
  template &lt;template&lt;class...&gt; class Op, class... Args&gt;
    <ins>inline</ins> constexpr bool is_detected_v = is_detected&lt;Op, Args...&gt;::value;
  template &lt;template&lt;class...&gt; class Op, class... Args&gt;
    using detected_t = <i>see below</i>;
  template &lt;class Default, template&lt;class...&gt; class Op, class... Args&gt;
    using detected_or = <i>see below</i>;
  template &lt;class Default, template&lt;class...&gt; class Op, class... Args&gt;
    using detected_or_t = typename detected_or&lt;Default, Op, Args...&gt;::type;
  template &lt;class Expected, template&lt;class...&gt; class Op, class... Args&gt;
    using is_detected_exact = is_same&lt;Expected, detected_t&lt;Op, Args...&gt;&gt;;
  template &lt;class Expected, template&lt;class...&gt; class Op, class... Args&gt;
    <ins>inline</ins> constexpr bool is_detected_exact_v
      = is_detected_exact&lt;Expected, Op, Args...&gt;::value;
  template &lt;class To, template&lt;class...&gt; class Op, class... Args&gt;
    using is_detected_convertible = is_convertible&lt;detected_t&lt;Op, Args...&gt;, To&gt;;
  template &lt;class To, template&lt;class...&gt; class Op, class... Args&gt;
    <ins>inline</ins> constexpr bool is_detected_convertible_v
      = is_detected_convertible&lt;To, Op, Args...&gt;::value;

} // inline namespace fundamentals_v3
} // namespace std::experimental</code></pre>
      </section>
    </cxx-section>

    </section>
  </cxx-section>

  </section>
</cxx-clause>


<cxx-clause id="func">
    <section>
      <header><span class="section-number">4</span> <h1 data-bookmark-label="4 Function objects">Function objects</h1> <span style="float:right"><a href="#func">[func]</a></span></header>

  <cxx-section id="header.functional.synop">
    <section>
      <header><span class="section-number">4.1</span> <h1 data-bookmark-label="4.1 Header <experimental/functional> synopsis">Header <code>&lt;experimental/functional&gt;</code> synopsis</h1> <span style="float:right"><a href="#header.functional.synop">[header.functional.synop]</a></span></header>

<pre><code>#include &lt;functional&gt;

namespace std {
  namespace experimental {
  inline namespace fundamentals_v3 {
<del>
    // See <cxx-ref in="cxx" to="bind">C++17 <span title="bind">§</span></cxx-ref>, Function object binders
    template &lt;class T&gt; constexpr bool is_bind_expression_v
      = is_bind_expression&lt;T&gt;::value;
    template &lt;class T&gt; constexpr int is_placeholder_v
      = is_placeholder&lt;T&gt;::value;
</del>
    <cxx-ref insynopsis="" to="func.wrap.func">// <i><a title="func.wrap.func" href="#func.wrap.func">4.2</a>, Class template function</i></cxx-ref>
    template&lt;class&gt; class function; <i>// undefined</i>
    template&lt;class R, class... ArgTypes&gt; class function&lt;R(ArgTypes...)&gt;;

    template&lt;class R, class... ArgTypes&gt;
    void swap(function&lt;R(ArgTypes...)&gt;&amp;, function&lt;R(ArgTypes...)&gt;&amp;);

    template&lt;class R, class... ArgTypes&gt;
    bool operator==(const function&lt;R(ArgTypes...)&gt;&amp;, nullptr_t) noexcept;
    template&lt;class R, class... ArgTypes&gt;
    bool operator==(nullptr_t, const function&lt;R(ArgTypes...)&gt;&amp;) noexcept;
    template&lt;class R, class... ArgTypes&gt;
    bool operator!=(const function&lt;R(ArgTypes...)&gt;&amp;, nullptr_t) noexcept;
    template&lt;class R, class... ArgTypes&gt;
    bool operator!=(nullptr_t, const function&lt;R(ArgTypes...)&gt;&amp;) noexcept;

  } // namespace fundamentals_v3
  } // namespace experimental

  template&lt;class R, class... ArgTypes, class Alloc&gt;
  struct uses_allocator&lt;experimental::function&lt;R(ArgTypes...)&gt;, Alloc&gt;;

} // namespace std</code></pre>

    </section>
  </cxx-section>


    </section>
  </cxx-clause>


<cxx-clause id="memory">
  <section>
    <header><span class="section-number">5</span> <h1 data-bookmark-label="5 Memory">Memory</h1> <span style="float:right"><a href="#memory">[memory]</a></span></header>

  <cxx-section id="header.memory.synop">
    <section>
      <header><span class="section-number">5.1</span> <h1 data-bookmark-label="5.1 Header <experimental/memory> synopsis">Header &lt;experimental/memory&gt; synopsis</h1> <span style="float:right"><a href="#header.memory.synop">[header.memory.synop]</a></span></header>

<pre><code>#include &lt;memory&gt;

namespace std {
  namespace experimental {
  inline namespace fundamentals_v3 {
<del>
    // See <cxx-ref in="cxx" to="allocator.uses">C++17 <span title="allocator.uses">§23.10.7</span></cxx-ref>, uses_allocator
    template &lt;class T, class Alloc&gt; constexpr bool uses_allocator_v
      = uses_allocator&lt;T, Alloc&gt;::value;
</del>
    <cxx-ref insynopsis="" to="memory.observer.ptr">// <i><a title="memory.observer.ptr" href="#memory.observer.ptr">5.2</a>, Non-owning pointers</i></cxx-ref>
    template &lt;class W&gt; class observer_ptr;

    <cxx-ref insynopsis="" to="memory.observer.ptr.special">// <i><a title="memory.observer.ptr.special" href="#memory.observer.ptr.special">5.2.6</a>, observer_ptr specialized algorithms</i></cxx-ref>
    template &lt;class W&gt;
    void swap(observer_ptr&lt;W&gt;&amp;, observer_ptr&lt;W&gt;&amp;) noexcept;
    template &lt;class W&gt;
    observer_ptr&lt;W&gt; make_observer(W*) noexcept;
    // (in)equality operators
    template &lt;class W1, class W2&gt;
    bool operator==(observer_ptr&lt;W1&gt;, observer_ptr&lt;W2&gt;);

    template &lt;class W1, class W2&gt;
    bool operator!=(observer_ptr&lt;W1&gt;, observer_ptr&lt;W2&gt;);
    template &lt;class W&gt;
    bool operator==(observer_ptr&lt;W&gt;, nullptr_t) noexcept;
    template &lt;class W&gt;
    bool operator!=(observer_ptr&lt;W&gt;, nullptr_t) noexcept;
    template &lt;class W&gt;
    bool operator==(nullptr_t, observer_ptr&lt;W&gt;) noexcept;
    template &lt;class W&gt;
    bool operator!=(nullptr_t, observer_ptr&lt;W&gt;) noexcept;
    // ordering operators
    template &lt;class W1, class W2&gt;
    bool operator&lt;(observer_ptr&lt;W1&gt;, observer_ptr&lt;W2&gt;);
    template &lt;class W1, class W2&gt;
    bool operator&gt;(observer_ptr&lt;W1&gt;, observer_ptr&lt;W2&gt;);
    template &lt;class W1, class W2&gt;
    bool operator&lt;=(observer_ptr&lt;W1&gt;, observer_ptr&lt;W2&gt;);
    template &lt;class W1, class W2&gt;
    bool operator&gt;=(observer_ptr&lt;W1&gt;, observer_ptr&lt;W2&gt;);

  } // inline namespace fundamentals_v3
  } // namespace experimental

  <del><cxx-ref insynopsis="" to="memory.smartptr.shared.hash">// <i><a title="memory.smartptr.shared.hash" href="#memory.smartptr.shared.hash"></a>, </i></cxx-ref></del>
  <del>template&lt;class T&gt; struct hash&lt;experimental::shared_ptr&lt;T&gt;&gt;;</del>

  <cxx-ref insynopsis="" to="memory.observer.ptr.hash">// <i><a title="memory.observer.ptr.hash" href="#memory.observer.ptr.hash">5.2.7</a>, observer_ptr hash support</i></cxx-ref>
  template &lt;class T&gt; struct hash;
  template &lt;class T&gt; struct hash&lt;experimental::observer_ptr&lt;T&gt;&gt;;

} // namespace std</code></pre>

    </section>
  </cxx-section>

    </section>
  </cxx-section>

    </section>
  </cxx-clause>


<h2><a name="6.0">6. Acknowledgements</a></h2>
<p>
Thanks to Thomas Köppe for taking up the mantle as project editor
for the Library Fundamentals TS, and for highlighting this issue
for my attention.
</p>


<h2><a name="7.0">7. References</a></h2>
<ul>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0996r1">P0996R1</a> Rebase Library Fundamentals TS on C++17</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4758">N4758</a> Library Fundamentals V3 TS (proposed working draft)</li>
</ul>


</body>
</html>
