{"id":10081,"date":"2024-09-23T10:56:02","date_gmt":"2024-09-23T10:56:02","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=10081"},"modified":"2025-07-04T14:37:33","modified_gmt":"2025-07-04T14:37:33","slug":"reflection-in-c26","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/reflection-in-c26\/","title":{"rendered":"Reflection in C++26"},"content":{"rendered":"\n<p> After the search into the breadth starts today, the search into the depth: reflection.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"696\" height=\"537\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/09\/Time26Reflection.png\" alt=\"\" class=\"wp-image-10083\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/09\/Time26Reflection.png 696w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/09\/Time26Reflection-300x231.png 300w\" sizes=\"auto, (max-width: 696px) 100vw, 696px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Reflection<\/h2>\n\n\n\n<p><strong>Reflection <\/strong>is the ability of a program to examine, introspect, and modify its structure and behavior. <\/p>\n\n\n\n<p>Reflection in C++ is more. Here are two statements from the proposal (<a href=\"https:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2024\/p2996r5.html\">P2996R5<\/a>).<\/p>\n\n\n\n<p>&#8220;<em>We not only want to observe the structure of the program: We also want to ease generating code that depends on those observations. That combination is sometimes referred to as \u201c<strong>reflective metaprogramming<\/strong>\u201d, but within WG21 discussion the term \u201creflection\u201d has often been used informally to refer to the same general idea.<\/em>&#8220;<\/p>\n\n\n\n<p>&#8220;<em>This proposal is not intended to be the end-game as far as reflection and compile-time metaprogramming are concerned. Instead, we expect it will be a useful core around which more powerful features will be added incrementally over time. In particular, we believe that most or all the remaining features explored in P1240R2 and that code injection (along the lines described in [<a href=\"https:\/\/wg21.link\/p2237r0\">P2237R0<\/a>]) are desirable directions to pursue.<\/em>&#8220;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">History<\/h2>\n\n\n\n<p>The history of reflection in C++ is based on template metaprogramming. Template metaprogramming started around 1994, and so does reflection. C++98 got runtime reflection (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Run-time_type_information\">RTTI<\/a>) and <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/template_argument_deduction\">function template type deduction<\/a>. The type traits library in C++11 improved C++ capabilities. In C++26, we will probably get general reflection support.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"> My Strategy<\/h2>\n\n\n\n<p>I will base my reflection presentation in C++26 on proposal P2996R and use examples from it.<\/p>\n\n\n\n<p>First, let me jump forward and back from the reflection value to the grammatical elements.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Grammatical Elements &lt;=&gt; Reflection Value <\/h2>\n\n\n\n<p>The following program starts in the grammatical domain, jumps to the reflection domain, and back to the grammatical domain.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ forthAndBack.cpp (P2996R5)<\/span>\n\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;cassert&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;concepts&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>() {\n    constexpr <span style=\"color: #006699; font-weight: bold\">auto<\/span> r <span style=\"color: #555555\">=<\/span> <span style=\"color: #555555\">^<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span>;\n    <span style=\"color: #006699; font-weight: bold\">typename<\/span>[<span style=\"color: #555555\">:<\/span>r<span style=\"color: #555555\">:<\/span>] x <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">42<\/span>;       <span style=\"color: #0099FF; font-style: italic\">\/\/ Same as: int x = 42;<\/span>\n    <span style=\"color: #006699; font-weight: bold\">typename<\/span>[<span style=\"color: #555555\">:^<\/span><span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">:<\/span>] c <span style=\"color: #555555\">=<\/span> <span style=\"color: #CC3300\">&#39;*&#39;<\/span>;  <span style=\"color: #0099FF; font-style: italic\">\/\/ Same as: char c = &#39;*&#39;;<\/span>\n\n    static_assert(std<span style=\"color: #555555\">::<\/span>same_as<span style=\"color: #555555\">&lt;<\/span>decltype(x), <span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&gt;<\/span>);\n    static_assert(std<span style=\"color: #555555\">::<\/span>same_as<span style=\"color: #555555\">&lt;<\/span>decltype(c), <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">&gt;<\/span>);\n    assert(x <span style=\"color: #555555\">==<\/span> <span style=\"color: #FF6600\">42<\/span>);\n    assert(c <span style=\"color: #555555\">==<\/span> <span style=\"color: #CC3300\">&#39;*&#39;<\/span>);\n}\n<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code><strong> ^<\/strong><\/code>: <strong>Reflection Operator <\/strong>creates a reflection value from its operand (<code>^int <\/code>and<code> ^char<\/code>)<\/li>\n\n\n\n<li><code><strong>[: refl :]<\/strong><\/code>: <strong>Splicer <\/strong>creates a grammatical element from a reflection value (<code>[:r:]<\/code> and <code>[:^char:]<\/code>)<\/li>\n\n\n\n<li> <strong>Reflection Value <\/strong>is a representation of program elements as a constant expression<\/li>\n<\/ul>\n\n\n\n<p> The call<code> ^gramOper <\/code>creates a reflection value with an opaque reflection type:<code> std::meta::info<\/code>. <code>std::same_as<\/code> is a concept.<\/p>\n\n\n\n<p>Jumping between the grammatical and reflection domains makes no sense on its own. Let&#8217;s do something meaningful. Let&#8217;s analyze the program<code> enumString.cpp <\/code>deeper.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Enum &lt;=&gt; String<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Enum =&gt; String<\/h3>\n\n\n\n<p>The following example converts an enum value to a string. <\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ enumString.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;experimental\/meta&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;string&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;type_traits&gt;<\/span>\n\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span><span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> E<span style=\"color: #555555\">&gt;<\/span>\n  requires std<span style=\"color: #555555\">::<\/span>is_enum_v<span style=\"color: #555555\">&lt;<\/span>E<span style=\"color: #555555\">&gt;<\/span>                      <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\nconstexpr std<span style=\"color: #555555\">::<\/span>string enum_to_string(E value) {\n  std<span style=\"color: #555555\">::<\/span>string result <span style=\"color: #555555\">=<\/span> <span style=\"color: #CC3300\">&quot;&lt;unnamed&gt;&quot;<\/span>;\n  [<span style=\"color: #555555\">:<\/span>expand(std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>enumerators_of(<span style=\"color: #555555\">^<\/span>E))<span style=\"color: #555555\">:<\/span>] <span style=\"color: #555555\">&gt;&gt;<\/span>    <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n  [<span style=\"color: #555555\">&amp;<\/span>]<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">auto<\/span> e<span style=\"color: #555555\">&gt;<\/span>{\n    <span style=\"color: #006699; font-weight: bold\">if<\/span> (value <span style=\"color: #555555\">==<\/span> [<span style=\"color: #555555\">:<\/span>e<span style=\"color: #555555\">:<\/span>]) {\n      result <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>identifier_of(e);       <span style=\"color: #0099FF; font-style: italic\">\/\/ (3)<\/span>\n    }\n  };\n  <span style=\"color: #006699; font-weight: bold\">return<\/span> result;\n}\n\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> main() {\n\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold\">enum<\/span> Color { red, green, blue };\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;enum_to_string(Color::red): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> enum_to_string(Color<span style=\"color: #555555\">::<\/span>red) <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ std::cout &lt;&lt; &quot;enum_to_string(42): &quot; &lt;&lt; enum_to_string(42) &lt;&lt; &#39;\\n&#39;; <\/span>\n\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n}\n<\/pre><\/div>\n\n\n\n<p>Line (1) checks if <code>value <\/code>is an enumerator using the type trait <code>std::is_enum.<\/code> The expression <code>^E<\/code> in line (2) produces the reflection value. You can ignore the function <code>expand <\/code>in the same line. The expansion statements are missing in the current implementation. <\/p>\n\n\n\n<p>The functions <code>std::meta::enumerators_of <\/code>and <code>std::meta::enumerators_of<\/code> in lines (2 and 3) are metafunctions. The metafunctions can only run at compile time because they are declared as <code><a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-consteval-and-constinit\/\">consteval<\/a><\/code>.<\/p>\n\n\n\n<p> Here are a few of them:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">namespace<\/span> std<span style=\"color: #555555\">::<\/span>meta {\n  consteval <span style=\"color: #006699; font-weight: bold\">auto<\/span> members_of(info type_class) <span style=\"color: #555555\">-&gt;<\/span> vector<span style=\"color: #555555\">&lt;<\/span>info<span style=\"color: #555555\">&gt;<\/span>;\n  consteval <span style=\"color: #006699; font-weight: bold\">auto<\/span> bases_of(info type_class) <span style=\"color: #555555\">-&gt;<\/span> vector<span style=\"color: #555555\">&lt;<\/span>info<span style=\"color: #555555\">&gt;<\/span>;\n\n  consteval <span style=\"color: #006699; font-weight: bold\">auto<\/span> static_data_members_of(info type_class) <span style=\"color: #555555\">-&gt;<\/span> vector<span style=\"color: #555555\">&lt;<\/span>info<span style=\"color: #555555\">&gt;<\/span>;\n  consteval <span style=\"color: #006699; font-weight: bold\">auto<\/span> nonstatic_data_members_of(info type_class) <span style=\"color: #555555\">-&gt;<\/span> vector<span style=\"color: #555555\">&lt;<\/span>info<span style=\"color: #555555\">&gt;<\/span>;\n\n  consteval <span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">subobjects_of<\/span>(info type_class) <span style=\"color: #555555\">-&gt;<\/span> vector<span style=\"color: #555555\">&lt;<\/span>info<span style=\"color: #555555\">&gt;<\/span> {\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> subobjects <span style=\"color: #555555\">=<\/span> bases_of(type_class);\n    subobjects.append_range(nonstatic_data_members_of(type_class));\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> subobjects;\n  }\n\n  consteval <span style=\"color: #006699; font-weight: bold\">auto<\/span> enumerators_of(info type_enum) <span style=\"color: #555555\">-&gt;<\/span> vector<span style=\"color: #555555\">&lt;<\/span>info<span style=\"color: #555555\">&gt;<\/span>;\n}\n<\/pre><\/div>\n\n\n\n<p>All return a <code>std::vector<\/code>. Reflection offers many metafunctions for queering type information and generating code. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Enum &lt;= String<\/h3>\n\n\n\n<p>Applying the reverse steps makes an enum out of string.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> E<span style=\"color: #555555\">&gt;<\/span>\n  requires std<span style=\"color: #555555\">::<\/span>is_enum_v<span style=\"color: #555555\">&lt;<\/span>E<span style=\"color: #555555\">&gt;<\/span>                           \nconstexpr std<span style=\"color: #555555\">::<\/span>optional<span style=\"color: #555555\">&lt;<\/span>E<span style=\"color: #555555\">&gt;<\/span> string_to_enum(std<span style=\"color: #555555\">::<\/span>string_view name) {\n  <span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #006699; font-weight: bold\">for<\/span> (constexpr <span style=\"color: #006699; font-weight: bold\">auto<\/span> e <span style=\"color: #555555\">:<\/span> std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>enumerators_of(<span style=\"color: #555555\">^<\/span>E)) {\n    <span style=\"color: #006699; font-weight: bold\">if<\/span> (name <span style=\"color: #555555\">==<\/span> std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>identifier_of(e)) {                     \n      <span style=\"color: #006699; font-weight: bold\">return<\/span> [<span style=\"color: #555555\">:<\/span>e<span style=\"color: #555555\">:<\/span>];\n    }\n  }\n\n  <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>nullopt;\n}\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"> What&#8217;s next?<\/h2>\n\n\n\n<p>Reflection offers many metafunctions. I will apply them in my next post.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>After the search into the breadth starts today, the search into the depth: reflection. Reflection Reflection is the ability of a program to examine, introspect, and modify its structure and behavior. Reflection in C++ is more. Here are two statements from the proposal (P2996R5). &#8220;We not only want to observe the structure of the program: [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":10083,"comment_status":"closed","ping_status":"open","sticky":false,"template":"custom-template","format":"standard","meta":{"footnotes":""},"categories":[559],"tags":[560],"class_list":["post-10081","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c26-blog","tag-reflection"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10081","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=10081"}],"version-history":[{"count":24,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10081\/revisions"}],"predecessor-version":[{"id":10108,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10081\/revisions\/10108"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/10083"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=10081"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=10081"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=10081"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}