<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title></title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
  margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
  </style>
</head>
<body>
<h1 id="static-reflection-in-a-nutshell">Static Reflection in a Nutshell</h1>
<ul>
<li>Document number: <strong>P0578R1</strong>, ISO/IEC JTC1 SC22 WG21</li>
<li>Date: 2017-06-18</li>
<li>Authors: Matúš Chochlík <a href="mailto:chochlik@gmail.com">chochlik@gmail.com</a>, Axel Naumann <a href="mailto:axel@cern.ch">axel@cern.ch</a>, and David Sankel <a href="mailto:dsankel@bloomberg.net">dsankel@bloomberg.net</a></li>
<li>Audience: LEWG</li>
</ul>
<h2 id="abstract">Abstract</h2>
<p>This paper is a concise introduction to the static reflection facilities proposed in <a href="http://wg21.link/p0194">P0194</a>. See also <a href="http://wg21.link/p0385">P0385</a> for examples, in-depth design rational, and future extensions. A previous version of the functionality described here has been <a href="https://github.com/matus-chochlik/clang/tree/mirror-reflection">implemented in clang</a> and is available for experimentation.</p>
<h2 id="history">History</h2>
<ul>
<li>2017-06-13. <strong>P0578R1</strong>. Modified to reflect the outcome of the 2016 Oulu meeting where <code>reflexpr</code> was preferred to <code>$reflect</code>. The <code>get_base_name</code> operation was changed to <code>get_name</code> which only works for types that have a name (e.g., <code>const</code> and <code>&amp;</code> qualified types do not have a name).</li>
<li>2016-02-04. <strong>P0578R0</strong>. The initial version of this paper.</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>C++ provides many facilities that allow for the compile-time inspection and manipulation of types and values. Indeed an entire field, template metaprogramming, arose to take advantage of these features. While the feats accomplished have been both surprising and impressive, C++ still lacks some fundamental building blocks in this area. There is no way, for example, to discover an arbitrary class's name or query its member variables. This paper describes an attempt to extend the language with the most crucial of these building blocks.</p>
<p>Lets look at a simple example illustrating our proposed design:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;<span class="kw">typename</span> T&gt;
T min(<span class="at">const</span> T&amp; a, <span class="at">const</span> T&amp; b) {
  log() &lt;&lt; <span class="st">&quot;min&lt;&quot;</span>
        &lt;&lt; get_display_name_v&lt;reflexpr(T)&gt;
        &lt;&lt; <span class="st">&quot;&gt;(&quot;</span> &lt;&lt; a &lt;&lt; <span class="st">&quot;, &quot;</span> &lt;&lt; b &lt;&lt; <span class="st">&quot;) = &quot;</span>;
  T result = a &lt; b ? a : b;
  log() &lt;&lt; result &lt;&lt; <span class="bu">std::</span>endl;
  <span class="cf">return</span> result;
}</code></pre></div>
<p>Here we define a <code>min</code> function that closely resembles, aside from the logging, the semantics of <code>std::min</code>. Assuming several calls, the output of this function might look something like this:</p>
<pre><code>min&lt;int&gt;(1, 33)
min&lt;std::string&gt;(hello, world)
...</code></pre>
<p>Note that the <em>type</em> argument as well as the value arguments are printed out. Our proposed reflection syntax and library is what makes this possible.</p>
<p>The key expression is <code>get_display_name_v&lt;reflexpr(T)&gt;</code>, which consists of two parts. The first is <code>reflexpr(T)</code>. This expression produces a special type that contains meta-information concerning <code>T</code> (e.g. name, member variable, and inheritance information). We call these types &quot;meta objects&quot; following industry practice. <code>reflexpr</code>'s argument doesn't necessarily have to be a type though; many kinds of syntax are recognized in the general case. The second part is the call to <code>get_display_name_v</code>. This is where we extract a piece of information from the meta object, in this case the &quot;display name&quot;. Most uses of the reflection facilities we provide are variations of this simple theme: reflect to produce a metaobject and query that meta object for information.</p>
<h3 id="our-approach">Our Approach</h3>
<p>The design space for reflection is vast. It is tempting to set complete coverage as a goal even though the value proposition is dubious at best. Instead, we attempted a pragmatic approach where we add a minimal set of features that are tied to concrete use cases and compliment the existing C++ feature set. You will not see, for instance, a replacement or alternative for <code>std::is_const</code> or other well-established pre-existing reflection capabilities.</p>
<p>We also are not, in this iteration, proposing a high-level reflection API. There is still a lot of discussion as to what such an API should look like. More experimentation is required. Instead we provide low-level interfaces that can be built upon.</p>
<p>Our vision for a complete reflection software stack is as follows</p>
<center>
User Code<br> ↑<br> Domain Specific Library<br> ↑<br> Reflection Library<br> ↑<br> Reflection Facilities
</center>
<p>At the bottom are low-level reflection facilities. That is what we are proposing here. On top of that is a higher-level reflection library that, building on the lower-level facilities, provides an easy and convenient way to write libraries requiring reflection. Higher yet are domain specific libraries. This could be a serialization library or an automatic database schema generator. Finally, on the top, is user code which makes use of the domain specific libraries.</p>
<p>The danger of designing facilities instead of a high-level API is that the former ends up inadequate for the latter. Fortunately, we've been developing in parallel several variations of high-level APIs that make use of our facilities. See the following snippet making use of the <a href="https://github.com/matus-chochlik/mirror">mirror library</a>, a Boost.MPL style reflection library built on our facilities:</p>
<div class="sourceCode"><pre class="sourceCode c++"><code class="sourceCode cpp"><span class="kw">template</span> &lt;<span class="kw">typename</span> T&gt;
<span class="dt">bool</span> generic_equal(<span class="at">const</span> T&amp; a, <span class="at">const</span> T&amp; b)
{
  <span class="kw">using</span> metaT = reflexpr(T);
  <span class="dt">bool</span> result = <span class="kw">true</span>;
  mirror::for_each&lt;mirror::<span class="dt">get_data_members_t</span>&lt;metaT&gt;&gt;(
    compare_data_members&lt;T&gt;{a, b, result}
  );
  <span class="cf">return</span> result;
}</code></pre></div>
<p>At the 2016 Issaquah meeting, Louis Dionne presented a Boost.Hana-styled reflection library built on the facilities described here along with an impressive JSON serialization library built on top of that. We find this result encouraging and suggestive that our facilities are as general and API-agnostic as we had hoped.</p>
<h3 id="whats-in-and-whats-out">What's In and What's Out</h3>
<p>As mentioned above, we're aiming for a minimal set of functionality that still satisfies a number of use cases. Here's a basic summary of what's included and what's not.</p>
<p>Included:</p>
<ul>
<li><p><strong>Data members</strong>. e.g. walking through the data members of a class</p></li>
<li><p><strong>Member types</strong>. e.g. walking through nested types or <code>typedef</code>s in a class</p></li>
<li><p><strong>Enumerators</strong>. The ability to, for example, make one-line serialization routines for <code>enum</code>s</p></li>
<li><p><strong>Template instantiations</strong>. The ability to reflect on instantiated templates, such as <code>std::vector&lt;int&gt;</code></p></li>
<li><p><strong>Alias support</strong>. The ability to distinguish between a <code>typedef</code> and its underlying type</p></li>
</ul>
<p>Not Included:</p>
<ul>
<li><p><strong>Namespace member sequences</strong>. We're not providing the ability to walk through all the declarations of a namespace. Efficient implementations of such a feature seem unlikely and use cases are wanting.</p></li>
<li><p><strong>Functions</strong>. We think we know what we want and how we can do it, but this chapter is complex. This is comming in a separate proposal, <a href="http://wg21.link/p0670">P0670</a>.</p></li>
<li><p><strong>Class templates</strong>. It is unclear, as of yet, what reflecting on an uninstantiated template, like <code>vector</code>, would look like.</p></li>
<li><p><strong>Building new datatypes</strong>. We have plans to extend this proposal at some point with the ability to build new datatypes with an identifier generation facility. See the design document for more details.</p></li>
<li><p><strong>Reflection facilities already in C++</strong>. As mentioned before, we're in the business of cooperating with existing facilities instead of replacing what already exists.</p></li>
<li><p><strong>Anonymous functions</strong>. An extension to this paper which supports anonymous functions will be forthcoming.</p></li>
<li><p><strong>Attributes</strong>. We feel that reflecting on attributes would be a highly valuable extension to this proposal. However, this feature would cause a significant change to how we use attributes today. We intend to propose this in a future paper.</p></li>
</ul>
<h2 id="language-considerations">Language Considerations</h2>
<p>The primary consideration at the language level was what to call the <code>reflexpr</code> operator. There was a bikeshedding at the 2016 Kona meeting and <code>reflexpr</code> had the most consensus when compared to several other options.</p>
<h2 id="library-considerations">Library Considerations</h2>
<h3 id="strings">strings</h3>
<p>The lack of a decent compile-time string representation forced us to choose between several undesirable options. For consistency with the other metafunctions we decided to use <code>integral_constant&lt;const char (&amp;)[N], STR&gt;</code> where <code>STR</code> is the name of a static, null-terminated byte string of length <code>N</code>.</p>
<p>We assume WG21 will incorporate proper compile-time strings at some point and consider this a placeholder implementation.</p>
<h3 id="objectsequence"><code>ObjectSequence</code></h3>
<p>Because there isn't a native type-list implementation in the standard library, we included a placeholder implementation in the reflection proposal. It provides the ability to query size and get an element by index.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;ObjectSequence T&gt;
  <span class="kw">constexpr</span> <span class="kw">auto</span> get_size_v = get_size&lt;T&gt;::value;

<span class="kw">template</span> &lt;<span class="dt">size_t</span> I, ObjectSequence S&gt;
  <span class="kw">using</span> <span class="dt">get_element_t</span> = <span class="kw">typename</span> get&lt;I, S&gt;::type;</code></pre></div>
<p>Additionally, the <code>unpack_sequence_v</code> metafunction was provided that enables the convenient conversion of a <code>ObjectSequence</code> into another type-list representation, such as a <code>std::tuple</code>.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;<span class="kw">template</span> &lt;<span class="kw">class</span>...&gt; <span class="kw">class</span> Tpl, ObjectSequence S&gt;
  <span class="kw">constexpr</span> <span class="kw">auto</span> unpack_sequence_v = unpack_sequence&lt;Tpl, S&gt;::value;</code></pre></div>
<p>We assume WG21 will incorporate proper compile-time type lists at some point and consider this a placeholder implementation as well.</p>
<h3 id="concepts">Concepts</h3>
<p>All types containing metainformation satisfy the <code>reflect::Object</code> concept. Beyond that, there are several other concepts that provide more specialized information. Generally a metaobject will satisfy several of the concepts below.</p>
<p>Class-like things:</p>
<ul>
<li><code>Record</code>. A <code>union</code> or a <code>Class</code></li>
<li><code>Class</code>. A <code>class</code> or a <code>struct</code></li>
<li><code>Base</code>. The <code>public B</code> part of <code>class A : public B {};</code>, for example</li>
<li><code>RecordMember</code>. Data members and member types</li>
</ul>
<p>Scopes:</p>
<ul>
<li><code>Namespace</code>. A namespace</li>
<li><code>Scope</code>. A namespace, class, or enumeration scope</li>
<li><code>ScopeMember</code>. Something in a scope</li>
<li><code>GlobalScope</code>. The global namespace, <code>::</code></li>
</ul>
<p>Enums:</p>
<ul>
<li><code>Enum</code>. An <code>enum</code>.</li>
<li><code>Enumerator</code>. An enumerator.</li>
</ul>
<p>Types:</p>
<ul>
<li><code>Typed</code>. Something with a type, such as a member variable.</li>
<li><code>Type</code>. A type.</li>
</ul>
<p>Expressions:</p>
<ul>
<li><code>Variable</code>. A variable.</li>
<li><code>Constant</code>. A constant expression, like an enumerator.</li>
</ul>
<p>Other:</p>
<ul>
<li><code>Named</code>. Something with a name.</li>
<li><code>Alias</code>. An alias, such as a <code>typedef</code>.</li>
<li><code>ObjectSequence</code>. Our stand-in for type lists.</li>
</ul>
<p>In the following sections we'll go into more detail for some of the more important concepts and operations.</p>
<h3 id="object">Object</h3>
<p>The <code>reflexpr</code> operation always produces a type that satisfies the <code>Object</code> concept. <code>Object</code>s provide the ability to query source location and the <code>reflects_same</code> method determines whether or not two objects reflect the same underlying entity.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;Object T&gt; <span class="kw">struct</span> get_source_line;
<span class="kw">template</span> &lt;Object T&gt; <span class="kw">struct</span> get_source_column;
<span class="kw">template</span> &lt;Object T&gt; <span class="kw">struct</span> get_source_file_name;

<span class="kw">template</span> &lt;Object T1, Object T2&gt;
<span class="kw">struct</span> reflects_same;</code></pre></div>
<p>Additionally, <code>get_source_location</code> is provided for compatibility with the <code>std::source_location</code> datatype in the library fundamentals TS.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;Object T&gt;
<span class="kw">struct</span> get_source_location;
<span class="co">// return a std::source_location object</span></code></pre></div>
<h3 id="record"><code>Record</code></h3>
<p>A record is a <code>union</code>, <code>class</code>, or <code>struct</code> (i.e. a class type).</p>
<p>The most general way to query members is through use of <code>get_data_members</code> and <code>get_member_types</code>. These provide lists of all the public, private, and protected members. Because the access of private members can cause abstraction leaks, two other variants are provided.</p>
<p>The <code>get_public_*</code> metafunctions return only the public members of a record. This operation can be used safely on third party code. The <code>get_accessible_*</code> metafunctions, on the other hand, will include private members as well if the <code>reflexpr</code> operation's surrounding context allows it (e.g. it is found in a member function or friend class). Encapsulation cannot be broken with either of these two variants.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;Record T&gt; <span class="kw">struct</span> get_data_members;
<span class="kw">template</span> &lt;Record T&gt; <span class="kw">struct</span> get_public_data_members;
<span class="kw">template</span> &lt;Record T&gt; <span class="kw">struct</span> get_accessible_data_members;

<span class="kw">template</span> &lt;Record T&gt; <span class="kw">struct</span> get_member_types;
<span class="kw">template</span> &lt;Record T&gt; <span class="kw">struct</span> get_public_member_types;
<span class="kw">template</span> &lt;Record T&gt; <span class="kw">struct</span> get_accessible_member_types;</code></pre></div>
<h3 id="named">Named</h3>
<p>Most entities that can be reflected upon have a name of some sort and the <code>Named</code> concept supports this. There are two primary string-returning operations, <code>get_display_name</code> and <code>get_name</code>.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;Named T&gt; <span class="kw">struct</span> get_display_name;
<span class="kw">template</span> &lt;Named T&gt; <span class="kw">struct</span> get_name;</code></pre></div>
<p>While the semantics of both of these functions is implementation defined, they have a clear difference in intent as described below.</p>
<h4 id="get_name"><code>get_name</code></h4>
<p><code>get_name</code> returns the name of the underlying reflected entity if it has one. Note that abbreviations are elaborated and instantiated template classes return the name of the template class itself. Decorated types, such as those with <code>const</code> and <code>volatile</code> do not have a name and the <code>get_name</code> operation on these returns &quot;&quot;.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp">get_name_v&lt;reflexpr(<span class="dt">unsigned</span>)&gt;
<span class="co">// &quot;unsigned int&quot;</span>

<span class="kw">using</span> foo = <span class="dt">int</span>;
get_name_v&lt;reflexpr(foo)&gt;
<span class="co">// &quot;foo&quot;</span>

get_name_v&lt;reflexpr(<span class="bu">std::</span>vector&lt;<span class="dt">int</span>&gt;)&gt;
<span class="co">// &quot;vector&quot;</span>

get_name_v&lt;reflexpr(<span class="at">volatile</span> <span class="bu">std::</span>size_t* [<span class="dv">10</span>])&gt;
<span class="co">// &quot;&quot;</span></code></pre></div>
<h4 id="get_display_name"><code>get_display_name</code></h4>
<p><code>get_display_name</code> provides a way for compilers to provide a non-portable, but human readable, representation of the underlying entity. The intent is for this to hook into the technology already used in compilers to provide human readable diagnostics.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp">get_display_name_v&lt;reflexpr(<span class="dt">unsigned</span>)&gt;
<span class="co">// &quot;unsigned&quot;</span>

<span class="kw">using</span> foo = <span class="dt">int</span>;
get_display_name_v&lt;reflexpr(foo)&gt;
<span class="co">// &quot;foo&quot;</span>

get_display_name_v&lt;reflexpr(<span class="bu">std::</span>vector&lt;<span class="dt">int</span>&gt;)&gt;
<span class="co">// &quot;std::vector&lt;int&gt;&quot;</span>

get_display_name_v&lt;reflexpr(<span class="at">volatile</span> <span class="bu">std::</span>size_t* [<span class="dv">10</span>])&gt;
<span class="co">// &quot;volatile std::size_t *[10]&quot;</span></code></pre></div>
<h3 id="alias"><code>Alias</code></h3>
<p>Aliases (viz. <code>typedef</code>s, etc.) provide a <code>get_aliased</code> operation which returns the underlying entity being reflected.</p>
<pre><code>template &lt;Alias T&gt; struct get_aliased;</code></pre>
<p>For example:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">using</span> MyInt = <span class="dt">int</span>;

get_name_v&lt;reflexpr(MyInt)&gt; <span class="co">// &quot;MyInt&quot;</span>
get_name_v&lt;<span class="dt">get_aliased_t</span>&lt;reflexpr(MyInt)&gt;&gt; <span class="co">// &quot;int&quot;</span></code></pre></div>
<p>Note that <code>get_aliased_t</code> always returns the true underlying type. Walking through <code>typedef</code>s of <code>typedef</code>s is not supported as a concession to compiler implementers.</p>
<h2 id="conclusion">Conclusion</h2>
<p>We've overviewed a proposal for adding static reflection to C++. The feature set provided here goes a long way towards filling the holes metaprogrammers face today and will be extended to support even more ambitious reflection capabilities in the future.</p>
</body>
</html>
