<!DOCTYPE html>
<!-- saved from url=(0062)https://bb.githack.com/karies/cxxstd-p0194/raw/HEAD/d0194.html -->
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  
  <meta name="author" content="P0194R6, ISO/IEC JTC1 SC22 WG21">

<link rel="stylesheet" href="./P0194R6_files/hack.min.css">
<style type="text/css">
pre {
  font-family: "Hack", "OCR A Extended", "Consolas", "Lucida Console", monospace;
  margin-left:20pt;
  line-height: 1.1em;
  font-size: small;
}
code {
  font-family: "Hack", "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-size: small;
}
pre > i {
  font-family: "Hack", "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
code > i {
  font-family: "Hack", "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
pre > em {
  font-family: "Hack", "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
code > em {
  font-family: "Hack", "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
body {
    color: #000000; background-color: #FFFFFF; 
    font-family: "Book Antiqua", "Times New Roman", "Times", serif;
    padding: 2em;
}
/*del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }*/
del { text-decoration: line-through; color: #8B0040; background-color: rgb(248, 215, 231); }
ins { text-decoration: none;
    border-bottom: 1px solid #005100;
    color: #005100;
    background-color: #dbf8db;
    line-height: 1.4em;
}

ins.edit { text-decoration: none;
    border-bottom: 1px solid #0000c1;
    color: #0000c1;
    line-height: 1.4em;
    background-color: #eeeeff;
}
del.edit {
  text-decoration: line-through;
    border-bottom: 1px solid #0000c1;
    color: #0000c1;
    line-height: 1.4em;
    background-color: #eeeeff;
}
span.section_name {
    float: right;
    font-weight: bold;
}

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

div.std {
  margin-left: 1em;
  border-left: 1px gray solid;
  padding-left: 1em;}
div.ins { text-decoration: none;
    border-left: 1px solid #005100;
    color: #005100;
    background-color: #dbf8db;
    line-height: 1.4em;
}

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; margin-bottom: 0.5em;}

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5em;
  padding-right: 0.5em; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #dbf8db;
  border: 1px solid #B3EBB3; padding: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto;
  margin-top: 2em; margin-bottom: 2em;}

table.withBorder {
  border-top: none;
  border-left: none;
  border-right: 1px solid black;
  border-bottom: 1px solid black;
}
.withBorder th {
  border-top: 1px solid black;
  border-bottom: 1px solid black;
  border-left: 1px solid black;
/*  border-top: 2px solid black;
  border-left: 2px solid black;
  border-bottom: 1px solid black;
  border-right: 1px solid black;*/
}
.withBorder td {
  border-top: 1px solid black;
  border-left: 1px solid black;
}

table.header {
  margin-left: 0em;
  border: none;
    margin-bottom: 2em;
}
th { text-align: left; vertical-align: top;
  padding-left: 0.4em; 
  padding-right: 0.4em; }
td { text-align: left; vertical-align: top;
  padding-left: 0.4em; 
  padding-right: 0.4em;  }

ul.nobullet {
    list-style-type: none;
    /*margin: 0;
    padding: 0;*/
}
</style>

<title>Static reflection</title>
</head>

<body>
<table class="header">
    <tbody><tr><td>Document Number:</td> <td><b>P0194R6</b>, ISO/IEC JTC1 SC22 WG21</td></tr>
  <tr><td>Audience:</td><td>CWG, LWG</td></tr>
    <tr><td>Date:</td><td>2018-03-16</td></tr>
  <tr><td rowspan="3">Authors:</td><td>Matus Chochlik (chochlik@gmail.com)</td></tr>
  <tr><td>Axel Naumann (axel@cern.ch)</td></tr>
  <tr><td>David Sankel (dsankel@bloomberg.net)</td></tr>
</tbody></table>
<h1>Static reflection</h1>

<!--    <h2>Table of Contents</h2>
<nav id="TOC">
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#other-proposals">Interplay with other proposals</a></li>
<li><a href="#proposed-wording">Proposed wording</a></li>
<li><a href="#acknowledgments">Acknowledgments</a></li>
<li><a href="#history">Revision history</a></li>
<li><a href="#references">References</a></li>
</ul>
</nav>
-->

  <!--
    <h2>&nbsp;</h2>
<blockquote>
<p></p>
</blockquote>
-->

<h3 id="introduction">0. Introduction</h3>
<p>This paper proposes to add support for compile-time reflection as a Technical Specification for C++. We propose that the compiler shall generate meta-object types — representations of certain program declarations, which can be reasoned about at compile time. These meta-object types can then be used, through a set of operations to obtain various pieces of metadata, like declaration names, lists of scope members, information about specifiers, and so on. The meta-object types are implemented as unique, unnamed types conforming to defined concepts, and the operations are implemented as class templates.</p>

<p>This paper is accompanied by two more papers — <a href="http://wg21.link/p0385">P0385</a>, which discusses the use cases, rationale, design decisions, future evolution of the proposed reflection facility and contains multiple examples of use and replies to frequently asked questions; and <a href="http://wg21.link/p0578">P0578</a> which gives a concise introduction to the feature set presented here.</p>
  
<p>Reflection proposed here behaves as follows:</p>
<pre><code>
enum E { first, second };
using E_m = reflexpr(E);
using namespace std::experimental::reflect;
using first_m = get_element_t&lt;0, get_enumerators_t&lt;E_m&gt;&gt;;
std::cout &lt;&lt; get_name_v&lt;first_m&gt; &lt;&lt; std::endl; // prints "first"
</code></pre>

<p>The publication as a Technical Specification is intended to collect implementation and usage experience on several aspects of this proposal.
   One of these aspects is the unspecified nature of the meta-object type's uniqueness for subsequent invocations of the <code>reflexpr</code> operator on the same operand.
</p>

  
<h4 id="other-proposals">0.1 Interplay with other proposals</h4>
<p>This proposal relies on the Concepts TS rebased onto C++17. It also assumes that WG21 will incorporate proper compile-time strings; until then, this proposal provides a placeholder implementation (see [reflect.ops.named]).</p>


<h3>1 Scope <span class="section_name">[intro.scope]</span></h3>
  <p>This Technical Specification describes extensions to the C++ Programming Language (Clause 2) that enable operations on source code.
   These extensions include new syntactic forms and modifications to existing language semantics, as well as changes and additions to the existing library facilities.</p>
   <p>The International Standard, ISO/IEC 14882, provides important context and specification for this Technical
   Specification. This document is written as a set of changes against that specification, as modified by ISO/IEC TS 19217:2015.
   Instructions to modify or add paragraphs are written as explicit instructions.
   Modifications made directly to existing text from the International Standard use <ins>underlining</ins> to represent added text and <del>strikethrough</del> to represent deleted text.</p>
  

<h3>2 Normative references <span class="section_name">[intro.refs]</span></h3>
<p>The following referenced document is indispensable for the application of this document. For dated references,
   only the edition cited applies.
   For undated references, the latest edition of the referenced document (including
   any amendments) applies.</p>
<p>
</p><ul>
<li>ISO/IEC 14882:2017, <em>Programming Languages - C++</em></li>
<li>ISO/IEC TS 19217:2015, <em>Programming Languages - C++ Extensions for Concepts</em></li>
</ul>
<p></p>
<p>ISO/IEC 14882:2017 is hereafter called the <em>C++ Standard</em>.</p>
<p>ISO/IEC TS 19217:2015 is hereafter called the <em>Concepts TS</em>. </p>
<p>The numbering of clauses, subclauses, and
      paragraphs in this document reflects the numbering in the C++ Standard and the Concepts TS.
      References to clauses and
      subclauses not appearing in this Technical Specification refer to the original, unmodified text in the Concepts TS,
      or in the C++ Standard for clauses and subclauses not appearing in the Concepts TS.
</p>


<h3>3 Terms and definitions <span class="section_name">[intro.defs]</span></h3>
<p>No terms and definitions are listed in this document. ISO and IEC maintain terminological databases for
      use in standardization at the following addresses:</p>
<ul>
      <li>IEC Electropedia: available at http://www.electropedia.org/</li>
      <li>ISO Online browsing platform: available at http://www.iso.org/obp</li>
</ul>


<h3>4 General <span class="section_name">[intro]</span></h3>
<h4>4.1 Implementation compliance <span class="section_name">[intro.compliance]</span></h4>
<p>
Conformance requirements for this specification are those defined in subclause 4.1 in the Concepts TS,
except that references to the Concepts TS or the C++ Standard therein shall be taken as referring to the document that is the
result of applying the editing instructions. Similarly, all references to the Concepts TS or the C++ Standard in the resulting
document shall be taken as referring to the resulting document itself.
[<em>Note:</em> Conformance is defined in terms of the behavior of programs. <em>— end note</em>]
</p>

<h4>4.2 Namespaces and headers <span class="section_name">[intro.namespaces]</span></h4>
<p>Whenever a name <code>x</code> declared in subclause 21.11 at namespace scope is mentioned, the name <code>x</code> is assumed to be
fully qualified as <code>::std::experimental::reflect::v1::x</code>, unless otherwise specified.
The header described in this specification (see Table 1) shall import the contents of <code>::std::experimental::reflect::v1</code> into <code>::std::experimental::reflect</code> as if by:</p>
<pre><code>
namespace std::experimental::reflect {
  inline namespace v1 {}
}
</code></pre>
<p>Whenever a name <code>x</code> declared in the standard library at namespace scope is mentioned, the name <code>x</code> is assumed to be fully qualified as <code>::std::x</code>, unless otherwise specified.</p>
<!-- <p>New headers are provided in the <code>&lt;experimental/meta/&gt;</code> directory.</p> -->
  
<table>
  <caption>Table 1 — Reflection library headers</caption>
  <tbody><tr><td>&lt;experimental/reflect&gt;</td></tr>
</tbody></table>

<h4>4.3 Acknowledgements <span class="section_name">[intro.ack]</span></h4>
<p>This work is the result of a collaboration of researchers in industry and academia.
   We wish to thank people who made valuable contributions within and outside these groups, including
   Ricardo Fabiano de Andrade, Roland Bock, Chandler Carruth, Klaim-Jo<c3><ab>l Lamotte, Jens Maurer,
   and many others not named here who contributed to the discussion.</ab></c3></p>




<h3>5 Lexical conventions <span class="section_name">[lex]</span></h3>
<h4>5.1 Keywords <span class="section_name">[lex.key]</span></h4>
<p>In C++ [lex.key], add the keyword <ins><code>reflexpr</code></ins> to the list of keywords in Table 5.</p>

<h3>6 Basic concepts <span class="section_name">[basic]</span></h3>
<p>In C++ [basic], add the following last paragraph:</p>
<div class="std">
<ins>An <em>alias</em> is a name introduced by a <code>typedef</code> declaration, an <em>alias-declaration</em>, or a <em>using-declaration</em>.</ins></div>

<h4>6.1 Fundamental types <span class="section_name">[basic.fundamental]</span></h4>
<p>In C++ [basic.fundamental], apply the following change:</p>
<div class="std">An expression of type <em>cv</em> <code>void</code> shall be used only as an expression statement (9.2), as an operand of a comma expression (8.19), as a second or third operand of <code>?:</code> (8.16), as the operand of <code>typeid</code>, <code>noexcept</code>, <ins><code>reflexpr</code>,</ins> or <code>decltype</code>, as the expression in a return statement (9.6.3) for a function with the return type <em>cv</em> <code>void</code>, or as the operand of an explicit conversion to type <em>cv</em> <code>void</code>.</div>

<h3>7 Standard conversions<span class="section_name">[conv]</span></h3>
<p>No changes are made to Clause 7 of the C++ Standard.</p>

<h3>8 Expressions<span class="section_name">[expr]</span></h3>
<p>No changes are made to Clause 8 of the C++ Standard.</p>

<h3>9 Statements<span class="section_name">[stmt.stmt]</span></h3>
<p>No changes are made to Clause 9 of the C++ Standard.</p>

<h3>10 Declarations <span class="section_name">[dcl.dcl]</span></h3>
<h4>10.1 Specifiers [dcl.spec]</h4>
<h4>10.1.7 Type specifiers [dcl.type]</h4>
<h4>10.1.7.2 Simple type specifiers <span class="section_name">[dcl.type.simple]</span></h4>
<p>In C++ [dcl.type.simple], apply the following change</p>
<div class="std">
The simple type specifiers are
<ul class="nobullet">
<li><em>simple-type-specifier</em>:
<ul class="nobullet">
<li><em>nested-name-specifier</em><sub>opt</sub> <em>type-name</em></li>
<li><em>nested-name-specifier</em> <code>template</code> <em>simple-template-id</em><br>
<code>char</code><br>
<code>char16_t</code><br>
<code>char32_t</code><br>
<code>wchar_t</code><br>
<code>bool</code><br>
<code>short</code><br>
<code>int</code><br>
<code>long</code><br>
<code>signed</code><br>
<code>unsigned</code><br>
<code>float</code><br>
<code>double</code><br>
<code>void</code><br>
<code>auto</code><br>
<em>decltype-specifier</em><br>
<em>constrained-type-specifier</em><br>
<ins><em>reflexpr-specifier</em></ins></li>
</ul></li>
<li><em>type-name</em>:
<ul class="nobullet">
<li>
<em>class-name</em><br>
<em>enum-name</em><br>
<em>typedef-name</em><br>
<em>simple-template-id</em></li>
</ul></li>
<li><em>decltype-specifier</em>:
<ul class="nobullet"><li><code>decltype (</code> <em>expression</em> <code>)</code><br>
<code>decltype ( auto )</code></li>
</ul></li>
<li><ins><em>reflexpr-specifier</em>:</ins>
<ul class="nobullet">
<li><ins><code>reflexpr (</code> <em>reflexpr-operand</em> <code>)</code></ins></li>
</ul></li>
<li><br></li>
<li><ins><em>reflexpr-operand</em>:</ins>
<ul class="nobullet">
<li><ins><code>::</code><br>
<em>type-id</em><br>
<em>nested-name-specifier</em><sub>opt</sub> <em>identifier</em><br>
<em>nested-name-specifier</em><sub>opt</sub> <em>simple-template-id</em><br>
</ins></li></ul></li>
</ul>

<p>...</p>

<p>The other <em>simple-type-specifiers</em> specify either a previously-declared type, a type determined from an expression, <ins>a reflection meta-object type (10.1.7.6)</ins>, or one of the fundamental types (6.9.1).</p>
</div>
<p>Add the following row to Table 11</p>
<table>
<tbody><tr><td><ins>reflexpr (<em>reflexpr-operand</em>)</ins></td><td><ins>The type as defined below</ins></td></tr>
</tbody></table>
<p>At the end of 10.1.7.2, insert the following paragraph:</p>
<div class="std">
<ins>For a <em>reflexpr-operand</em> <code><b>x</b></code>, the type denoted by <code>reflexpr(x)</code> is an implementation-defined type that satisfies constraints as laid out in 10.1.7.6.</ins>
</div>


<h4>10.1.7.6 Reflection type specifier <span class="section_name">[dcl.type.reflexpr]</span></h4>
<p>Insert the following section:</p>
<div class="std ins">
   <p>The <code>reflexpr</code> operator yields a type <code>T</code> that allows inspection of some properties of its operand through type traits or type transformations on <code>T</code> (21.11.4).
   The operand to the <code>reflexpr</code> operator shall be a type, namespace, enumerator, variable, structured binding or data member.
   Any such <code>T</code> satisfies the requirements of <code>reflect::Object</code> (21.11.3) and other <code>reflect</code> concepts, depending on the operand.
   A type satisfying the requirements of <code>reflect::Object</code> is called a <em>meta-object type</em>.
   A meta-object type is an incomplete namespace-scope class type ([class]).</p>
<p>
      An entity or alias <code>A</code> is <em>reflection-related</em> to an entity or alias <code>B</code> if
      </p>
      <ul>
      <li><code>A</code> and <code>B</code> are the same entity or alias,</li>
      <li><code>A</code> is a variable or enumerator and <code>B</code> is the type of <code>A</code>,</li>
      <li><code>A</code> is an enumeration and <code>B</code> is the underlying type of <code>A</code>,</li>
      <li><code>A</code> is a class and <code>B</code> is a member or base class of <code>A</code>,</li>
      <li><code>A</code> is a non-template alias that designates the entity <code>B</code>,</li>
      <li><code>A</code> is a class nested in <code>B</code> (12.2.5 [class.nest]),</li>
      <li><code>A</code> is not the global namespace and <code>B</code> is an enclosing namespace of <code>A</code>, or</li>
      <li><code>A</code> is reflection-related to an entity or alias <code>X</code> and <code>X</code> is reflection-related to <code>B</code>.</li>
      </ul>
<p>
[<em>Note:</em> This relationship is reflexive and transitive, but not symmetric. <em>— end note</em>]
</p>
<p>
[<em>Example:</em></p>
<pre><code>struct X;
struct B  {
   using X = ::X;
   typedef X Y;
};
struct D : B {
   using B::Y;
};
</code></pre><p>The alias <code>D::Y</code> is reflection-related to <code>::X</code>, but not to <code>B::Y</code> or <code>B::X</code>.
      <em>— end example</em>]</p>
<p>     
     Zero or more successive applications of type transformations that yield
     meta-object types (21.11.4) to the type denoted by a <em>reflexpr-specifier</em>
     enable inspection of entities and aliases that are reflection-related
     to the operand; such a meta-object type is said to <em>reflect</em> the respective
     reflection-related entity or alias.
     
</p>

[<em>Example:</em><p></p>
<pre><code>template &lt;typename T&gt; std::string get_type_name() {
   namespace reflect = std::experimental::reflect;
   // T_t is an Alias reflecting T:
   using T_t = reflexpr(T);
   // aliased_T_t is a Type reflecting the type for which T is a synonym:
   using aliased_T_t = reflect::get_aliased_t&lt;T_t&gt;;
   return reflect::get_name_v&lt;aliased_T_t&gt;;
}

std::cout &lt;&lt; get_type_name&lt;std::string&gt;(); // prints "basic_string"
</code></pre><p><em>— end example</em>]</p>

<p>The type specified by the <em>reflexpr-specifier</em> is implementation-defined.
   It is unspecified whether repeatedly applying <code>reflexpr</code> to the
   same operand yields the same type or a different type.
[ <em>Note:</em> If a meta-object type reflects an incomplete class type, certain
type transformations (21.11.4) cannot be applied. <em>— end note</em> ]

</p><p>[<em>Example:</em></p>
<pre><code>class X;
using X1_m = reflexpr(X);
class X {};
using X2_m = reflexpr(X);
using X_bases_1 = std::experimental::reflect::get_base_classes_t&lt;X1_m&gt;; // ok, X1_m reflects complete class X
using X_bases_2 = std::experimental::reflect::get_base_classes_t&lt;X2_m&gt;; // ok
std::experimental::reflect::get_reflected_type_t&lt;X1_m&gt; x; // ok, type X is complete
</code></pre><p> <em>— end example</em>]</p>

<p>For the operand <code>::</code>, the type specified by the <code>reflexpr-specifier</code> satisfies <code>reflect::GlobalScope</code>.
   For an operand of the form <em>identifier</em> where <em>identifier</em> is a template <em>type-parameter</em>, the type satisfies both <code>reflect::Type</code> and <code>reflect::Alias</code>.</p>

<p>
      The <em>identifier</em> or <em>simple-template-id</em> is looked up using the rules for name lookup (6.4): if a <em>nested-name-specifier</em> is included in the operand, qualified lookup (6.4.3) of <em>nested-name-specifier identifier</em> or <em>nested-name-specifier simple-template-id</em> will be performed, otherwise unqualified lookup (6.4.1) of <em>identifier</em> or <em>simple-template-id</em> will be performed.
   The type specified by the <em>reflexpr-specifier</em> satisfies concepts depending on the result of the name lookup, as shown in Table 12.</p>

<table class="withBorder">
<caption>Table 12 — <code>reflect</code> concept (21.11.3) that the type specified by a <em>reflexpr-specifier</em> satisfies, for a given <em>reflexpr-operand</em> <em>identifier</em> or <em>simple-template-id</em>.</caption>
<thead><tr><th>Category</th><th><em>identifier</em> or <em>simple-template-id</em> kind</th><th><code>reflect</code> Concept</th></tr></thead>
<tbody>
<tr><td rowspan="5">type</td><td><em>class-name</em> designating a union</td><td><code>reflect::Record</code></td></tr>
<tr><td><em>class-name</em> designating a non-union class</td><td><code>reflect::Class</code></td></tr>
<tr><td><em>enum-name</em></td><td><code>reflect::Enum</code></td></tr>
<tr><td><em>type-name</em> introduced by a <em>using-declaration</em></td><td>both <code>reflect::Type</code> and <code>reflect::Alias</code></td></tr>
<tr><td>any other <em>typedef-name</em></td><td>both <code>reflect::Type</code> and <code>reflect::Alias</code></td></tr>
<tr><td rowspan="2">namespace</td><td><em>namespace-alias</em></td><td>both <code>reflect::Namespace</code> and <code>reflect::Alias</code></td></tr>
<tr><td>any other <em>namespace-name</em></td><td>both <code>reflect::Namespace</code> and <code>reflect::ScopeMember</code></td></tr>
<tr><td>data member</td><td>the name of a data member</td><td><code>reflect::Variable</code></td></tr>
<tr><td rowspan="2">value</td><td>the name of a variable or structured binding that is not a local entity</td><td><code>reflect::Variable</code></td></tr>
<tr><td>the name of an enumerator</td><td>both <code>reflect::Enumerator</code> and <code>reflect::Constant</code></td></tr>
</tbody>
</table>
<p>If the <em>reflexpr-operand</em> designates a <em>type-id</em> not explicitly mentioned in Table 12, the type represented by the <em>reflexpr-specifier</em> satisfies <code>reflect::Type</code>.
    Any other <em>reflexpr-operand</em> renders the program ill-formed.</p>

<p>If the <em>reflexpr-operand</em> designates an entity or alias at block scope (6.3.3) or function prototype scope (6.3.4), the program is ill-formed.
   If the <em>reflexpr-operand</em> designates a class member, the type represented by the <em>reflexpr-specifier</em> also satisfies <code>reflect::RecordMember</code>.
   If the <em>reflexpr-operand</em> designates an variable or a data member, it is an unevaluated operand (expr.context).
   If the <em>reflexpr-operand</em> designates both an alias and a class name, the type represented by the <em>reflexpr-specifier</em> reflects the alias and satisfies <code>Alias</code>.
</p>

</div>

<h3>11 Declarators <span class="section_name">[dcl.decl]</span></h3>
<h4>11.1 Type names <span class="section_name">[dcl.name]</span></h4>
To specify type conversions explicitly, and as an argument of <code>sizeof</code>, <code>alignof</code>, <code>new</code>, <del>or</del> <code>typeid</code>, <ins>or reflexpr,</ins> the name of a type shall be specified.

 <h3>12 Classes<span class="section_name">[class]</span></h3>
 <p>No changes are made to Clause 12 of the C++ Standard.</p>

 <h3>13 Derived classes<span class="section_name">[class.derived]</span></h3>
 <p>No changes are made to Clause 13 of the C++ Standard.</p>

 <h3>14 Member access control<span class="section_name">[class.access]</span></h3>
 <p>No changes are made to Clause 14 of the C++ Standard.</p>

 <h3>15 Special member functions<span class="section_name">[special]</span></h3>
 <p>No changes are made to Clause 15 of the C++ Standard.</p>

 <h3>16 Overloading<span class="section_name">[over]</span></h3>
 <p>No changes are made to Clause 16 of the C++ Standard.</p>

 <h3>17 Templates <span class="section_name">[temp]</span></h3>
 <h4>17.6.2.1 Dependent types <span class="section_name">[temp.dep.type]</span></h4>
  A type is dependent if it is<br>
  [...]<br>
  — a <em>simple-template-id</em> in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent, <del>or</del><br>
   — denoted by <code>decltype(</code><em>expression</em><code>)</code>, where <em>expression</em> is type-dependent (14.6.2.2)<del>.</del><ins>, or</ins><br>
  <ins>— denoted by <code>reflexpr(</code><em>operand</em><code>)</code>, where <em>operand</em> designates a dependent type or a member of an unknown specialization.</ins>
 
 
 <h3>18 Exception handling<span class="section_name">[except]</span></h3>
 <p>No changes are made to Clause 18 of the C++ Standard.</p>

 <h3>19 Preprocessing directives<span class="section_name">[cpp]</span></h3>
 <p>No changes are made to Clause 19 of the C++ Standard.</p>

 <h3>20 Library introduction<span class="section_name">[library]</span></h3>
 <h4>20.5 Library-wide requirements <span class="section_name">[requirements]</span></h4>
 <h4>20.5.1 Library contents and organization <span class="section_name">[organization]</span></h4>
 <h4>20.5.1.2 Headers <span class="section_name">[headers]</span></h4>
 <p> Add &lt;experimental/reflect&gt; to Table 16 — C++ library headers.</p>

<h3>21 Language support library <span class="section_name">[language.support]</span></h3>
Insert the following section:
<div class="std ins">
<h4>21.11 Static reflection <span class="section_name">[reflect]</span></h4>
<h4>21.11.1 In general<span class="section_name">[reflect.general]</span></h4>

<p>As laid out in 10.1.7.6, compile-time constant metadata, describing various aspects of a program (static reflection data), can be accessed through meta-object types.
The actual metadata is obtained by instantiating templates constituting the interface of the meta-object types. These templates are collectively referred to as <em>meta-object operations</em>.</p>

<p>Meta-object types satisfy different concepts (21.11.3) depending on the type they reflect (10.1.7.6).
These concepts can also be used for meta-object type classification.
They form a generalization-specialization hierarchy, with <code>reflect::Object</code> being the common generalization for all meta-object types.
Unary operations and type transformations used to query static reflection data associated with these concepts are described in 21.11.4.</p>

  
<!--
<h3>2 meta-object trait <span class="section_name">[trait]</span></h3>
<p>This section conceptually adds a new trait to [reflect.unary.cat], to distinguish between <em>meta-object</em> types generated by the compiler and all other types.</p>
  <p>Header &lt;experimental/ranges/type_traits&gt; synopsis</p>
  
<pre><code>
namespace std {
namespace experimental {

template &lt;class T&gt; struct is_meta-object;
template &lt;class T&gt; constexpr bool is_meta-object_v = is_meta-object&lt;T&gt;::value;

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

  
<!--  
  <p>Insert a new element in <em>Table 14, C++ library headers</em> of [general.namespaces], named <code>&lt;experimental/reflexpr&gt;</code>.</p>
  -->
  
  <h4>21.11.2 Header <code>&lt;experimental/reflect&gt;</code> synopsis <span class="section_name">[reflect.synopsis]</span></h4>
<pre><code>

namespace std::experimental::reflect {
inline namespace v1 {

// 21.11.3 Concepts for meta-object types
template &lt;class T&gt; concept Object;
template &lt;class T&gt; concept ObjectSequence;
template &lt;class T&gt; concept Named;
template &lt;class T&gt; concept Alias;
template &lt;class T&gt; concept RecordMember;
template &lt;class T&gt; concept Enumerator;
template &lt;class T&gt; concept Variable;
template &lt;class T&gt; concept ScopeMember;
template &lt;class T&gt; concept Typed;
template &lt;class T&gt; concept Namespace;
template &lt;class T&gt; concept GlobalScope;
template &lt;class T&gt; concept Class;
template &lt;class T&gt; concept Enum;
template &lt;class T&gt; concept Record;
template &lt;class T&gt; concept Scope;
template &lt;class T&gt; concept Type;
template &lt;class T&gt; concept Constant;
template &lt;class T&gt; concept Base;


// 21.11.4 Meta-object operations
// 21.11.4.1 Multi-concept operations
template &lt;class T&gt; struct is_public;
template &lt;class T&gt; struct is_protected;
template &lt;class T&gt; struct is_private;

template &lt;class T&gt;
  constexpr auto is_public_v = is_public&lt;T&gt;::value;
template &lt;class T&gt;
  constexpr auto is_protected_v = is_protected&lt;T&gt;::value;
template &lt;class T&gt;
  constexpr auto is_private_v = is_private&lt;T&gt;::value;

// 21.11.4.2 Object operations
template &lt;Object T1, Object T2&gt; struct reflects_same;
template &lt;class T&gt; struct get_source_line;
template &lt;class T&gt; struct get_source_column;
template &lt;class T&gt; struct get_source_file_name;<!--
template &lt;class T&gt; struct get_source_function_name; unused: no reflexpr on decls from function scope -->

template &lt;Object T1, Object T2&gt;
  constexpr auto reflects_same_v = reflects_same&lt;T1, T2&gt;::value;
template &lt;class T&gt;
  constexpr auto get_source_line_v = get_source_line&lt;T&gt;::value;
template &lt;class T&gt;
  constexpr auto get_source_column_v = get_source_column&lt;T&gt;::value;
template &lt;class T&gt;
  constexpr auto get_source_file_name_v = get_source_file_name&lt;T&gt;::value;<!--
template &lt;class T&gt;
  constexpr auto get_source_function_name_v = get_source_function_name&lt;T&gt;::value; -->

// 21.11.4.3 ObjectSequence operations
template &lt;ObjectSequence S&gt; struct get_size;
template &lt;size_t I, ObjectSequence S&gt; struct get_element;
template &lt;template &lt;class...&gt; class Tpl, ObjectSequence S&gt;
  struct unpack_sequence;

template &lt;ObjectSequence T&gt;
  constexpr auto get_size_v = get_size&lt;T&gt;::value;
template &lt;size_t I, ObjectSequence S&gt;
  using get_element_t = typename get_element&lt;I, S&gt;::type;
template &lt;template &lt;class...&gt; class Tpl, ObjectSequence S&gt;
  constexpr auto unpack_sequence_t = unpack_sequence&lt;Tpl, S&gt;::type;

// 21.11.4.4 Named operations
template &lt;Named T&gt; struct is_unnamed;
template &lt;Named T&gt; struct get_name;
template &lt;Named T&gt; struct get_display_name;

template &lt;Named T&gt;
  constexpr auto is_unnamed_v = is_unnamed&lt;T&gt;::value;
template &lt;Named T&gt;
  constexpr auto get_name_v = get_name&lt;T&gt;::value;
template &lt;Named T&gt;
  constexpr auto get_display_name_v = get_display_name&lt;T&gt;::value;

// 21.11.4.5 Alias operations
template &lt;Alias T&gt; struct get_aliased;

template &lt;Alias T&gt;
  using get_aliased_t = typename get_aliased&lt;T&gt;::type;

// 21.11.4.6 Type operations
template &lt;Typed T&gt; struct get_type;
template &lt;Type T&gt; struct get_reflected_type;
template &lt;Type T&gt; struct is_enum;
template &lt;Type T&gt; struct is_class;
template &lt;Type T&gt; struct is_struct;
template &lt;Type T&gt; struct is_union;

template &lt;Typed T&gt;
  using get_type_t = typename get_type&lt;T&gt;::type;
template &lt;Type T&gt;
  using get_reflected_type_t = typename get_reflected_type&lt;T&gt;::type;
template &lt;Type T&gt;
  constexpr auto is_enum_v = is_enum&lt;T&gt;::value;
template &lt;Type T&gt;
  constexpr auto is_class_v = is_class&lt;T&gt;::value;
template &lt;Type T&gt;
  constexpr auto is_struct_v = is_struct&lt;T&gt;::value;
template &lt;Type T&gt;
  constexpr auto is_union_v = is_union&lt;T&gt;::value;

// 21.11.4.7 Member operations
template &lt;ScopeMember T&gt; struct get_scope;
template &lt;RecordMember T&gt; struct is_public&lt;T&gt;;
template &lt;RecordMember T&gt; struct is_protected&lt;T&gt;;
template &lt;RecordMember T&gt; struct is_private&lt;T&gt;;

template &lt;ScopeMember T&gt;
  using get_scope_t = typename get_scope&lt;T&gt;::type;

// 21.11.4.8 Record operations
template &lt;Record T&gt; struct get_public_data_members;
template &lt;Record T&gt; struct get_accessible_data_members;
template &lt;Record T&gt; struct get_data_members;
template &lt;Record T&gt; struct get_public_member_types;
template &lt;Record T&gt; struct get_accessible_member_types;
template &lt;Record T&gt; struct get_member_types;
template &lt;Class T&gt; struct get_public_base_classes;
template &lt;Class T&gt; struct get_accessible_base_classes;
template &lt;Class T&gt; struct get_base_classes;
template &lt;Class T&gt; struct is_final;

template &lt;Record T&gt;
  using get_public_data_members_t = typename get_public_data_members&lt;T&gt;::type;
template &lt;Record T&gt;
  using get_accessible_data_members_t = typename get_accessible_data_members&lt;T&gt;::type;
template &lt;Record T&gt;
  using get_data_members_t = typename get_data_members&lt;T&gt;::type;
template &lt;Record T&gt;
  using get_public_member_types_t = typename get_public_member_types&lt;T&gt;::type;
template &lt;Record T&gt;
  using get_accessible_member_types_t = typename get_accessible_member_types&lt;T&gt;::type;
template &lt;Record T&gt;
  using get_member_types_t = typename get_member_types&lt;T&gt;::type;
template &lt;Class T&gt;
  using get_public_base_classes_t = typename get_public_base_classes&lt;T&gt;::type;
template &lt;Class T&gt;
  using get_accessible_base_classes_t = typename get_accessible_base_classes&lt;T&gt;::type;
template &lt;Class T&gt;
  using get_base_classes_t = typename get_base_classes&lt;T&gt;::type;
template &lt;Class T&gt;
  constexpr auto is_final_v = is_final&lt;T&gt;::value;

// 21.11.4.9 Enum operations
template &lt;Enum T&gt; struct is_scoped_enum;
template &lt;Enum T&gt; struct get_enumerators;
template &lt;Enum T&gt; struct get_underlying_type;

template &lt;Enum T&gt;
  constexpr auto is_scoped_enum_v = is_scoped_enum&lt;T&gt;::value;
template &lt;Enum T&gt;
  using get_enumerators_t = typename get_enumerators&lt;T&gt;::type;
template &lt;Enum T&gt;
  using get_underlying_type_t = typename get_underlying_type&lt;T&gt;::type;

// 21.11.4.10 Value operations
template &lt;Constant T&gt; struct get_constant;
template &lt;Variable T&gt; struct is_constexpr;
template &lt;Variable T&gt; struct is_static;
template &lt;Variable T&gt; struct get_pointer;

template &lt;Constant T&gt;
  constexpr auto get_constant_v = get_constant&lt;T&gt;::value;
template &lt;Variable T&gt;
  constexpr auto is_constexpr_v = is_constexpr&lt;T&gt;::value;
template &lt;Variable T&gt;
  constexpr auto is_static_v = is_static&lt;T&gt;::value;
template &lt;Variable T&gt;
  const auto get_pointer_v = get_pointer&lt;T&gt;::value;

// 21.11.4.11 Base operations
template &lt;Base T&gt; struct get_class;
template &lt;Base T&gt; struct is_virtual;
template &lt;Base T&gt; struct is_public&lt;T&gt;;
template &lt;Base T&gt; struct is_protected&lt;T&gt;;
template &lt;Base T&gt; struct is_private&lt;T&gt;;

template &lt;Base T&gt;
  using get_class_t = typename get_class&lt;T&gt;::type;
template &lt;Base T&gt;
  constexpr auto is_virtual_v = is_virtual&lt;T&gt;::value;

// 21.11.4.12 Namespace operations
template &lt;Namespace T&gt; struct is_inline;

template &lt;Namespace T&gt;
  constexpr auto is_inline_v = is_inline&lt;T&gt;::value;

} // inline namespace v1
} // namespace std::experimental::reflect
</code>
</pre>

  
<h4>21.11.3 Concepts for meta-object types <span class="section_name">[reflect.concepts]</span></h4>

<p>The operations on meta-object types defined here require meta-object types to satisfy certain concepts ([dcl.spec.concept]). These concepts are also used to specify the result type for <em>TransformationTrait</em> type transformations that yield meta-object types.</p>

<h4>21.11.3.1 Concept <code>Object</code><span class="section_name">[reflect.concepts.object]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Object = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Object&lt;T&gt;</code> is satisfied if and only if <code>T</code> is a meta-object type, as generated by the <code>reflexpr</code> operator or any of the meta-object operations that in turn generate meta-object types.</dd>
</dl>


<h4>21.11.3.2 Concept <code>ObjectSequence</code><span class="section_name">[reflect.concepts.objseq]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept ObjectSequence = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>ObjectSequence&lt;T&gt;</code> is satisfied if and only if <code>T</code> is a sequence of <code>Object</code>s, generated by a meta-object operation.</dd>
</dl>

<h4>21.11.3.3 Concept <code>Named</code><span class="section_name">[reflect.concepts.named]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Named = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Named&lt;T&gt;</code> is satisfied if and only if <code>T</code> is an <code>Object</code> with an associated (possibly empty) name.</dd>
</dl>

<h4>21.11.3.4 Concept <code>Alias</code><span class="section_name">[reflect.concepts.alias]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Alias = Named&lt;T&gt; &amp;&amp; <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Alias&lt;T&gt;</code> is satisfied if and only if <code>T</code> is a <code>Named</code> that reflects a <code>typedef</code> declaration, an <em>alias-declaration</em>, a <em>namespace-alias</em>, a template <em>type-parameter</em>, a <em>decltype-specifier</em>, or a declaration introduced by a <em>using-declaration</em>.
Any such <code>T</code> also satisfies <code>ScopeMember</code>; its scope is the scope that the alias was injected into. [<em>Example:</em>
<pre><code>
namespace N {
   struct A;
}
namespace M {
   using X = N::A;
}
using M_X_t = reflexpr(M::X);
using M_X_scope_t = get_scope_t&lt;M_X_t&gt;;
</code></pre> The scope reflected by <code>M_X_scope_t</code> is <code>M</code>, not <code>N</code>. <em>— end example</em>]
Except for the type represented by the <code>reflexpr</code> operator, <code>Alias</code> properties resulting from type transformations (21.11.4) are not retained.</dd>
</dl>

<h4>21.11.3.5 Concept <code>RecordMember</code><span class="section_name">[reflect.concepts.recordmember]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept RecordMember = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>RecordMember&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects a <em>member-declaration</em>. Any such <code>T</code> also satisfies <code>ScopeMember</code>.<!-- covers members of class, struct, union --></dd>
</dl>

<h4>21.11.3.6 Concept <code>Enumerator</code><span class="section_name">[reflect.concepts.enumerator]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Enumerator = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Enumerator&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects an enumerator. Any such <code>T</code> also satisfies <code>Typed</code> and <code>ScopeMember</code>; the <code>Scope</code> of an <code>Enumerator</code> is its type also for enumerations that are unscoped enumeration types.</dd>
</dl>

<h4>21.11.3.7 Concept <code>Variable</code><span class="section_name">[reflect.concepts.variable]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Variable = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Variable&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects a variable or non-static data member. Any such <code>T</code> also satisfies <code>Typed</code>.</dd>
</dl>

<h4>21.11.3.8 Concept <code>ScopeMember</code><span class="section_name">[reflect.concepts.scopemember]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept ScopeMember = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>ScopeMember&lt;T&gt;</code> is satisfied if and only if <code>T</code> satisfies <code>RecordMember</code>, <code>Enumerator</code>, or <code>Variable</code>, or if <code>T</code> reflects a namespace that is not the global namespace. Any such <code>T</code> also satisfies <code>Named</code>. The scope of members of an unnamed union is the unnamed union; the scope of enumerators is their type.</dd>
</dl>

<h4>21.11.3.9 Concept <code>Typed</code><span class="section_name">[reflect.concepts.typed]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Typed = Variable&lt;T&gt; || Constant&lt;T&gt;;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Typed&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects a variable or enumerator.  Any such <code>T</code> also satisfies <code>Named</code></dd>.
</dl>


<h4>21.11.3.10 Concept <code>Namespace</code><span class="section_name">[reflect.concepts.namespace]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Namespace = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Namespace&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects a namespace (including the global namespace). Any such <code>T</code> also satisfies <code>Scope</code>. Any such <code>T</code> that does not reflect the global namespace also satisfies <code>ScopeMember</code>.</dd>
</dl>

<h4>21.11.3.11 Concept <code>GlobalScope</code><span class="section_name">[reflect.concepts.globalscope]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept GlobalScope = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>GlobalScope&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects the global namespace. Any such <code>T</code> also satisfies <code>Namespace</code>; it does not satisfy <code>ScopeMember</code>.</dd>
</dl>

<h4>21.11.3.12 Concept <code>Class</code><span class="section_name">[reflect.concepts.class]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Class = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Class&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects a non-union class type. Any such <code>T</code> also satisfies <code>Record</code>.</dd>
</dl>

<h4>21.11.3.13 Concept <code>Enum</code><span class="section_name">[reflect.concepts.enum]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Enum = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Enum&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects an enumeration type. Any such <code>T</code> also satisfies <code>Type</code> and <code>Scope</code>.</dd>
</dl>

<h4>21.11.3.14 Concept <code>Record</code><span class="section_name">[reflect.concepts.record]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Record = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Record&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects a class type. Any such <code>T</code> also satisfies <code>Type</code> and <code>Scope</code>.</dd>
</dl>

<h4>21.11.3.15 Concept <code>Scope</code><span class="section_name">[reflect.concepts.scope]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Scope = Namespace&lt;T&gt; || Record&lt;T&gt; || Enum&lt;T&gt;;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Scope&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects a namespace (including the global namespace), class, or enumeration. Any such <code>T</code> that does not reflect the global namespace also satisfies <code>ScopeMember</code>.</dd>
</dl>

<h4>21.11.3.16 Concept <code>Type</code><span class="section_name">[reflect.concepts.type]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Type = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Type&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects a type. Any such <code>T</code> also satisfies <code>Named</code> and <code>ScopeMember</code>.</dd>
</dl>

<h4>21.11.3.17 Concept <code>Constant</code><span class="section_name">[reflect.concepts.const]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Constant = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Constant&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects a constant expression ([expr.const]). Any such <code>T</code> also satisfies <code>ScopeMember</code> and <code>Typed</code>.</dd>
</dl>

<h4>21.11.3.18 Concept <code>Base</code><span class="section_name">[reflect.concepts.base]</span></h4>
<p class="function">
<code>
template &lt;class T&gt; concept Base = <em>see below</em>;
</code></p>
<dl class="attribute">
<dt></dt>
<dd><code>Base&lt;T&gt;</code> is satisfied if and only if <code>T</code> reflects a direct base class, as returned by the template <code>get_base_classes</code>.</dd>
</dl>



<h4>21.11.4 Meta-object Operations <span class="section_name">[reflect.ops]</span></h4>

<p>A meta-object operation extracts information from meta-object types. It is a class template taking one or more arguments, at least one of which models the <code>Object</code> concept. The result of a meta-object operation can be either a constant expression ([expr.const]) or a type.</p>

<h4>21.11.4.1 Multi-concept operations <span class="section_name">[reflect.ops.over]</span></h4>

<p class="function">
<code>
template &lt;class T&gt; struct is_public;<br>
template &lt;class T&gt; struct is_protected;<br>
template &lt;class T&gt; struct is_private;<br>
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>These meta-object operations are applicable to both <code>RecordMember</code> and <code>Base</code>. The generic templates do not have a definition. When multiple concepts implement the same meta-object operation, its template will be partially specialized for the concepts implementing the operation. [<em>Note:</em> For these overloaded operations, any meta-object type will always satisfy at most one of the concepts that the operation is applicable to. <em>— end note</em>]</dd>
<dt></dt><dd>[<em>Example:</em> An operation <code>OP</code> applicable to concepts <code>A</code> and <code>B</code> can be defined as follows:
<pre><code>
  template &lt;class T&gt; concept A = is_signed_v&lt;T&gt;;
  template &lt;class T&gt; concept B = is_class_v&lt;T&gt;;
  template &lt;class T&gt; struct OP; // undefined
  template &lt;A T&gt; struct OP&lt;T&gt; {...};
  template &lt;B T&gt; struct OP&lt;T&gt; {...};
  </code></pre> <em>— end example</em>]
  </dd></dl>

<h4>21.11.4.2 Object operations<span class="section_name">[reflect.ops.object]</span></h4>

<p class="function">
<code>
template &lt;Object T1, Object T2&gt; struct reflects_same;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>reflects_same&lt;T1, T2&gt;</code> shall meet the <code>BinaryTypeTrait</code> requirements ([meta.rqmts]),
    with a base characteristic of <code>true_type</code> if 
    <ul>
       <li><code>T1</code> and <code>T2</code> reflect the same alias, or</li>
       <li>neither <code>T1</code> nor <code>T2</code> reflect an alias and <code>T1</code> and <code>T2</code> reflect the same entity;</li>
    </ul>
    otherwise, with a base characteristic of <code>false_type</code>.</dd>
<dt></dt><dd>[<em>Example:</em> With <pre><code>
class A;
using a0 = reflexpr(A);
using a1 = reflexpr(A);
class A {};
using a2 = reflexpr(A);
constexpr bool b1 = is_same_v&lt;a0, a1&gt;; // unspecified value
constexpr bool b2 = reflects_same_v&lt;a0, a1&gt;; // true
constexpr bool b3 = reflects_same_v&lt;a0, a2&gt;; // true

struct C { };
using C1 = C;
using C2 = C;
constexpr bool b4 = reflects_same_v&lt;reflexpr(C1), reflexpr(C2)&gt;; // false
</code></pre> <em>— end example</em>]
</dd>
</dl>

<p class="function">
<code>
template &lt;class T&gt; struct get_source_line;<br>
template &lt;class T&gt; struct get_source_column;<br>
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of above templates shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]) with a base characteristic of <code>integral_constant&lt;uint_least32_t&gt;</code> and a value of the presumed line number ([cpp.predefined]) (for <code>get_source_line&lt;T&gt;</code>) and an implementation-defined value representing some offset from the start of the line (for <code>get_source_column&lt;T&gt;</code>) of the most recent declaration of the entity or typedef described by <code>T</code>.</dd>
</dl>

<p class="function">
<code>
template &lt;class T&gt; struct get_source_file_name;<!-- <br/>
template &lt;class T&gt; struct get_source_function_name; -->
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_source_file_name&lt;T&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]) with a static data member named <code>value</code> of type <code>const char (&amp;)[N]</code>, referencing a static, constant expression character array (NTBS) of length <code>N</code>, as if declared as <code>static constexpr char STR[N] = ...;</code>. The value of the NTBS is the presumed name of the source file ([cpp.predefined]) of the most recent declaration of the entity or typedef described by <code>T</code>.</dd>
</dl>


<h4>21.11.4.3 ObjectSequence operations<span class="section_name">[reflect.ops.objseq]</span></h4>

<p class="function">
<code>
template &lt;ObjectSequence S&gt; struct get_size;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_size&lt;S&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]) with a base characteristic of <code>integral_constant&lt;size_t, N&gt;</code>, where <code>N</code> is the number of elements in the object sequence.</dd>
</dl>

<p class="function">
<code>
template &lt;size_t I, ObjectSequence S&gt; struct get_element;
</code>
</p>
<dl class="attribute">
<dt>Remarks:</dt>
<dd>All specializations of <code>get_element&lt;I, S&gt;</code> shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> corresponds to the <code>I</code><sup>th</sup> element <code>Object</code> in <code>S</code>, where the indexing is zero-based.</dd>
</dl>

<p class="function">
<code>
template &lt;template &lt;class...&gt; class Tpl, ObjectSequence S&gt;<br>
&nbsp;&nbsp;struct unpack_sequence;
</code>
</p>
<dl class="attribute">
<dt>Remarks:</dt>
<dd>All specializations of <code>unpack_sequence&lt;Tpl, S&gt;</code> shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is an alias to the template <code>Tpl</code> specialized with the types in <code>S</code>.</dd>
</dl>


<h4>21.11.4.4 Named operations<span class="section_name">[reflect.ops.named]</span></h4>

<p class="function">
<code>
template &lt;Named T&gt; struct is_unnamed;<br>
template &lt;Named T&gt; struct get_name;<br>
template &lt;Named T&gt; struct get_display_name;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>is_unnamed&lt;T&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]) with a base characteristic as specified below.</dd>
<dt></dt>
<dd>All specializations of <code>get_name</code> and <code>get_display_name</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]) with a static data member named <code>value</code> of type <code>const char (&amp;)[N]</code>, referencing a static, constant expression character array (NTBS) of length <code>N</code>, as if declared as <code>static constexpr char STR[N] = ...;</code>.
<ul><li>For <code>T</code> reflecting an unnamed entity, the string's value is the empty string.</li>
<li>For <code>T</code> reflecting a <em>decltype-specifier</em>, the string's value is the empty string for <code>get_name&lt;T&gt;</code> and implementation-defined for <code>get_display_name&lt;T&gt;</code>.</li>
<li>For <code>T</code> reflecting an array, pointer, reference of function type, or a <em>cv</em>-qualified type, the string's value is the empty string for <code>get_name&lt;T&gt;</code> and implementation-defined for <code>get_display_name&lt;T&gt;</code>.</li>
<li>In the following cases, the string's value is implementation-defined for <code>get_display_name&lt;T&gt;</code> and has the following value for <code>get_name&lt;T&gt;</code>:
<ul>
  <li>for <code>T</code> reflecting an <code>Alias</code>, the unqualified name of the aliasing declaration: the identifier introduced by a <em>type-parameter</em> or a type name introduced by a <em>using-declaration</em>, alias;</li>
  <li>for <code>T</code> reflecting a specialization of a class template, its <em>template-name</em>;</li>
  <li>for <code>T</code> reflecting a class type, its <em>class-name</em>;</li>
  <li>for <code>T</code> reflecting a namespace, its <em>namespace-name</em>;</li>
  <li>for <code>T</code> reflecting an enumeration type, its <em>enum-name</em>;</li>
  <li>for <code>T</code> reflecting all other <em>simple-type-specifiers</em>, the name stated in the "Type" column of Table 9 in ([dcl.type.simple]);</li>
  <li>for <code>T</code> reflecting a variable, its unqualified name;</li>
  <li>for <code>T</code> reflecting an enumerator, its unqualified name;</li>
  <li>for <code>T</code> reflecting a class data member, its unqualified name.</li>
</ul>
</li>
<li>In all other cases, the string's value is the empty string for <code>get_name&lt;T&gt;</code> and implementation-defined for <code>get_display_name&lt;T&gt;</code>.</li>
 </ul></dd>
<dt></dt>
<dd>[<em>Note:</em> With <pre><code>namespace n { template &lt;class T&gt; class A; }
using a_m = reflexpr(n::A&lt;int&gt;);
</code></pre>
the value of <code>get_name_v&lt;a_m&gt;</code> is <code>"A"</code> while the value of <code>get_display_name_v&lt;a_m&gt;</code> might be <code>"n::A&lt;int&gt;"</code>. <em>— end note</em>]
</dd><dt></dt>
<dd>
The base characteristic of <code>is_unnamed&lt;T&gt;</code> is <code>true_type</code> if the value of <code>get_name_v&lt;T&gt;</code> is the empty string, otherwise it is <code>false_type</code>.
</dd></dl>



<h4>21.11.4.5 Alias operations<span class="section_name">[reflect.ops.alias]</span></h4>

<p class="function">
<code>
template &lt;Alias T&gt; struct get_aliased;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_aliased&lt;T&gt;</code> shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is the <code>Named</code> meta-object type reflecting
<ul><li>the redefined name, if <code>T</code> reflects an alias;</li>
<li>the template specialization's template argument type, if <code>T</code> reflects a template <em>type-parameter</em>;</li>
<li>the original declaration introduced by a <em>using-declaration</em>;</li>
<li>the aliased namespace of a <em>namespace-alias</em>;</li>
<li>the type denoted by the <em>decltype-specifier</em>.</li>
</ul>
The nested type named <code>type</code> is not an <code>Alias</code>; instead, it is reflecting the underlying non-<code>Alias</code> entity.</dd>
<dt></dt>
<dd>[<em>Example:</em> For
  <pre><code>
using i0 = int; using i1 = i0;
</code></pre>
<code>get_aliased_t&lt;reflexpr(i1)&gt;</code> reflects <code>int</code>. <em>— end example</em>]
</dd></dl>


<h4>21.11.4.6 Type operations<span class="section_name">[reflect.ops.type]</span></h4>

<p class="function">
<code>
template &lt;Typed T&gt; struct get_type;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_type&lt;T&gt;</code> shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is the <code>Type</code> reflecting the type of the entity reflected by <code>T</code>.</dd>
<dt></dt>
<dd>[<em>Example:</em> For
  <pre><code>
int v; using v_m = reflexpr(v);
</code></pre>
<code>get_type_t&lt;v_m&gt;</code> reflects <code>int</code>. <em>— end example</em>]
</dd>
<dt></dt>
<dd>If the entity reflected by <code>T</code> is a static data member that is declared to have a type array of unknown bound in the class definition, possible specifications of the array bound will only be accessible when the <em>reflexpr-operand</em> is the data member. </dd>
<dt></dt>
<dd>[<em>Note:</em> For
<pre><code>struct C {
   static int arr[17][];
};
int C::arr[17][42];
using C1 = get_type_t&lt;get_element_t&lt;0, get_data_members_t&lt;reflexpr(C)&gt;&gt;&gt;;
using C2 = get_type_t&lt;reflexpr(C::arr)&gt;;
</code></pre>
<code>C1</code> will reflect <code>int[17][]</code> while <code>C2</code> will reflect <code>int[17][42]</code>. <em>— end note</em>]
</dd></dl>

<p class="function">
<code>
template &lt;Type T&gt; struct get_reflected_type;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_reflected_type&lt;T&gt;</code> shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is the type reflected by <code>T</code>.
</dd>
<dd>[<em>Example:</em> For
   <pre><code>
 using int_m = reflexpr(int);
 get_reflected_type_t&lt;int_m&gt; x; // x is of type int
</code></pre>
<em>— end example</em>]
 </dd>
 <dt></dt>
</dl>

<p class="function">
<code>
template &lt;Type T&gt; struct is_enum;<br>
template &lt;Type T&gt; struct is_union;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>is_enum&lt;T&gt;</code> and <code>is_union&lt;T&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]). If <code>T</code> reflects an enumeration type (a union), the base characteristic of <code>is_enum&lt;T&gt;</code> (<code>is_union&lt;T&gt;</code>) is <code>true_type</code>, otherwise it is <code>false_type</code>.</dd></dl>

<p class="function">
<code>
template &lt;Type T&gt; struct is_class;<br>
template &lt;Type T&gt; struct is_struct;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of these templates shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]). If <code>T</code> reflects a class with <em>class-key</em> <code>class</code> (for <code>is_class&lt;T&gt;</code>) or <code>struct</code> (for <code>is_struct&lt;T&gt;</code>), the base characteristic of the respective template specialization is <code>true_type</code>, otherwise it is <code>false_type</code>. If the same class has redeclarations with both <em>class-key</em> <code>class</code> and <em>class-key</em> <code>struct</code>, the base characteristic of the template specialization of exactly one of <code>is_class&lt;T&gt;</code> and <code>is_struct&lt;T&gt;</code> can be <code>true_type</code>, the other template specialization is <code>false_type</code>; the actual choice of value is unspecified.</dd></dl>


<h4>21.11.4.7 Member operations<span class="section_name">[reflect.ops.member]</span></h4>

<p>A specialization of any of these templates with a meta-object type that is reflecting an incomplete type renders the program ill-formed.
   Such errors are not in the immediate context ([temp.deduct]).</p>

<p class="function">
<code>
template &lt;ScopeMember T&gt; struct get_scope;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_scope&lt;T&gt;</code> shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is the <code>Scope</code> reflecting a scope <em>S</em>. With <em>ST</em> being the scope of the declaration of the entity or typedef reflected by <code>T</code>, <em>S</em> is found as the innermost scope enclosing <em>ST</em> that is either a namespace scope (including global scope), class scope, or enumeration scope.</dd></dl>

<p class="function">
<code>
template &lt;RecordMember T&gt; struct is_public&lt;T&gt;;<br>
template &lt;RecordMember T&gt; struct is_protected&lt;T&gt;;<br>
template &lt;RecordMember T&gt; struct is_private&lt;T&gt;;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of these partial template specializations shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]). If <code>T</code> reflects a public member (for <code>is_public</code>), protected member (for <code>is_protected</code>), or private member (for <code>is_private</code>), the base characteristic of the respective template specialization is <code>true_type</code>, otherwise it is <code>false_type</code>.</dd></dl>



<h4>21.11.4.8 Record operations<span class="section_name">[reflect.ops.record]</span></h4>

<p>A specialization of any of these templates with a meta-object type that is reflecting an incomplete type renders the program ill-formed.
   Such errors are not in the immediate context ([temp.deduct]).</p>

<p class="function">
<code>
template &lt;Record T&gt; struct get_public_data_members;<br>
template &lt;Record T&gt; struct get_accessible_data_members;<br>
template &lt;Record T&gt; struct get_data_members;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of these templates shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is an alias to an <code>ObjectSequence</code> specialized with <code>RecordMember</code> types that reflect the following subset of data members of the class reflected by <code>T</code>:
<ul>
   <li>for <code>get_data_members</code>, all data members.</li>
   <li>for <code>get_public_data_members</code>, all public data members;</li>
  <li>for <code>get_accessible_data_members</code>, all data members that are accessible from the scope of the invocation of <code>reflexpr</code> which  (directly or indirectly) generated <code>T</code>.</li>
</ul>
The order of the elements in the <code>ObjectSequence</code> is the order of the declaration of the data members in the class reflected by <code>T</code>.</dd>
<dt>Remarks:</dt>
<dd>
  The program is ill-formed if <code>T</code> reflects a closure type.
</dd>
</dl>

<p class="function">
<code>
template &lt;Record T&gt; struct get_public_member_types;<br>
template &lt;Record T&gt; struct get_accessible_member_types;<br>
template &lt;Record T&gt; struct get_member_types;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of these templates shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is an alias to an <code>ObjectSequence</code> specialized with <code>Type</code> types that reflect the following subset of types declared in the class reflected by <code>T</code>:
<ul>
   <li>for <code>get_member_types</code>, all nested class types, enum types, or member typedefs.</li>
   <li>for <code>get_public_member_types</code>, all public nested class types, enum types, or member typedefs;</li>
  <li>for <code>get_accessible_member_types</code>, all nested class types, enum types, or member typedefs that are accessible from the scope of the invocation of <code>reflexpr</code> which (directly or indirectly) generated <code>T</code>.</li>
</ul>
The order of the elements in the <code>ObjectSequence</code> is the order of the first declaration of the types in the class reflected by <code>T</code>.</dd>
<dt>Remarks:</dt>
<dd>
  The program is ill-formed if <code>T</code> reflects a closure type.
</dd>
</dl>

<p class="function">
<code>
template &lt;Class T&gt; struct get_public_base_classes;<br>
template &lt;Class T&gt; struct get_accessible_base_classes;<br>
template &lt;Class T&gt; struct get_base_classes;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of these templates shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is an alias to an <code>ObjectSequence</code> specialized with <code>Base</code> types that reflect the following subset of base classes of the class reflected by <code>T</code>:
<ul>
  <li>for <code>get_base_classes</code>, all direct base classes;</li>
  <li>for <code>get_public_base_classes</code>, all public direct base classes;</li>
  <li>for <code>get_accessible_base_classes</code>, all direct base classes whose public members are accessible from the scope of the invocation of <code>reflexpr</code> which (directly or indirectly) generated <code>T</code>.</li>
</ul>
The order of the elements in the <code>ObjectSequence</code> is the order of the declaration of the base classes in the class reflected by <code>T</code>.</dd>
<dt>Remarks:</dt>
<dd>
  The program is ill-formed if <code>T</code> reflects a closure type.
</dd>
</dl>

<p class="function">
<code>
template &lt;Class T&gt; struct is_final;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>is_final&lt;T&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]). If <code>T</code> reflects a class that is marked with the <em>class-virt-specifier</em> <code>final</code>, the base characteristic of the respective template specialization is <code>true_type</code>, otherwise it is <code>false_type</code>.</dd></dl>


<h4>21.11.4.9 Enum operations<span class="section_name">[reflect.ops.enum]</span></h4>

<p class="function">
<code>
template &lt;Enum T&gt; struct is_scoped_enum;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>is_scoped_enum&lt;T&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]). If <code>T</code> reflects a <em>scoped enumeration</em>, the base characteristic of the respective template specialization is <code>true_type</code>, otherwise it is <code>false_type</code>.</dd></dl>


<p class="function">
<code>
template &lt;Enum T&gt; struct get_enumerators;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_enumerators&lt;T&gt;</code> shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is an alias to an <code>ObjectSequence</code> specialized with <code>Enumerator</code> types that reflect the enumerators of the enumeration type reflected by <code>T</code>.</dd>
<dt>Remarks:</dt>
<dd>A specialization of this template with a meta-object type that is reflecting an incomplete type renders the program ill-formed.
      Such errors are not in the immediate context ([temp.deduct]).</dd>
</dl>

<p class="function">
<code>
template &lt;Enum T&gt; struct get_underlying_type;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_underlying_type&lt;T&gt;</code> shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is an alias to a meta-object type that reflects the underlying type (10.2) of the enumeration reflected by <code>T</code>.</dd>
<dt>Remarks:</dt>
<dd>A specialization of this template with a meta-object type that is reflecting an incomplete type renders the program ill-formed.
      Such errors are not in the immediate context ([temp.deduct]).</dd>
</dl>


<h4>21.11.4.10 Value operations<span class="section_name">[reflect.ops.value]</span></h4>

<p class="function">
<code>
template &lt;Constant T&gt; struct get_constant;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_constant&lt;T&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]). It has a static data member named <code>value</code> whose type and value are those of the constant expression of the constant reflected by <code>T</code>.</dd></dl>

<p class="function">
<code>
template &lt;Variable T&gt; struct is_constexpr;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>is_constexpr&lt;T&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]). If <code>T</code> reflects a variable declared with the <em>decl-specifier</em> <code>constexpr</code>, the base characteristic of the respective template specialization is <code>true_type</code>, otherwise it is <code>false_type</code>.</dd></dl>

<p class="function">
<code>
template &lt;Variable T&gt; struct is_static;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>is_static&lt;T&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]). If <code>T</code> reflects a variable with static storage duration, the base characteristic of the respective template specialization is <code>true_type</code>, otherwise it is <code>false_type</code>.</dd></dl>

<p class="function">
<code>
template &lt;Variable T&gt; struct get_pointer;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_pointer&lt;T&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]), with a static data member named <code>value</code> of type <code>X</code> and value <code>x</code>, where
<ul>
  <li>for variables with static storage duration: <code>X</code> is <code>add_pointer&lt;Y&gt;</code>, where <code>Y</code> is the type of the variable reflected by <code>T</code> and <code>x</code> is the address of that variable; otherwise, </li>
  <li><code>X</code> is the pointer-to-member type of the member variable reflected by <code>T</code> and <code>x</code> a pointer to the member.</li>
</ul>
</dd></dl>

<h4>21.11.4.11 Base operations<span class="section_name">[reflect.ops.derived]</span></h4>

<p>A specialization of any of these templates with a meta-object type that is reflecting an incomplete type renders the program ill-formed.
      Such errors are not in the immediate context ([temp.deduct]).</p>

<p class="function">
<code>
template &lt;Base T&gt; struct get_class;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>get_class&lt;T&gt;</code> shall meet the <code>TransformationTrait</code> requirements ([meta.rqmts]). The nested type named <code>type</code> is an alias to <code>reflexpr(<em>X</em>)</code>, where <code><em>X</em></code> is the base class reflected by <code>T</code>.</dd></dl>


<p class="function">
<code>
template &lt;Base T&gt; struct is_virtual;<br>
template &lt;Base T&gt; struct is_public&lt;T&gt;;<br>
template &lt;Base T&gt; struct is_protected&lt;T&gt;;<br>
template &lt;Base T&gt; struct is_private&lt;T&gt;;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of the template and of these partial template specializations shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]). If <code>T</code> reflects a direct base class with the <code>virtual</code> specifier (for <code>is_virtual</code>), with the <code>public</code> specifier or with an assumed (see C++ [class.access.base]) <code>public</code> specifier (for <code>is_public</code>), with the <code>protected</code> specifier (for <code>is_protected</code>), or with the <code>private</code> specifier or with an assumed <code>private</code> specifier (for <code>is_private</code>), then the base characteristic of the respective template specialization is <code>true_type</code>, otherwise it is <code>false_type</code>.</dd></dl>



<h4>21.11.4.12 Namespace operations<span class="section_name">[reflect.ops.namespace]</span></h4>

<p class="function">
<code>
template &lt;Namespace T&gt; struct is_inline;
</code>
</p>
<dl class="attribute">
<dt></dt>
<dd>All specializations of <code>is_inline&lt;T&gt;</code> shall meet the <code>UnaryTypeTrait</code> requirements ([meta.rqmts]). If <code>T</code> reflects an inline namespace, the base characteristic of the template specialization is <code>true_type</code>, otherwise it is <code>false_type</code>.</dd></dl>

</div>

<!--
<h2 id="conclusion">Conclusion</h2>
<p>A variant has proven to be a useful tool. This paper proposes the necessary ingredients.</p>
-->



<h2 id="history">Revision history</h2>

<h4>Revision 1 (<a href="http://wg21.link/N3996">N3996</a>)</h4>

<p>Describes the method of static reflection
by means of compiler-generated unnamed types. Introduces the first version
of the metaobject concepts and some possibilities of their implementation.
Also includes discussion about the motivation and the design rationale for the proposal.
</p>

<h4>Revision 2 (<a href="http://wg21.link/N4111">N4111</a>)</h4>

<p>Refines the metaobject concepts and introduces
a concrete implementation of their interface by the means of templates similar
to the standard type traits. Describes some additions to the standard library
(mostly meta-programming utilities), which simplify the use of the metaobjects.
Answers some questions from the discussion about N3996 and expands the design
rationale.
</p>

<h4>Revision 3 (<a href="http://wg21.link/N4451">N4451</a>)</h4>

<p>Incorporates the feedback from the discussion
about N4111 at the Urbana meeting, most notably reduces the set of metaobject concepts and refines their
definitions, removes some of the additions to the standard library added in the previous revisions.
Adds context-dependent reflection.
</p>

<h4>Revision 4 (<a href="http://wg21.link/P0194R0">P0194R0</a>)</h4>

<p>Further refines the concepts from N4111; prefixes
the names of the metaobject operations with <code>get_</code>, adds new operations,
replaces the metaobject category tags with new metaobject traits.
Introduces a nested namespace <code>std::reflect</code> which contains most
of the reflection-related additions to the standard library.
Rephrases definition of meta objects using Concepts Lite. Specifies the
reflection operator name — <code>reflexpr</code>.
Introduces an experimental implementation of the reflection operator in clang.
Drops the context-dependent reflection from N4111 (will be re-introduced later).
</p>

<h4>Revision 5 (<a href="http://wg21.link/P0194R1">P0194R1</a>)</h4>

<p>Dropped all metaobject traits except <code>is_metaobject</code>. All metaobject
classification is now done by using the concepts.</p>
<p>The <code>meta::Scoped</code> concept has been renamed to <code>meta::ScopeMember</code>.
The <code>meta::Constant</code> and <code>meta::Specifier</code> concepts,
and several new operations have been added.
</p>
<p>The aliases for the operation templates returning metaobjects had previously
the <code>_t</code> suffix; this has been changed to the <code>_m</code> suffix.</p>

<h4>Revision 6 (<a href="http://wg21.link/p0194r2">P0194R2</a>)</h4>

<p>The following concepts from P0194R1 were dropped in order to simplify
the proposal:
<code>meta::Linkable</code>, <code>meta::Enum</code>,
<code>meta::DataMember</code>, <code>meta::MemberType</code>,
<code>meta::EnumClass</code>, <code>meta::TypeAlias</code> and
<code>meta::NamespaceAlias</code>.
</p>
<p>The following concepts were added to the proposal:
<code>meta::TagType</code>, <code>meta::Record</code>,
<code>meta::Enumerator</code>.
</p>
<p>Unlike in the previous proposal, metaobjects reflecting unnamed entities -
the global scope, unnamed namespaces and classes, etc. <em>do</em> conform to the
<code>meta::Named</code> concept and implement the name-returning operations.
</p>
<p>Unlike in the previous proposal, metaobjects reflecting the global scope
<em>do</em> conform to the <code>meta::ScopeMember</code> concept and the
<code>meta::get_scope</code> operation. For arguments reflecting
the global scope returns a metaobject reflecting the global scope
(i.e. the global scope is its own scope).
</p>
<p>Metaobjects reflecting built-in types and types like pointers, references,
arrays, etc. now don't have a scope (i.e. they do not conform to the
<code>meta::ScopeMember</code> concept).
</p>
<p>We have added a different mechanism for distinguishing between
unscoped and scoped <code>enum</code>s - the <code>meta::is_scoped_enum</code>
operation. Unlike in the previous proposal, <code>meta::Enum</code> reflecting
a unscoped enum <em>is</em> a <code>meta::Scope</code>.
</p>
<p>We now allow the default construction and copy construction of
values of metaobject types.
</p>
<p>Direct reflection of class data members, member types and type aliases,
enumerators and global scope/namespace-level variables has been added.</p>
<p>The typedef (type-alias) reflection has been simplified based on the
feedback from Oulu. Previously we required reflection to be aware about all
aliases in a <em>"chain"</em> even in the context of templates.</p>
<p>The mechanism for enumerating public-only vs. all (including non-public ones)
class members has been changed. Now the <em>"basic"</em> operations like
<code>meta::get_data_members</code>, <code>meta::get_member_types</code>, etc.
return all members, and the <code>meta::get_public_data_members</code>,
<code>meta::get_public_member_types</code>, return only the public class members.
</p>

<h4>Revision 7 (<a href="http://wg21.link/p0194r3">P0194R3</a>)</h4>
<p>Major wording update, clarifying the behavior for instance on dependent names and function-local declarations. All examples but those required for the wording are now found in the design discussion paper, <a href="http://wg21.link/p0385">P0385</a>.</p>
<p>Rename header, namespace from <code>meta</code> to <code>reflect</code>. Target a TS.</p>
<p>Use of function-style concepts, following the example set by the Ranges TS, for consistency reasons. The name of the reflection operator was changed to <code>$reflect</code>; the <em>basic source character set</em> was adjusted accordingly.</p>
<p>In addition to <code>get_public_base_classes</code>, <code>get_public_data_members</code> and <code>get_public_member_types</code> and their sibling without <code>public</code>, a new sibling <code>get_accessible_...</code> was added. The <code>Specifier</code>, <code>TagType</code> and <code>Reversible</code> concepts were removed. So was the <code>is_metaobject</code> trait. The type of meta-object operations "returning" strings have been updated. The order of template parameters for <code>MetaSequence</code> operations has been matched to similar operations of <code>tuple</code>. The suffix <code>_m</code> was reverted to <code>_t</code>. <code>$reflect()</code> with an empty operand is disallowed.</p>

<h4>Revision 8 (<a href="http://wg21.link/p0194r4">P0194R4</a>)</h4>
<p>As requested by EWG in Kona, the operator was renamed back to <code>reflexpr</code>; no need to change the source character set anymore. <code>get_base_name</code> is now called <code>get_name</code> and returns an empty string on pointer, references, arrays and <em>cv</em>-qualified types.</p>

<h4>Revision 9 (<a href="http://wg21.link/p0194r5">P0194R5</a>)</h4>
<p>Switched concept definitions to use variable concepts, unconstrained them (constrained concepts don't exist). Proper wording for the language part, based on a mixture of C++17 and the Concepts TS). Moved [meta] to section 20.15.</p>

<h4>Revision 10 (<a href="http://wg21.link/p0194r6">P0194R6</a>)</h4>
<p>A meta-object type is now incomplete (instead of trivial). Names of function types are now specified to be empty. A name found through a using directives does not create an <code>Alias</code> anymore. <code>GlobalScope</code> is not a <code>ScopeMember</code> anymore. Using declarations of members are now supported. The behavior of <code>is_class</code> versus <code>is_struct</code> is now clarified, especially in the case of conflicting redeclarations. Added <code>get_underlying_type&lt;Enum&gt;</code>. A structured binding now behaves as a <code>Variable</code>. Variables wil an initially declared type of array of unknown bound will only see a complete bound if reflected through the member (in contrast to a reflection through the class). Do not reference <code>source_location</code> to not create a dependency on LibFunv2.</p>


<h2 id="references" class="references unnumbered">References</h2>
<div id="ref-p0385">
<p>1. <em>Static reflection. Rationale, design and evolution.</em> <a href="http://wg21.link/p0385">P0385</a></p>
</div>
<div id="ref-p0578">
<p>2. <em>Static reflection in a nutshell.</em> <a href="http://wg21.link/p0578">P0578</a></p>
</div>



</body></html>