blob: 033746a40349bb3a7ff4598667de82cdbbf59f54 [file] [log] [blame]
// <meta> -*- 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
// <http://www.gnu.org/licenses/>.
/** @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 <bits/version.h>
#if __glibcxx_reflection >= 202506L // C++ >= 26 && __cpp_impl_reflection
#include <array>
#include <initializer_list>
#include <optional>
#include <source_location>
#include <span>
#include <string>
#include <string_view>
#include <vector>
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<ranges::input_range _Rg>
static consteval u8string_view _S_exception_cvt_to_utf8(_Rg&&);
template<ranges::input_range _Rg>
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<info> template_arguments_of(info);
consteval vector<info> 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<info> members_of(info, access_context);
consteval vector<info> bases_of(info, access_context);
consteval vector<info> static_data_members_of(info, access_context);
consteval vector<info> nonstatic_data_members_of(info, access_context);
consteval vector<info> subobjects_of(info, access_context);
consteval vector<info> 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<class _Tp>
consteval _Tp extract(info);
// [meta.reflection.substitute], reflection substitution
template<class _Rg>
concept reflection_range = ranges::input_range<_Rg>
&& same_as<ranges::range_value_t<_Rg>, info>
&& same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, info>;
template<reflection_range _Rg = initializer_list<info>>
consteval bool can_substitute(info, _Rg&&);
template<reflection_range _Rg = initializer_list<info>>
consteval info substitute(info, _Rg&&);
// [meta.reflection.result], expression result reflection
template<typename _Tp>
requires (is_copy_constructible_v<_Tp>)
consteval info reflect_constant(_Tp);
template<typename _Tp>
requires (!is_function_v<remove_reference_t<_Tp>>)
consteval info reflect_object(_Tp&);
template<typename _Tp>
requires (is_function_v<remove_reference_t<_Tp>>)
consteval info reflect_function(_Tp&);
// [meta.reflection.array], promoting to static storage arrays
template<ranges::input_range _Rg>
consteval info reflect_constant_string(_Rg&&);
template<ranges::input_range _Rg>
consteval info reflect_constant_array(_Rg&&);
// [meta.reflection.define.aggregate], class definition generation
struct data_member_options {
struct _Name {
template<class _Tp>
requires constructible_from<u8string, _Tp>
consteval _Name(_Tp&& __n) : _M_is_u8(true), _M_u8s((_Tp&&) __n) {}
template<class _Tp>
requires constructible_from<string, _Tp>
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<int> alignment;
optional<int> bit_width;
bool no_unique_address = false;
};
consteval info data_member_spec(info, data_member_options);
consteval bool is_data_member_spec(info);
template<reflection_range _Rg = initializer_list<info>>
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<reflection_range _Rg = initializer_list<info>>
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<reflection_range _Rg = initializer_list<info>>
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<reflection_range _Rg = initializer_list<info>>
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<reflection_range _Rg = initializer_list<info>>
consteval bool is_invocable_type(info, _Rg&&);
template<reflection_range _Rg = initializer_list<info>>
consteval bool is_invocable_r_type(info, info, _Rg&&);
template<reflection_range _Rg = initializer_list<info>>
consteval bool is_nothrow_invocable_type(info, _Rg&&);
template<reflection_range _Rg = initializer_list<info>>
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<reflection_range _Rg = initializer_list<info>>
consteval info common_type(_Rg&&);
template<reflection_range _Rg = initializer_list<info>>
consteval info common_reference(_Rg&&);
consteval info underlying_type(info);
template<reflection_range _Rg = initializer_list<info>>
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<info> annotations_of(info);
consteval vector<info> 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<ranges::input_range _Rg>
consteval const ranges::range_value_t<_Rg>*
define_static_string(_Rg&& __r)
{
auto __str = meta::reflect_constant_string(__r);
return meta::extract<const ranges::range_value_t<_Rg>*>(__str);
}
template<ranges::input_range _Rg>
consteval span<const ranges::range_value_t<_Rg>>
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<const _Tp>(meta::extract<const _Tp*>(__array),
meta::extent(__type, 0U));
else
return span<const _Tp>();
}
template<class _Tp>
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<const _Up&>(__cst));
}
else
return std::define_static_array(span<const _Up>(std::addressof(__t),
1)).data();
}
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++26
#endif // _GLIBCXX_META