Reflection in C++26: Metafunctions

Reflection in C++26: Metafunctions

Reflection offers many metafunctions that run at compile time.

The metafunctions are declared as consteval. consteval creates a so-called immediate function. Each invocation of an immediate function creates a compile-time constant. To say it more directly. A consteval (immediate) function is executed at compile-time.

Read more about consteval and constinit in my previous post: Two new Keywords in C++20: consteval and constinit.

What we Know so far:

 constexpr auto r = ^int;
    typename[:r:] x = 42;       // Same as: int x = 42;
    typename[:^char:] c = '*';  // Same as: char c = '*';
        

The reflection operator (^) produces out of the grammatical element (C++ element) a reflection value. The type of the reflection value std::meta::info. The reflection value (the reflection) can be an argument of the metafunctions or the splicers ([: refl :]). The splicers create grammatical elements.

So reflection value can be defined as follows:

namespace std {
  namespace meta {
    using info = decltype(^::);
  }
}
        

So, what is missing? Of course, the metafunctions. I will present you all of them for two reasons:

  • There are many metafunctions.
  • There is no official listing of all the meta functions (October 2024)

Metafunctions

namespace std::meta {
  using info = decltype(^::);

  template <typename R>
  concept reflection_range = /* see above */;

  // name and location
  consteval auto identifier_of(info r) -> string_view;
  consteval auto u8identifier_of(info r) -> u8string_view;

  consteval auto display_string_of(info r) -> string_view;
  consteval auto u8display_string_of(info r) -> u8string_view;

  consteval auto source_location_of(info r) -> source_location;

  // type queries
  consteval auto type_of(info r) -> info;
  consteval auto parent_of(info r) -> info;
  consteval auto dealias(info r) -> info;

  // object and value queries
  consteval auto object_of(info r) -> info;
  consteval auto value_of(info r) -> info;

  // template queries
  consteval auto template_of(info r) -> info;
  consteval auto template_arguments_of(info r) -> vector<info>;

  // member queries
  consteval auto members_of(info type_class) -> vector<info>;
  consteval auto bases_of(info type_class) -> vector<info>;
  consteval auto static_data_members_of(info type_class) -> vector<info>;
  consteval auto nonstatic_data_members_of(info type_class) -> vector<info>;
  consteval auto subobjects_of(info type_class) -> vector<info>;
  consteval auto enumerators_of(info type_enum) -> vector<info>;

  // member access
  struct access_context {
    static consteval access_context current() noexcept;
    consteval access_context() noexcept;
  };

  consteval auto is_accessible(
          info r,
          acess_context from = access_context::current());

  consteval auto accessible_members_of(
          info target,
          access_context from = access_context::current()) -> vector<info>;
  consteval auto accessible_bases_of(info target,
          info target,
          access_context from = access_context::current()) -> vector<info>;
  consteval auto accessible_nonstatic_data_members_of(
          info target,
          access_context from = access_context::current()) -> vector<info>;
  consteval auto accessible_static_data_members_of(
          info target,
          access_context from = access_context::current()) -> vector<info>;
  consteval auto accessible_subobjects_of(
          info target,
          access_context from = access_context::current()) -> vector<info>;

  // substitute
  template <reflection_range R = initializer_list<info>>
  consteval auto can_substitute(info templ, R&& args) -> bool;
  template <reflection_range R = initializer_list<info>>
  consteval auto substitute(info templ, R&& args) -> info;

  // reflect_invoke
  template <reflection_range R = initializer_list<info>>
  consteval auto reflect_invoke(info target, R&& args) -> info;
  template <reflection_range R1 = initializer_list<info>, reflection_range R2 = initializer_list<info>>
  consteval auto reflect_invoke(info target, R1&& tmpl_args, R2&& args) -> info;

  // reflect expression results
  template <typename T>
    consteval auto reflect_value(T value) -> info;
  template <typename T>
    consteval auto reflect_object(T& value) -> info;
  template <typename T>
    consteval auto reflect_function(T& value) -> info;

  // extract
  template <typename T>
    consteval auto extract(info) -> T;

  // other type predicates (see the wording)
  consteval auto is_public(info r) -> bool;
  consteval auto is_protected(info r) -> bool;
  consteval auto is_private(info r) -> bool;
  consteval auto is_virtual(info r) -> bool;
  consteval auto is_pure_virtual(info entity) -> bool;
  consteval auto is_override(info entity) -> bool;
  consteval auto is_final(info r) -> bool;
  consteval auto is_deleted(info entity) -> bool;
  consteval auto is_defaulted(info entity) -> bool;
  consteval auto is_explicit(info entity) -> bool;
  consteval auto is_noexcept(info entity) -> bool;
  consteval auto is_bit_field(info entity) -> bool;
  consteval auto is_enumerator(info entity) -> bool;
  consteval auto is_const(info r) -> bool;
  consteval auto is_volatile(info r) -> bool;
  consteval auto is_lvalue_reference_qualified(info r) -> bool;
  consteval auto is_rvalue_reference_qualified(info r) -> bool;
  consteval auto has_static_storage_duration(info r) -> bool;
  consteval auto has_thread_storage_duration(info r) -> bool;
  consteval auto has_automatic_storage_duration(info r) -> bool;
  consteval auto has_internal_linkage(info r) -> bool;
  consteval auto has_module_linkage(info r) -> bool;
  consteval auto has_external_linkage(info r) -> bool;
  consteval auto has_linkage(info r) -> bool;
  consteval auto is_class_member(info entity) -> bool;
  consteval auto is_namespace_member(info entity) -> bool;
  consteval auto is_nonstatic_data_member(info entity) -> bool;
  consteval auto is_static_member(info entity) -> bool;
  consteval auto is_base(info entity) -> bool;
  consteval auto is_data_member_spec(info r) -> bool;
  consteval auto is_namespace(info entity) -> bool;
  consteval auto is_function(info entity) -> bool;
  consteval auto is_variable(info entity) -> bool;
  consteval auto is_type(info entity) -> bool;
  consteval auto is_type_alias(info entity) -> bool;
  consteval auto is_namespace_alias(info entity) -> bool;
  consteval auto is_complete_type(info entity) -> bool;
  consteval auto is_template(info entity) -> bool;
  consteval auto is_function_template(info entity) -> bool;
  consteval auto is_variable_template(info entity) -> bool;
  consteval auto is_class_template(info entity) -> bool;
  consteval auto is_alias_template(info entity) -> bool;
  consteval auto is_conversion_function_template(info entity) -> bool;
  consteval auto is_operator_function_template(info entity) -> bool;
  consteval auto is_literal_operator_template(info entity) -> bool;
  consteval auto is_constructor_template(info entity) -> bool;
  consteval auto is_concept(info entity) -> bool;
  consteval auto is_structured_binding(info entity) -> bool;
  consteval auto is_value(info entity) -> bool;
  consteval auto is_object(info entity) -> bool;
  consteval auto has_template_arguments(info r) -> bool;
  consteval auto has_default_member_initializer(info r) -> bool;

  consteval auto is_special_member(info r) -> bool;
  consteval auto is_conversion_function(info r) -> bool;
  consteval auto is_operator_function(info r) -> bool;
  consteval auto is_literal_operator(info r) -> bool;
  consteval auto is_constructor(info r) -> bool;
  consteval auto is_default_constructor(info r) -> bool;
  consteval auto is_copy_constructor(info r) -> bool;
  consteval auto is_move_constructor(info r) -> bool;
  consteval auto is_assignment(info r) -> bool;
  consteval auto is_copy_assignment(info r) -> bool;
  consteval auto is_move_assignment(info r) -> bool;
  consteval auto is_destructor(info r) -> bool;
  consteval auto is_user_provided(info r) -> bool;

  // define_class
  struct data_member_options_t;
  consteval auto data_member_spec(info type_class,
                                  data_member_options_t options = {}) -> info;
  template <reflection_range R = initializer_list<info>>
  consteval auto define_class(info type_class, R&&) -> info;

  // define_static_string
  consteval auto define_static_string(string_view str) -> const char *;
  consteval auto define_static_string(u8string_view str) -> const char8_t *;

  // data layout
  struct member_offsets {
    size_t bytes;
    size_t bits;
    constexpr auto total_bits() const -> . double quote. double quote. double quote. double quote. size_t;
    auto operator<=>(member_offsets const&) const = default;
  };

  consteval auto offset_of(info entity) -> member_offsets;
  consteval auto size_of(info entity) -> size_t;
  consteval auto alignment_of(info entity) -> size_t;
  consteval auto bit_size_of(info entity) -> size_t;

}
        

First of all, the metafunctions may remind you of the type traits metafunctions. There’s a big difference. The type traits metafunctions are declared as constexpr, but the reflection metafunctions as consteval. This means the type traits metafunctions can run at compile time, but the reflection metafunctions must run at compile time. Consequently, the arguments must be constant expressions.

Now, let’s have a closer look

The reflection library has metafunctions for

  • Returns the name or location
  • Returns the reflection value from a type, object and value, template, and member
  • Returns the member access
  • Returns the reflection on the template arguments
  • Returns the result of a call expression
  • Returns the result of the evaluated expression
  • Extract in the value similar to the splicers

Furthermore, the reflection library has more than 50 compile time predicates. A compile time predicate is a callable which returns bool at compile time.

?


Modernes C++ Mentoring

Do you want to stay informed: Subscribe.

?

Additionally, there are metafunctions to define a class.

What’s next?

In my next post, I will apply the metafunctions.

Farhad Shiri

Lead Technical Architect

2 周

Rainer Grimm Why ? typename[:^char:] c = '*'; Python++ ??

回复

要查看或添加评论,请登录

Rainer Grimm的更多文章

  • Mentoring as a Key to Success

    Mentoring as a Key to Success

    I know that we are going through very challenging times. Saving is the top priority.

  • Reflection in C++26: Determine the Layout

    Reflection in C++26: Determine the Layout

    Thanks to reflection, you can determine the layout of types. My examples are based on the reflection proposal P2996R5.

    4 条评论
  • My ALS Journey (15/n): A typical Day

    My ALS Journey (15/n): A typical Day

    You may wonder how my day looks. Let me compare a day before ALS with a current day.

    3 条评论
  • Reflection in C++26: Metafunctions for Enums and Classes

    Reflection in C++26: Metafunctions for Enums and Classes

    Today, I continue my journey through reflection in C++26 and play with enums and classes. The names of the…

    2 条评论
  • Become a Professional C++ Developer

    Become a Professional C++ Developer

    Do you want to become a professional C++ developer? Here is your chance. Take my mentoring program "Fundamentals for…

  • Improve You Or Your Team

    Improve You Or Your Team

    Do you want to become a professional C++ developer? Here is your chance. Take one of my mentoring programs and try out…

  • Reflection in C++

    Reflection in C++

    After the search into the breadth starts today, the search into the depth: reflection. Reflection Reflection is the…

  • Embedded Programming with Modern C++

    Embedded Programming with Modern C++

    My most successful class is now available as mentoring. I have given this class around 100 times in the last few years.

  • An Overview of C++26: Concurrency

    An Overview of C++26: Concurrency

    Today, I will finish my overview of C++26 and write about concurrency. There are still two library features left before…

    1 条评论
  • Improve your Team

    Improve your Team

    Bring your team to the next level. Consider my mentoring programs.