Reflection in C++26: metafunctions for enums and classes

0
19
Reflection in C++26: metafunctions for enums and classes


After an introduction to reflection and a basic introduction to metafunctions in C++26, this time it’s about enums and classes.

Advertisement





Rainer Grimm has been working as a software architect, team and training manager for many years. He enjoys writing articles on the programming languages ​​C++, Python, and Haskell, but also frequently speaks at expert conferences. On his blog Modern C++ he discusses his passion C++ in depth.

The names of metafunctions for accessing elements of an enum or class are often the same.



ZTE launches the photography-focused Nubia Focus Pro 5G in our marketZTE launches the photography-focused Nubia Focus Pro 5G in our market

The following program is based on a program by David VandeWorde. David is one of the fathers of reflection in C++ and included this example in his presentation.Reflections on C++ Reflection used.

The program loops through an enum and displays the name and value for each enumerator.

// daveed.cpp

#include 
#include 
#include 

template 
struct enum_item { 
  std::string_view name; 
  E value;
};

template 
consteval auto get_enum_data() {
  std::array, std::meta::enumerators_of(^E).size()> result;
  int k = 0;
  for (auto mem: std::meta::enumerators_of(^E))
    result(k++) = enum_item{ std::meta::identifier_of(mem), std::meta::extract(mem) };
  return result;
}

enum MyEnum { 
  x, 
  y, 
  e = -1, 
  z = 99 
};

int main() {

  std::cout << '\n';

  std::cout << "members of " << std::meta::identifier_of(^MyEnum) << '\n';
  for (auto x: get_enum_data()) {
    std::cout << "  " << x.name << " = " << (long)x.value << '\n';
  }

  std::cout << '\n';

}

The code snippet provided demonstrates the use of experimental metaprogramming features in C++ to check and manipulate enum types at compile time. The code starts by inserting the necessary headers:array>For array support,experimental,meta> for metaprogramming utilities andiostream>For input-output operations.

enum_item Structure template is defined to hold information about an enum element. It consists of two elements: name is one std::string_viewwhich represents the name of the enum element, and valuewhich is the value of the enum element of data type E prevent.

get_enum_data The function template is like this consteval Marked, which means it will be evaluated at compile time. This function produces an array enum_item-Structures for a specific enum type Eshe uses it std::meta::enumerators_ofThe function of getting enum elements of enum type and iterating through them. For each enum value it creates one enum_item with the name and value of the enum value, where they std::meta::identifier_of got the name, and std::meta::extractTo get the value. The resulting array is then returned.

MyEnum-The enum is defined with four enum elements: y, x, e (explicitly set to -1) and z (explicitly set to 99). This computation is used as an example to demonstrate metaprogramming features.

In mainThe function, code first outputs a new line for formatting purposes. then enum type name MyEnum with the help of std::meta::identifier_of Were issued. will be next get_enum_data() called into the table of enum_item-Structures for MyEnum And iterate through this array. for all enum_item The name and value of the enum element are output. Values ​​are stored for consistent output formatting long Converted. Finally, there is output for another line break formatting.

Overall, this code shows how reflection can be used at compile time to check enum types and generate useful metadata such as enum names and values, which can then be used at run time.

Here is the output of the program:



This explanation was created using AI tools co-pilot Created by Microsoft. I have to admit that I was quite impressed since the feature described is fairly new.

The following program shows two ways to access elements of a class: by index and by name.

// reflectionClass.cpp

#include 
#include 

struct Base { 
    int i{}; 
    void inc(int& j){ j++; }
};

consteval auto number(int n) {
  //return std::meta::nonstatic_data_members_of(^Base)(n);
  return std::meta::members_of(^Base)(n);
}


consteval auto named(std::string_view name) {
  for (std::meta::info field : std::meta::members_of(^Base)) {
    if (std::meta::has_identifier(field) && std::meta::identifier_of(field) == name)
      return field;
  } 
  return std::meta::info{};
}


int main() { 

  std::cout << '\n';

  Base base;
  base.(:number(0):) = 1;  
  std::cout << "base.i= " << base.i << '\n';
  base.(:number(1):)(base.i);
  std::cout << "base.i= " << base.i << '\n';

  std::cout << '\n';
 
  base.(:named("i"):) = 3;
  std::cout << "base.i= " << base.i << '\n';
  base.(:named("inc"):)(base.i);
  std::cout << "base.i= " << base.i << '\n';

}

Base This is the class I want to think about. metafunctionnumber” And “named“Provide me with the information I need.

  • "number": std::meta::members_of(^Base)(n) returns element n From Base Back. On the contrary, there is “number": std::meta::nonstatic_data_members_of(^Base)(n) non-static data elements n From Base Back. The Reflection library also has a meta function that can be used to retrieve all the static data members of a class: std::meta::static_data_members_of(^Base)(n)
  • namend:iterates through all elements of Base and returns the element with name name Back: std::meta::identifier_of(field) == name

Now I will go to the main event. Element i From Base Increases. either by assigning a value or calling a function incUsing the wrong index or name will cause a compile-time error.:(:member_number(10):) = 1).

Finally, I show the output of the program here:



In my next article I will continue playing with reflection in C++26.


(rme)

Logitech launches POP icon keys, a keyboard with smart shortcutsLogitech launches POP icon keys, a keyboard with smart shortcuts

LEAVE A REPLY

Please enter your comment!
Please enter your name here