Reflection is the ability to examine, consider, and change the structure and behavior of a program.
Advertisement
C++ has more reflection. Here are two statements from the proposal (P2996R5,
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 speaking at specialist conferences. On his blog Modern C++ he discusses his passion C++ in depth.

,We not only want to observe the structure of the program: we also want to make it easy to generate code that relies on those observations. That combination is sometimes referred to as “reflective metaprogramming”, but within the WG21 discussion the term “reflection” is often used informally to refer to the same general idea.,
,As far as reflection and compile-time metaprogramming are concerned, this proposal is not intended to be the end game. Instead, we expect it to be a useful core around which more powerful features will be added over time. In particular, we believe that most or all of the remaining features have been discovered in P1240R2 and that code injection (according to the lines described inP2237R0)) are the desirable directions to follow.,
Story
The history of reflection in C++ is based on template metaprogramming. Template metaprogramming started around 1994, as did reflection. C++98 received runtime reflection (RTTI) and this function template type deduction. The data type library in C++11 improved the capabilities of C++. In C++26 we will probably get general reflection support.
My Strategy
I will rely on proposal P2996R5 and use the examples from proposal P2996R5 when introducing reflection in C++26.
First, I want to go back and forth from reflection value to grammatical elements.
Grammatical elements <=> Reflectance values
The following program starts in the grammatical area, goes to the reflection area and comes back to the grammatical area.
// forthAndBack.cpp (P2996R5)
#include
#include
#include
int main() {
constexpr auto r = ^int;
typename(:r:) x = 42; // Same as: int x = 42;
typename(:^char:) c = '*'; // Same as: char c = '*';
static_assert(std::same_as);
static_assert(std::same_as);
assert(x == 42);
assert(c == '*');
}
^: Reflexionsoperator
Produces a reflection value from its operand (^int
And^char
,(: refl :): Splicer
The reflexive value forms a grammatical element ((:r:)
And(:^char:)
,Reflexionswert
The representation of program elements as a constant expression is
Call ^gramOper
Creates a reflection with the data type: std::meta::info. std::same_as
There is a concept.
It makes no sense to just jump between the areas of grammar and thinking. Here is a more detailed analysis of the program enumString.cpp
,
Enum <=> String
enum => string
The following example converts an enum value to a string:
// enumString.cpp
#include
#include
#include
#include
template
requires std::is_enum_v // (1)
constexpr std::string enum_to_string(E value) {
std::string result = "";
(:expand(std::meta::enumerators_of(^E)):) >> // (2)
(&){
if (value == (:e:)) {
result = std::meta::identifier_of(e); // (3)
}
};
return result;
}
int main() {
std::cout << '\n';
enum Color { red, green, blue };
std::cout << "enum_to_string(Color::red): " << enum_to_string(Color::red) << '\n';
// std::cout << "enum_to_string(42): " << enum_to_string(42) << '\n';
std::cout << '\n';
}
In (1) we use the data type property std::is_enum
It was checked whether value
There is an enumerator. Expression ^E
The reflection value in (2) is generated. The function expand
in the same line can be ignored. The extension directive is missing in the current implementation.
Work std::meta::enumerators_of
And std::meta::enumerators_of
These (2) and (3) are metafunctions. They can only be executed at compile time because they are of the form consteval
Are declared.
Here are some meta functions.
namespace std::meta {
consteval auto members_of(info type_class) -> vector;
consteval auto bases_of(info type_class) -> vector;
consteval auto static_data_members_of(info type_class) -> vector;
consteval auto nonstatic_data_members_of(info type_class) -> vector;
consteval auto subobjects_of(info type_class) -> vector {
auto subobjects = bases_of(type_class);
subobjects.append_range(nonstatic_data_members_of(type_class));
return subobjects;
}
consteval auto enumerators_of(info type_enum) -> vector;
}
All meta functions give a std::vector
Reflection provides a number of meta-functions for analyzing data types and generating code.
enum <= string
Using the opposite steps converts the string to an Enum:
template
requires std::is_enum_v
constexpr std::optional string_to_enum(std::string_view name) {
template for (constexpr auto e : std::meta::enumerators_of(^E)) {
if (name == std::meta::identifier_of(e)) {
return (:e:);
}
}
return std::nullopt;
}
What will happen next?
Reflection provides several meta functions. I will implement them in my next article.
(RME)
