{"id":10130,"date":"2024-10-07T13:53:28","date_gmt":"2024-10-07T13:53:28","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=10130"},"modified":"2025-07-04T14:16:59","modified_gmt":"2025-07-04T14:16:59","slug":"reflection-in-c26-metafunctions-for-enums-and-classes","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/reflection-in-c26-metafunctions-for-enums-and-classes\/","title":{"rendered":"Reflection in C++26: Metafunctions for Enums and Classes"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Today, I continue my journey through reflection in C++26 and play with enums and classes.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter 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<p class=\"wp-block-paragraph\">The names of the metafunctions to access an Enum or a Class member are often identical.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Access the Members of an Enum<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The following program is based on one by Daveed Vandevoorde. Daveed is one of the fathers of reflection, and he used this example in his presentation, &#8220;<a href=\"https:\/\/www.youtube.com\/watch?v=eSJsURVV-Zk\">Reflections on C++ Reflection.<\/a>&#8220;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"> The program iterates through an Enum and displays its name and value for each enumerator.<\/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\">\/\/ daveed.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;array&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;experimental\/meta&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\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<span style=\"color: #006699; font-weight: bold\">struct<\/span> enum_item { \n  std<span style=\"color: #555555\">::<\/span>string_view name; \n  E value;\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> \nconsteval <span style=\"color: #006699; font-weight: bold\">auto<\/span> get_enum_data() {\n  std<span style=\"color: #555555\">::<\/span>array<span style=\"color: #555555\">&lt;<\/span>enum_item<span style=\"color: #555555\">&lt;<\/span>E<span style=\"color: #555555\">&gt;<\/span>, std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>enumerators_of(<span style=\"color: #555555\">^<\/span>E).size()<span style=\"color: #555555\">&gt;<\/span> result;\n  <span style=\"color: #007788; font-weight: bold\">int<\/span> k <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>;\n  <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span> mem<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    result[k<span style=\"color: #555555\">++<\/span>] <span style=\"color: #555555\">=<\/span> enum_item<span style=\"color: #555555\">&lt;<\/span>E<span style=\"color: #555555\">&gt;<\/span>{ std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>identifier_of(mem), std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>extract<span style=\"color: #555555\">&lt;<\/span>E<span style=\"color: #555555\">&gt;<\/span>(mem) };\n  <span style=\"color: #006699; font-weight: bold\">return<\/span> result;\n}\n\n<span style=\"color: #006699; font-weight: bold\">enum<\/span> MyEnum { \n  x, \n  y, \n  e <span style=\"color: #555555\">=<\/span> <span style=\"color: #555555\">-<\/span><span style=\"color: #FF6600\">1<\/span>, \n  z <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">99<\/span> \n};\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/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  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;members of &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>identifier_of(<span style=\"color: #555555\">^<\/span>MyEnum) <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span> x<span style=\"color: #555555\">:<\/span> get_enum_data<span style=\"color: #555555\">&lt;<\/span>MyEnum<span style=\"color: #555555\">&gt;<\/span>()) {\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;  &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> x.name <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot; = &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> (<span style=\"color: #007788; font-weight: bold\">long<\/span>)x.value <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  }\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 class=\"wp-block-paragraph\">The provided code snippet demonstrates the use of experimental metaprogramming features in C++ to introspect and manipulate enumeration types at compile time. The code begins by including the necessary headers: <code>&lt;array&gt;<\/code> for array support, <code>&lt;experimental\/meta&gt;<\/code> for metaprogramming utilities, and <code>&lt;iostream&gt;<\/code> for input-output operations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>enum_item<\/code> struct template is defined to hold information about an enumeration item. It contains two members: <code>name<\/code>, a <code>std::string_view<\/code> representing the name of the enumerator, and <code>value<\/code>, which holds the enumerator&#8217;s value of type <a href=\"command:_github.copilot.openSymbolFromReferences?%5B%22%22%2C%5B%7B%22uri%22%3A%7B%22scheme%22%3A%22file%22%2C%22authority%22%3A%22%22%2C%22path%22%3A%22%2FC%3A%2FUsers%2Fseminar%2FDropbox%2Fblog%2Fressourcen%2FC%2B%2B26%2FReflectionClass%2Fdaveed.cpp%22%2C%22query%22%3A%22%22%2C%22fragment%22%3A%22%22%7D%2C%22pos%22%3A%7B%22line%22%3A6%2C%22character%22%3A18%7D%7D%5D%2C%221fa4e15a-516a-4337-bff7-867c99377b8d%22%5D\"><code>E<\/code><\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>get_enum_data<\/code> function template is marked as <a href=\"command:_github.copilot.openSymbolFromReferences?%5B%22%22%2C%5B%7B%22uri%22%3A%7B%22scheme%22%3A%22file%22%2C%22authority%22%3A%22%22%2C%22path%22%3A%22%2FC%3A%2FUsers%2Fseminar%2FDropbox%2Fblog%2Fressourcen%2FC%2B%2B26%2FReflectionClass%2Fdaveed.cpp%22%2C%22query%22%3A%22%22%2C%22fragment%22%3A%22%22%7D%2C%22pos%22%3A%7B%22line%22%3A13%2C%22character%22%3A0%7D%7D%5D%2C%221fa4e15a-516a-4337-bff7-867c99377b8d%22%5D\"><code>consteval<\/code><\/a>, meaning it is evaluated at compile time. This function generates an array of <code>enum_item<\/code> structs for a given enumeration type <code>E<\/code>. It uses the <code>std::meta::enumerators_of<\/code> function to retrieve the enumerators of the enumeration type and iterates over them. For each enumerator, it creates an <code>enum_item<\/code> with the enumerator&#8217;s name and value, using <code>std::meta::identifier_of<\/code> to get the name and <code>std::meta::extract<\/code> to get the value. The resulting array is then returned.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>MyEnum<\/code> enumeration is defined with four enumerators: <code>x<\/code>, <code>y<\/code>, <code>e<\/code> (explicitly set to <code>-1<\/code>), and z (explicitly set to <code>99<\/code>). This enumeration is used as an example to demonstrate the metaprogramming capabilities.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the <code>main<\/code> function, the code first prints a newline for formatting purposes. It then prints the name of the enumeration type <code>MyEnum<\/code> using <code>std::meta::identifier_of<\/code>. Next, it calls <code>get_enum_data&lt;MyEnum&gt;()<\/code> to retrieve the array of <code>enum_item<\/code> structs for <code>MyEnum<\/code> and iterates over this array. For each <code>enum_item<\/code>, it prints the name and value of the enumerator. The value is cast to <code>long<\/code> for consistent output formatting. Finally, another newline is printed for formatting.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Overall, this code showcases how compile-time reflection can be used to introspect enumeration types and generate useful metadata, such as enumerator names and values, which can then be used at runtime.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the output of the program: <\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"218\" height=\"172\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/09\/daeed.png\" alt=\"\" class=\"wp-image-10138\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"> My Small Experiment<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This explanation was created by Microsoft&#8217;s KI tool <a href=\"https:\/\/copilot.microsoft.com\/\">Copilot<\/a>. Honestly, I was pretty impressed because the feature I described is brand new.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Access the Members of a Class<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The following program demonstrates two methods for accessing class members: by index and by name.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/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\">\/\/ reflectionClass.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;experimental\/meta&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Base { \n    <span style=\"color: #007788; font-weight: bold\">int<\/span> i{}; \n    <span style=\"color: #007788; font-weight: bold\">void<\/span> <span style=\"color: #CC00FF\">inc<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span><span style=\"color: #555555\">&amp;<\/span> j){ j<span style=\"color: #555555\">++<\/span>; }\n};\n\nconsteval <span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">number<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span> n) {\n  <span style=\"color: #0099FF; font-style: italic\">\/\/return std::meta::nonstatic_data_members_of(^Base)[n];<\/span>\n  <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>members_of(<span style=\"color: #555555\">^<\/span>Base)[n];\n}\n\n\nconsteval <span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">named<\/span>(std<span style=\"color: #555555\">::<\/span>string_view name) {\n  <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>info field <span style=\"color: #555555\">:<\/span> std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>members_of(<span style=\"color: #555555\">^<\/span>Base)) {\n    <span style=\"color: #006699; font-weight: bold\">if<\/span> (std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>has_identifier(field) <span style=\"color: #555555\">&amp;&amp;<\/span> std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>identifier_of(field) <span style=\"color: #555555\">==<\/span> name)\n      <span style=\"color: #006699; font-weight: bold\">return<\/span> field;\n  } \n  <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>meta<span style=\"color: #555555\">::<\/span>info{};\n}\n\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/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  Base base;\n  base.[<span style=\"color: #555555\">:<\/span>number(<span style=\"color: #FF6600\">0<\/span>)<span style=\"color: #555555\">:<\/span>] <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">1<\/span>;  \n  <span style=\"color: #0099FF; font-style: italic\">\/\/ base.[:member_number(10):] = 1;  Error<\/span>\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;base.i= &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> base.i <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  base.[<span style=\"color: #555555\">:<\/span>number(<span style=\"color: #FF6600\">1<\/span>)<span style=\"color: #555555\">:<\/span>](base.i);\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;base.i= &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> base.i <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#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  base.[<span style=\"color: #555555\">:<\/span>named(<span style=\"color: #CC3300\">&quot;i&quot;<\/span>)<span style=\"color: #555555\">:<\/span>] <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">3<\/span>;\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;base.i= &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> base.i <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  base.[<span style=\"color: #555555\">:<\/span>named(<span style=\"color: #CC3300\">&quot;inc&quot;<\/span>)<span style=\"color: #555555\">:<\/span>](base.i);\n  std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;base.i= &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> base.i <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 class=\"wp-block-paragraph\"><code>Base <\/code>is the class I want to reflect on. The metafunctions <code>number <\/code>and <code>named<\/code> provide me with the necessary information.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>number<\/code>: <code>std::meta::members_of(^Base)[n]<\/code> returns the member <code>n <\/code>of <code>Base<\/code>. On the contrary, <code>number<\/code>: <code>std::meta::nonstatic_data_members_of(^Base)[n]<\/code> returns the non-static data member <code>n <\/code>of Base. The reflection library also has a metafunction for getting all static data members of a class: <code>std::meta::static_data_members_of(^Base)[n]<\/code> <\/li>\n\n\n\n<li><code>named<\/code>: iterates through all members of <code>Base<\/code> and returns the member with the name <code>name<\/code>: <code>std::meta::identifier_of(field) == name<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Let me jump to the <code>main <\/code>program. The member<code> i <\/code>of <code>Base <\/code>is incremented. Either by assigning the value or invoking the member function <code>inc<\/code>. Using the wrong index or name gives a compile-time error:<code>[:member_number(10):] = 1<\/code>)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"> Finally, here&#8217;s the output of the program.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"185\" height=\"167\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/09\/ReflectionClass-.png\" alt=\"\" class=\"wp-image-10134\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s Next?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In my next post, I will continue to play with reflection in C++26.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today, I continue my journey through reflection in C++26 and play with enums and classes. The names of the metafunctions to access an Enum or a Class member are often identical. Access the Members of an Enum The following program is based on one by Daveed Vandevoorde. Daveed is one of the fathers of reflection, [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":10083,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[559],"tags":[560],"class_list":["post-10130","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\/10130","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=10130"}],"version-history":[{"count":15,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10130\/revisions"}],"predecessor-version":[{"id":10854,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10130\/revisions\/10854"}],"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=10130"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=10130"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=10130"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}