// -*- C++ -*- // Copyright (C) 2025-2026 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file include/meta * This is a Standard C++ Library header. */ #ifndef _GLIBCXX_META #define _GLIBCXX_META 1 #ifdef _GLIBCXX_SYSHDR #pragma GCC system_header #endif #define __glibcxx_want_reflection #include #if __glibcxx_reflection >= 202506L // C++ >= 26 && __cpp_impl_reflection #include #include #include #include #include #include #include #include namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __has_builtin(__builtin_is_string_literal) // [meta.string.literal], checking string literals consteval bool is_string_literal(const char* __p) { return __builtin_is_string_literal(__p); } consteval bool is_string_literal(const wchar_t* __p) { return __builtin_is_string_literal(__p); } #ifdef _GLIBCXX_USE_CHAR8_T consteval bool is_string_literal(const char8_t* __p) { return __builtin_is_string_literal(__p); } #endif consteval bool is_string_literal(const char16_t* __p) { return __builtin_is_string_literal(__p); } consteval bool is_string_literal(const char32_t* __p) { return __builtin_is_string_literal(__p); } #endif namespace meta { using info = decltype(^^int); // [meta.reflection.exception], class exception class exception : public std::exception { private: string _M_what; u8string _M_u8what; info _M_from; source_location _M_where; public: consteval exception(u8string_view __what, info __from, source_location __where = source_location::current()) noexcept : _M_what{_S_exception_cvt_from_utf8(__what)}, _M_u8what{__what}, _M_from{__from}, _M_where{__where} {} consteval exception(string_view __what, info __from, source_location __where = source_location::current()) noexcept : _M_what{__what}, _M_u8what{_S_exception_cvt_to_utf8(__what)}, _M_from{__from}, _M_where{__where} {} consteval exception(const exception&) = default; consteval exception(exception&&) = default; consteval exception& operator=(const exception&) = default; consteval exception& operator=(exception&&) = default; consteval const char* what() const noexcept override { // If u8string is not empty and string is empty, conversion // from UTF-8 to ordinary literal encoding failed. // In that case what() should be non-constant. if (_M_what.size() == 0 && _M_u8what.size() != 0) asm(""); return _M_what.c_str(); } consteval u8string_view u8what() const noexcept { return _M_u8what; } consteval info from() const noexcept { return _M_from; } consteval source_location where() const noexcept { return _M_where; } private: // Helper special template metafunctions to convert from UTF-8 to // ordinary literal encoding and vice versa. On conversion failure // they just return an empty {,u8}string_view. template static consteval u8string_view _S_exception_cvt_to_utf8(_Rg&&); template static consteval string_view _S_exception_cvt_from_utf8(_Rg&&); }; // [meta.reflection.operators], operator representations enum class operators { op_new = 1, op_delete, op_array_new, op_array_delete, op_co_await, op_parentheses, op_square_brackets, op_arrow, op_arrow_star, op_tilde, op_exclamation, op_plus, op_minus, op_star, op_slash, op_percent, op_caret, op_ampersand, op_equals, op_pipe, op_plus_equals, op_minus_equals, op_star_equals, op_slash_equals, op_percent_equals, op_caret_equals, op_ampersand_equals, op_pipe_equals, op_equals_equals, op_exclamation_equals, op_less, op_greater, op_less_equals, op_greater_equals, op_spaceship, op_ampersand_ampersand, op_pipe_pipe, op_less_less, op_greater_greater, op_less_less_equals, op_greater_greater_equals, op_plus_plus, op_minus_minus, op_comma }; using enum operators; consteval operators operator_of(info); consteval string_view symbol_of(operators); consteval u8string_view u8symbol_of(operators); // [meta.reflection.names], reflection names and locations consteval bool has_identifier(info); consteval string_view identifier_of(info); consteval u8string_view u8identifier_of(info); consteval string_view display_string_of(info); consteval u8string_view u8display_string_of(info); consteval source_location source_location_of(info); // [meta.reflection.queries], reflection queries consteval info type_of(info); consteval info object_of(info); consteval info constant_of(info); consteval bool is_public(info); consteval bool is_protected(info); consteval bool is_private(info); consteval bool is_virtual(info); consteval bool is_pure_virtual(info); consteval bool is_override(info); consteval bool is_final(info); consteval bool is_deleted(info); consteval bool is_defaulted(info); consteval bool is_user_provided(info); consteval bool is_user_declared(info); consteval bool is_explicit(info); consteval bool is_noexcept(info); consteval bool is_bit_field(info); consteval bool is_enumerator(info); consteval bool is_annotation(info); consteval bool is_const(info); consteval bool is_volatile(info); consteval bool is_mutable_member(info); consteval bool is_lvalue_reference_qualified(info); consteval bool is_rvalue_reference_qualified(info); consteval bool has_static_storage_duration(info); consteval bool has_thread_storage_duration(info); consteval bool has_automatic_storage_duration(info); consteval bool has_internal_linkage(info); consteval bool has_module_linkage(info); consteval bool has_external_linkage(info); consteval bool has_c_language_linkage(info); consteval bool has_linkage(info); consteval bool is_complete_type(info); consteval bool is_enumerable_type(info); consteval bool is_variable(info); consteval bool is_type(info); consteval bool is_namespace(info); consteval bool is_type_alias(info); consteval bool is_namespace_alias(info); consteval bool is_function(info); consteval bool is_conversion_function(info); consteval bool is_operator_function(info); consteval bool is_literal_operator(info); consteval bool is_special_member_function(info); consteval bool is_constructor(info); consteval bool is_default_constructor(info); consteval bool is_copy_constructor(info); consteval bool is_move_constructor(info); consteval bool is_assignment(info); consteval bool is_copy_assignment(info); consteval bool is_move_assignment(info); consteval bool is_destructor(info); consteval bool is_function_parameter(info); consteval bool is_explicit_object_parameter(info); consteval bool has_default_argument(info); consteval bool has_ellipsis_parameter(info); consteval bool is_template(info); consteval bool is_function_template(info); consteval bool is_variable_template(info); consteval bool is_class_template(info); consteval bool is_alias_template(info); consteval bool is_conversion_function_template(info); consteval bool is_operator_function_template(info); consteval bool is_literal_operator_template(info); consteval bool is_constructor_template(info); consteval bool is_concept(info); consteval bool is_value(info); consteval bool is_object(info); consteval bool is_structured_binding(info); consteval bool is_class_member(info); consteval bool is_namespace_member(info); consteval bool is_nonstatic_data_member(info); consteval bool is_static_member(info); consteval bool is_base(info); consteval bool has_default_member_initializer(info); consteval bool has_parent(info); consteval info parent_of(info); consteval info dealias(info); consteval bool has_template_arguments(info); consteval info template_of(info); consteval vector template_arguments_of(info); consteval vector parameters_of(info); consteval info variable_of(info); consteval info return_type_of(info); // [meta.reflection.access.context], access control context struct access_context { private: consteval access_context(info __scope, info __designating_class) noexcept : _M_scope{__scope}, _M_designating_class{__designating_class} { } public: access_context() = delete; consteval access_context(const access_context &) = default; consteval access_context(access_context &&) = default; consteval info scope() const { return _M_scope; } consteval info designating_class() const { return _M_designating_class; } static consteval access_context current() noexcept; static consteval access_context unprivileged() noexcept { return access_context { ^^::, info {} }; } static consteval access_context unchecked() noexcept { return access_context { info {}, info {} }; } consteval access_context via(info) const; info _M_scope; info _M_designating_class; }; // [meta.reflection.access.queries], member accessibility queries consteval bool is_accessible(info, access_context); consteval bool has_inaccessible_nonstatic_data_members(info, access_context); consteval bool has_inaccessible_bases(info, access_context); consteval bool has_inaccessible_subobjects(info, access_context); // [meta.reflection.member.queries], reflection member queries consteval vector members_of(info, access_context); consteval vector bases_of(info, access_context); consteval vector static_data_members_of(info, access_context); consteval vector nonstatic_data_members_of(info, access_context); consteval vector subobjects_of(info, access_context); consteval vector enumerators_of(info); // [meta.reflection.layout], reflection layout queries struct member_offset { ptrdiff_t bytes; ptrdiff_t bits; constexpr ptrdiff_t total_bits() const { return bytes * __CHAR_BIT__ + bits; } auto operator<=>(const member_offset&) const = default; }; consteval member_offset offset_of(info); consteval size_t size_of(info); consteval size_t alignment_of(info); consteval size_t bit_size_of(info); // [meta.reflection.extract], value extraction template consteval _Tp extract(info); // [meta.reflection.substitute], reflection substitution template concept reflection_range = ranges::input_range<_Rg> && same_as, info> && same_as>, info>; template> consteval bool can_substitute(info, _Rg&&); template> consteval info substitute(info, _Rg&&); // [meta.reflection.result], expression result reflection template requires (is_copy_constructible_v<_Tp>) consteval info reflect_constant(_Tp); template requires (!is_function_v>) consteval info reflect_object(_Tp&); template requires (is_function_v>) consteval info reflect_function(_Tp&); // [meta.reflection.array], promoting to static storage arrays template consteval info reflect_constant_string(_Rg&&); template consteval info reflect_constant_array(_Rg&&); // [meta.reflection.define.aggregate], class definition generation struct data_member_options { struct _Name { template requires constructible_from consteval _Name(_Tp&& __n) : _M_is_u8(true), _M_u8s((_Tp&&) __n) {} template requires constructible_from consteval _Name(_Tp&& __n) : _M_is_u8(false), _M_s((_Tp&&) __n) {} private: bool _M_is_u8; u8string _M_u8s; string _M_s; info _M_unused = {}; }; optional<_Name> name; optional alignment; optional bit_width; bool no_unique_address = false; }; consteval info data_member_spec(info, data_member_options); consteval bool is_data_member_spec(info); template> consteval info define_aggregate(info, _Rg&&); // associated with [meta.unary.cat], primary type categories consteval bool is_void_type(info); consteval bool is_null_pointer_type(info); consteval bool is_integral_type(info); consteval bool is_floating_point_type(info); consteval bool is_array_type(info); consteval bool is_pointer_type(info); consteval bool is_lvalue_reference_type(info); consteval bool is_rvalue_reference_type(info); consteval bool is_member_object_pointer_type(info); consteval bool is_member_function_pointer_type(info); consteval bool is_enum_type(info); consteval bool is_union_type(info); consteval bool is_class_type(info); consteval bool is_function_type(info); consteval bool is_reflection_type(info); // associated with [meta.unary.comp], composite type categories consteval bool is_reference_type(info); consteval bool is_arithmetic_type(info); consteval bool is_fundamental_type(info); consteval bool is_object_type(info); consteval bool is_scalar_type(info); consteval bool is_compound_type(info); consteval bool is_member_pointer_type(info); // associated with [meta.unary.prop], type properties consteval bool is_const_type(info); consteval bool is_volatile_type(info); consteval bool is_trivially_copyable_type(info); consteval bool is_standard_layout_type(info); consteval bool is_empty_type(info); consteval bool is_polymorphic_type(info); consteval bool is_abstract_type(info); consteval bool is_final_type(info); consteval bool is_aggregate_type(info); consteval bool is_consteval_only_type(info); consteval bool is_signed_type(info); consteval bool is_unsigned_type(info); consteval bool is_bounded_array_type(info); consteval bool is_unbounded_array_type(info); consteval bool is_scoped_enum_type(info); template> consteval bool is_constructible_type(info, _Rg&&); consteval bool is_default_constructible_type(info); consteval bool is_copy_constructible_type(info); consteval bool is_move_constructible_type(info); consteval bool is_assignable_type(info, info); consteval bool is_copy_assignable_type(info); consteval bool is_move_assignable_type(info); consteval bool is_swappable_with_type(info, info); consteval bool is_swappable_type(info); consteval bool is_destructible_type(info); template> consteval bool is_trivially_constructible_type(info, _Rg&&); consteval bool is_trivially_default_constructible_type(info); consteval bool is_trivially_copy_constructible_type(info); consteval bool is_trivially_move_constructible_type(info); consteval bool is_trivially_assignable_type(info, info); consteval bool is_trivially_copy_assignable_type(info); consteval bool is_trivially_move_assignable_type(info); consteval bool is_trivially_destructible_type(info); template> consteval bool is_nothrow_constructible_type(info, _Rg&&); consteval bool is_nothrow_default_constructible_type(info); consteval bool is_nothrow_copy_constructible_type(info); consteval bool is_nothrow_move_constructible_type(info); consteval bool is_nothrow_assignable_type(info, info); consteval bool is_nothrow_copy_assignable_type(info); consteval bool is_nothrow_move_assignable_type(info); consteval bool is_nothrow_swappable_with_type(info, info); consteval bool is_nothrow_swappable_type(info); consteval bool is_nothrow_destructible_type(info); consteval bool is_implicit_lifetime_type(info); consteval bool has_virtual_destructor(info); consteval bool has_unique_object_representations(info); consteval bool reference_constructs_from_temporary(info, info); consteval bool reference_converts_from_temporary(info, info); // associated with [meta.unary.prop.query], type property queries consteval size_t rank(info); consteval size_t extent(info, unsigned = 0); // associated with [meta.rel], type relations consteval bool is_same_type(info, info); consteval bool is_base_of_type(info, info); consteval bool is_virtual_base_of_type(info, info); consteval bool is_convertible_type(info, info); consteval bool is_nothrow_convertible_type(info, info); consteval bool is_layout_compatible_type(info, info); consteval bool is_pointer_interconvertible_base_of_type(info, info); template> consteval bool is_invocable_type(info, _Rg&&); template> consteval bool is_invocable_r_type(info, info, _Rg&&); template> consteval bool is_nothrow_invocable_type(info, _Rg&&); template> consteval bool is_nothrow_invocable_r_type(info, info, _Rg&&); // associated with [meta.trans.cv], const-volatile modifications consteval info remove_const(info); consteval info remove_volatile(info); consteval info remove_cv(info); consteval info add_const(info); consteval info add_volatile(info); consteval info add_cv(info); // associated with [meta.trans.ref], reference modifications consteval info remove_reference(info); consteval info add_lvalue_reference(info); consteval info add_rvalue_reference(info); // associated with [meta.trans.sign], sign modifications consteval info make_signed(info); consteval info make_unsigned(info); // associated with [meta.trans.arr], array modifications consteval info remove_extent(info); consteval info remove_all_extents(info); // associated with [meta.trans.ptr], pointer modifications consteval info remove_pointer(info); consteval info add_pointer(info); // associated with [meta.trans.other], other transformations consteval info remove_cvref(info); consteval info decay(info); template> consteval info common_type(_Rg&&); template> consteval info common_reference(_Rg&&); consteval info underlying_type(info); template> consteval info invoke_result(info, _Rg&&); consteval info unwrap_reference(info); consteval info unwrap_ref_decay(info); consteval size_t tuple_size(info); consteval info tuple_element(size_t, info); consteval size_t variant_size(info); consteval info variant_alternative(size_t, info); consteval strong_ordering type_order(info, info); // [meta.reflection.annotation], annotation reflection consteval vector annotations_of(info); consteval vector annotations_of_with_type(info, info); consteval access_context access_context::via(info __cls) const { if (__cls != info {} && (!std::meta::is_class_type(__cls) || !std::meta::is_complete_type(__cls))) { #if __cpp_exceptions throw std::meta::exception(u8"via argument other than null " "or complete class type reflection", ^^access_context::via); #else asm(""); return *this; #endif } return access_context { _M_scope, __cls }; } } // namespace meta // [meta.define.static], promoting to static storage strings template consteval const ranges::range_value_t<_Rg>* define_static_string(_Rg&& __r) { auto __str = meta::reflect_constant_string(__r); return meta::extract*>(__str); } template consteval span> define_static_array(_Rg&& __r) { using _Tp = ranges::range_value_t<_Rg>; auto __array = meta::reflect_constant_array(__r); auto __type = meta::type_of(__array); if (meta::is_array_type(__type)) return span(meta::extract(__array), meta::extent(__type, 0U)); else return span(); } template consteval const remove_cvref_t<_Tp>* define_static_object(_Tp&& __t) { using _Up = remove_cvref_t<_Tp>; if constexpr (meta::is_class_type(^^_Up)) { auto __cst = meta::reflect_constant(std::forward<_Tp>(__t)); return std::addressof(meta::extract(__cst)); } else return std::define_static_array(span(std::addressof(__t), 1)).data(); } _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // C++26 #endif // _GLIBCXX_META