CodeNebula
C++26coreexpert

Reflection (P2996, Static Reflection)

C++26 · The Next Frontier · Compiler flag: -std=c++26

Explanation

Compile-time introspection of types, members, and namespaces via static reflection (P2996). Enables querying type properties, enumerating members, and generating code based on type structure -- all at compile time without runtime overhead.

Real-World Scenario

Automatically generate serialization and deserialization code for game objects by reflecting over their data members at compile time.

Quick Snippet

snippet.cpp
#include <meta>

struct Player { std::string name; int score; };

// Reflect over members of Player at compile time
constexpr auto members = std::meta::members_of(^Player);
static_assert(members.size() == 2);
// Access member name: std::meta::name_of(members[0]) == "name"

Full Example

reflection.cpp
// CodeNebula - C++26 Example: Static Reflection (P2996)
// Compile: g++ -std=c++26 -Wall -Wextra -o example reflection.cpp
// Note: Requires C++26 compiler support (GCC 15+ / Clang 19+ expected)

// P2996 introduces static reflection via std::meta::info. This allows
// compile-time introspection of types, members, enumerators, and more.
// ^^ (reflexpr) gives a meta::info handle for any named entity.

#include <iostream>
#include <string>
#include <vector>

// --- C++26 Reflection Syntax (not yet compilable) ---
//
// #include <meta>
//
// struct Point { double x; double y; double z; };
//
// // Get meta::info for a type
// constexpr auto point_info = ^^Point;
//
// // Iterate over members at compile time
// template<typename T>
// void print_members() {
//     [:expand(std::meta::nonstatic_data_members_of(^^T)):] >> [&]<auto mem> {
//         std::cout << std::meta::name_of(mem) << " = "
//                   << obj.[:mem:] << "\n";
//     };
// }
//
// // Get enumerator names automatically
// enum class Color { Red, Green, Blue };
// constexpr auto color_name(Color c) -> std::string {
//     // Iterate enumerators of Color via reflection
//     for (auto e : std::meta::enumerators_of(^^Color))
//         if (std::meta::value_of<Color>(e) == c)
//             return std::string(std::meta::name_of(e));
//     return "unknown";
// }

// --- Simulation using C++20 features ---

struct Point { double x; double y; double z; };

enum class Color { Red, Green, Blue };

// Manual simulation of what reflection would automate
void print_point_members(const Point& p) {
    std::cout << "  x = " << p.x << std::endl;
    std::cout << "  y = " << p.y << std::endl;
    std::cout << "  z = " << p.z << std::endl;
}

std::string color_name(Color c) {
    switch (c) {
        case Color::Red:   return "Red";
        case Color::Green: return "Green";
        case Color::Blue:  return "Blue";
    }
    return "unknown";
}

int main() {
    std::cout << "=== C++26 Static Reflection (Simulated) ===" << std::endl;

    Point p{1.0, 2.5, 3.7};
    std::cout << "Point members:" << std::endl;
    print_point_members(p);

    std::cout << "Color names:" << std::endl;
    std::cout << "  " << color_name(Color::Red) << std::endl;
    std::cout << "  " << color_name(Color::Green) << std::endl;
    std::cout << "  " << color_name(Color::Blue) << std::endl;

    std::cout << "Reflection eliminates boilerplate for serialization, "
              << "enum-to-string, etc." << std::endl;
    return 0;
}

// Expected output:
// === C++26 Static Reflection (Simulated) ===
// Point members:
//   x = 1
//   y = 2.5
//   z = 3.7
// Color names:
//   Red
//   Green
//   Blue
// Reflection eliminates boilerplate for serialization, enum-to-string, etc.
Run command
g++ -std=c++26 -Wall -Wextra -o example reflection.cpp