Reflection

FAQ

  1. Is there a native library or system that approximates the capabilities of .NET System.Reflection?

    Reflection in .NET is the ability of a program to inspect and manipulate its own structure and metadata at runtime. Think of reflection as a runtime mirror — it lets a program look at itself and act accordingly. Boost does not have a full runtime reflection system like .NET’s System.Reflection, but it does include several libraries and utilities that provide partial or compile-time reflection capabilities — the kind that are most practical and efficient in C++. The closest Boost comes to real reflection is encapsualted in Boost.Describe. This library allows you to describe the structure of a class — its members, base classes, and enums — at compile time, so you can iterate over them generically. Internally, Boost.Describe uses the features of Boost.Mp11.

    Other libraries that you might find value in include Boost.Pfr (Precise Function Reflection), which lets you reflect on structure fields without macros or metadata, using clever template magic. For richer type information there is Boost.TypeIndex and Boost.CallableTraits, and for metaprogramming there is Boost.Mp11, Boost.Fusion, and Boost.Hana.

  2. Can you show me example code demonstrating how to use Boost.Describe for Reflection?

    The following example shows how Boost.Describe and Boost.Mp11 work together to achieve something close to automatic runtime reflection:

    #include <boost/describe.hpp>
    #include <boost/mp11.hpp>
    #include <iostream>
    
    
    // Describe a simple struct
    struct User {
        int id;
        std::string name;
    };
    
    // Generate reflection metadata
    BOOST_DESCRIBE_STRUCT(User, (), (id, name))
    
    // Print fields using Boost.MP11 iteration
    template <typename T>
    void print_fields(const T& obj) {
        boost::mp11::mp_for_each<boost::describe::describe_members<T, boost::describe::mod_public>>(
            [&](auto D) {
                std::cout << D.name << " = " << obj.*D.pointer << "\n";
            });
    }
    
    int main() {
        User u{ 42, "Ada" };
        print_fields(u);
    }
  3. Can you show me example code demonstrating how to use Boost.PFR for Reflection?

    Boost.Pfr provides the io function for automatic input/output stream operators (<< and >>) for aggregate types — meaning you can print or read structs directly without manually defining stream operators. It reflects all public fields of a type at compile time (without macros or boilerplate), producing readable output like {field1, field2, field3} automatically, for example:

    #include <boost/pfr.hpp>
    #include <iostream>
    
    struct User {
        int id;
        std::string name;
        double balance;
    };
    
    int main() {
        User u{ 42, "Alice", 100.5 };
    
        std::cout << "As tuple: " << boost::pfr::io(u) << "\n";
    }
  4. Are there plans to extend Reflection further into the Standard C++ Library?

    Yes, in C++ 2026, though as C++ is a complicated language, the answer has to be complicated too. It is not just a case of making names and values available to the compiler, there are lots of different components that might make up a class or structure. The following table should help you identify what components will be fully reflectable, partly reflectable, and those that will not be:

    C++ construct C++26 reflection? Comments

    Class / struct

    ✅

    Can reflect the type itself

    Member names

    ✅

    Names can be obtained

    Member types

    ✅

    Types can be queried

    Data members

    ✅

    members_of() etc.

    Base classes

    ✅

    bases_of() exposes direct base-class relationships

    Inherited members

    🟡

    Can be reached through the reflected base classes; not simply flattened into members_of()

    Member functions

    ✅

    Functions are reflectable

    Function names/signatures

    ✅

    Various properties can be queried

    Static member functions

    ✅

    Special member functions

    ✅

    Reflection can identify special member functions

    Function templates

    ✅

    Explicitly representable

    Class templates

    ✅

    Explicitly representable

    Variable templates

    ✅

    Explicitly representable

    Concepts

    ✅

    Explicitly representable

    Free functions

    ✅

    Functions themselves can be reflected

    Friend functions

    🟡

    Reflectable as functions, but friendship/access relationships are more nuanced

    Namespaces

    ✅

    Namespaces and namespace aliases are representable

    Enums

    ✅

    Enumerators can be reflected

    Type aliases

    ✅

    Lambda expressions

    🟡

    Closure types have special restrictions

    Attributes

    🟡

    This has been evolving separately

    Statements / expressions / arbitrary AST

    ❌

    Not intended to be a general AST reflection system

    Source code itself

    ❌

    A C++ parser is not exposed to the program

    In short, C++26 reflection is not simply exposing every relationship in the compiler’s internal representation. There is also a security aspect too, passwords for example should not be made publicly available through reflection. For this case, there is the concept of access context, a pretty sophisticated aspect of the design.

    Note

    AST = Abstract Syntax Tree: the compiler’s structured representation of the program’s syntax and meaning.

  5. How does the "access context" of the Reflection design work?

    The access context is essentially reflection’s way of preserving C++'s normal public/protected/private rules. A reflection operation doesn’t automatically give you a magical back door into everything a class contains. Instead, the reflection machinery can be evaluated with a particular context representing who is asking. For example, if reflection is performed from within a class, it can have the access privileges that code inside that class normally has; if it is performed from unrelated code, private members remain inaccessible. The design includes facilities such as std::meta::access_context and is_accessible() to query whether a reflected entity is accessible from a particular context.

  6. How might Reflection in C++ 26 impact Boost libraries such as Describe and PFR?

    Clearly there will be an impact — and there is a very interesting answer: C++26 reflection does not simply make Boost.Describe and Boost.Pfr obsolete. In fact, the current Boost.Pfr implementation already has a switch to use C++26 reflection when available. Over time, Boost.Pfr may become a thin abstraction over standard reflection when available. And Boost.Describe could become a compatibility/adaptation layer, particularly useful for existing Boost libraries and pre-C++26 code.

    The following tables shows a likely comparison of features:

    Boost.PFR Boost.Describe C++26 Reflection

    Main idea

    Discover aggregate fields without annotations

    Explicitly describe selected members

    Standard language facility

    Macros required

    No

    Yes

    No

    C++14+

    ✅

    ✅

    ❌ C++26

    Member data

    ✅

    ✅

    ✅

    Member names

    ✅

    ✅

    ✅

    Member types

    ✅

    ✅

    ✅

    Base classes

    Limited

    ✅

    ✅

    Member functions

    ❌/very limited

    ✅

    ✅

    Enums

    Limited

    ✅

    ✅

    Templates

    ❌

    Some support

    ✅

    General program entities

    ❌

    Limited

    Much broader

    Standard facility

    ❌

    ❌

    ✅