https://gcc.gnu.org/g:1e38d1a4f42973cdbf49d4347d9bb0baac061851

commit r16-8448-g1e38d1a4f42973cdbf49d4347d9bb0baac061851
Author: Jakub Jelinek <[email protected]>
Date:   Fri Apr 3 20:52:33 2026 +0200

    c++, libstdc++: Implement P3856R8 - New reflection metafunction - 
is_structural_type
    
    This patch attempts to implement this paper, adds a new trait, builtin trait
    and metafunction.
    
    2026-04-03  Jakub Jelinek  <[email protected]>
    
    gcc/cp/
            * cp-trait.def (__builtin_is_structural): New trait.
            * semantics.cc (trait_expr_value): Handle CPTK_IS_STRUCTURAL.
            (finish_trait_expr): Likewise.
            * constraint.cc (diagnose_trait_expr): Likewise.
            * metafns.gperf (enum metafn_code): Add METAFN_IS_STRUCTURAL_TYPE.
            (is_structural_type): New metafn.
            * metafns.h: Regenerate.
            * reflect.cc (eval_is_structural_type): New function.
            (process_metafunction): Handle METAFN_IS_STRUCTURAL_TYPE.
    gcc/testsuite/
            * g++.dg/reflect/type_trait14.C: New test.
            * g++.dg/reflect/eh1.C: Add test for is_structural_type.
            * g++.dg/reflect/eh2.C: Likewise.
    libstdc++-v3/
            * include/bits/version.def (is_structural): New.
            * include/bits/version.h: Regenerate.
            * include/std/type_traits (__glibcxx_want_is_structural): Define.
            (std::is_structural): New type trait.
            (std::is_structural_v): New type trait variable template.
            * include/std/meta (std::meta::is_structural_type): New declaration.
            * src/c++23/std.cc.in: Export std::is_structural, 
std::is_structural_v
            and std::meta::is_structural_type.
            * 
testsuite/20_util/is_structural/requirements/explicit_instantiation.cc: New 
test.
            * testsuite/20_util/is_structural/requirements/typedefs.cc: New 
test.
            * testsuite/20_util/is_structural/value.cc: New test.
            * testsuite/20_util/variable_templates_for_traits.cc: Test
            is_structural_v.
    
    Reviewed-by: Jason Merrill <[email protected]>
    Reviewed-by: Jonathan Wakely <[email protected]>

Diff:
---
 gcc/cp/constraint.cc                               |   4 +
 gcc/cp/cp-trait.def                                |   1 +
 gcc/cp/metafns.gperf                               |   2 +
 gcc/cp/metafns.h                                   | 563 +++++++++++----------
 gcc/cp/reflect.cc                                  |  10 +
 gcc/cp/semantics.cc                                |   4 +
 gcc/testsuite/g++.dg/reflect/eh1.C                 |   4 +
 gcc/testsuite/g++.dg/reflect/eh2.C                 |   1 +
 gcc/testsuite/g++.dg/reflect/type_trait14.C        |  61 +++
 libstdc++-v3/include/bits/version.def              |   9 +
 libstdc++-v3/include/bits/version.h                |  10 +
 libstdc++-v3/include/std/meta                      |   3 +
 libstdc++-v3/include/std/type_traits               |  18 +
 libstdc++-v3/src/c++23/std.cc.in                   |   7 +
 .../requirements/explicit_instantiation.cc         |  12 +
 .../20_util/is_structural/requirements/typedefs.cc |  16 +
 .../testsuite/20_util/is_structural/value.cc       |  51 ++
 .../20_util/variable_templates_for_traits.cc       |   5 +
 18 files changed, 501 insertions(+), 280 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 4d667ced3429..0e0bcb2c90fc 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3357,6 +3357,10 @@ diagnose_trait_expr (location_t loc, tree expr, tree 
args)
     case CPTK_IS_CONSTEVAL_ONLY:
       inform (decl_loc, "%qT is not consteval-only", t1);
       break;
+    case CPTK_IS_STRUCTURAL:
+      inform (decl_loc, "%qT is not a structural type", t1);
+      structural_type_p (t1, /*explain=*/true);
+      break;
     case CPTK_RANK:
       inform (loc, "%qT cannot yield a rank", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 395cadc5767d..f1b40f2a6d87 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -98,6 +98,7 @@ DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_SAME, "__is_same", 2)
 DEFTRAIT_EXPR (IS_SCOPED_ENUM, "__is_scoped_enum", 1)
 DEFTRAIT_EXPR (IS_STD_LAYOUT, "__is_standard_layout", 1)
+DEFTRAIT_EXPR (IS_STRUCTURAL, "__builtin_is_structural", 1)
 DEFTRAIT_EXPR (IS_TRIVIAL, "__is_trivial", 1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
diff --git a/gcc/cp/metafns.gperf b/gcc/cp/metafns.gperf
index 0e919687c605..89e31866b03b 100644
--- a/gcc/cp/metafns.gperf
+++ b/gcc/cp/metafns.gperf
@@ -175,6 +175,7 @@ enum metafn_code {
   METAFN_IS_FINAL_TYPE,
   METAFN_IS_AGGREGATE_TYPE,
   METAFN_IS_CONSTEVAL_ONLY_TYPE,
+  METAFN_IS_STRUCTURAL_TYPE,
   METAFN_IS_SIGNED_TYPE,
   METAFN_IS_UNSIGNED_TYPE,
   METAFN_IS_BOUNDED_ARRAY_TYPE,
@@ -615,6 +616,7 @@ is_abstract_type, METAFN_IS_ABSTRACT_TYPE, 
METAFN_KIND_BOOL_TINFO,
 is_final_type, METAFN_IS_FINAL_TYPE, METAFN_KIND_BOOL_TINFO,
 is_aggregate_type, METAFN_IS_AGGREGATE_TYPE, METAFN_KIND_BOOL_TINFO,
 is_consteval_only_type, METAFN_IS_CONSTEVAL_ONLY_TYPE, METAFN_KIND_BOOL_TINFO,
+is_structural_type, METAFN_IS_STRUCTURAL_TYPE, METAFN_KIND_BOOL_TINFO,
 is_signed_type, METAFN_IS_SIGNED_TYPE, METAFN_KIND_BOOL_TINFO,
 is_unsigned_type, METAFN_IS_UNSIGNED_TYPE, METAFN_KIND_BOOL_TINFO,
 is_bounded_array_type, METAFN_IS_BOUNDED_ARRAY_TYPE, METAFN_KIND_BOOL_TINFO,
diff --git a/gcc/cp/metafns.h b/gcc/cp/metafns.h
index 611e0587f437..f47545c48db5 100644
--- a/gcc/cp/metafns.h
+++ b/gcc/cp/metafns.h
@@ -203,6 +203,7 @@ enum metafn_code {
   METAFN_IS_FINAL_TYPE,
   METAFN_IS_AGGREGATE_TYPE,
   METAFN_IS_CONSTEVAL_ONLY_TYPE,
+  METAFN_IS_STRUCTURAL_TYPE,
   METAFN_IS_SIGNED_TYPE,
   METAFN_IS_UNSIGNED_TYPE,
   METAFN_IS_BOUNDED_ARRAY_TYPE,
@@ -477,7 +478,7 @@ enum metafn_kind {
     = (METAFN_KIND_ARGS_INPUT_RANGE << METAFN_KIND_SHIFT)
       | METAFN_KIND_RET_U8STRING_VIEW
 };
-#line 453 "metafns.gperf"
+#line 454 "metafns.gperf"
 struct metafn_info
 {
   /* A name within "std::meta::" (or "std::meta::access_context::").  */
@@ -588,7 +589,7 @@ metafn_lookup::find (const char *str, size_t len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 237,
+      TOTAL_KEYWORDS = 238,
       MIN_WORD_LENGTH = 4,
       MAX_WORD_LENGTH = 40,
       MIN_HASH_VALUE = 39,
@@ -601,479 +602,481 @@ metafn_lookup::find (const char *str, size_t len)
 #endif
   static const struct metafn_info wordlist[] =
     {
-#line 656 "metafns.gperf"
+#line 658 "metafns.gperf"
       {"rank", METAFN_RANK, METAFN_KIND_SIZE_T_TINFO,},
-#line 586 "metafns.gperf"
+#line 587 "metafns.gperf"
       {"is_void_type", METAFN_IS_VOID_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 591 "metafns.gperf"
+#line 592 "metafns.gperf"
       {"is_pointer_type", METAFN_IS_POINTER_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 494 "metafns.gperf"
+#line 495 "metafns.gperf"
       {"is_volatile", METAFN_IS_VOLATILE, METAFN_KIND_BOOL_INFO,},
-#line 540 "metafns.gperf"
+#line 541 "metafns.gperf"
       {"is_value", METAFN_IS_VALUE, METAFN_KIND_BOOL_INFO,},
-#line 547 "metafns.gperf"
+#line 548 "metafns.gperf"
       {"is_base", METAFN_IS_BASE, METAFN_KIND_BOOL_INFO,},
-#line 479 "metafns.gperf"
+#line 480 "metafns.gperf"
       {"is_private", METAFN_IS_PRIVATE, METAFN_KIND_BOOL_INFO,},
-#line 508 "metafns.gperf"
+#line 509 "metafns.gperf"
       {"is_variable", METAFN_IS_VARIABLE, METAFN_KIND_BOOL_INFO,},
-#line 662 "metafns.gperf"
+#line 664 "metafns.gperf"
       {"is_nothrow_convertible_type", METAFN_IS_NOTHROW_CONVERTIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 641 "metafns.gperf"
+#line 643 "metafns.gperf"
       {"is_nothrow_constructible_type", METAFN_IS_NOTHROW_CONSTRUCTIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO_REFLECTION_RANGET,},
-#line 667 "metafns.gperf"
+#line 669 "metafns.gperf"
       {"is_nothrow_invocable_type", METAFN_IS_NOTHROW_INVOCABLE_TYPE, 
METAFN_KIND_BOOL_TINFO_REFLECTION_RANGET,},
-#line 646 "metafns.gperf"
+#line 648 "metafns.gperf"
       {"is_nothrow_copy_assignable_type", 
METAFN_IS_NOTHROW_COPY_ASSIGNABLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 668 "metafns.gperf"
+#line 670 "metafns.gperf"
       {"is_nothrow_invocable_r_type", METAFN_IS_NOTHROW_INVOCABLE_R_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO_REFLECTION_RANGET,},
-#line 643 "metafns.gperf"
+#line 645 "metafns.gperf"
       {"is_nothrow_copy_constructible_type", 
METAFN_IS_NOTHROW_COPY_CONSTRUCTIBLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 659 "metafns.gperf"
+#line 661 "metafns.gperf"
       {"is_base_of_type", METAFN_IS_BASE_OF_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 647 "metafns.gperf"
+#line 649 "metafns.gperf"
       {"is_nothrow_move_assignable_type", 
METAFN_IS_NOTHROW_MOVE_ASSIGNABLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 658 "metafns.gperf"
+#line 660 "metafns.gperf"
       {"is_same_type", METAFN_IS_SAME_TYPE, METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 644 "metafns.gperf"
+#line 646 "metafns.gperf"
       {"is_nothrow_move_constructible_type", 
METAFN_IS_NOTHROW_MOVE_CONSTRUCTIBLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 532 "metafns.gperf"
+#line 533 "metafns.gperf"
       {"is_variable_template", METAFN_IS_VARIABLE_TEMPLATE, 
METAFN_KIND_BOOL_INFO,},
-#line 587 "metafns.gperf"
+#line 588 "metafns.gperf"
       {"is_null_pointer_type", METAFN_IS_NULL_POINTER_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 645 "metafns.gperf"
+#line 647 "metafns.gperf"
       {"is_nothrow_assignable_type", METAFN_IS_NOTHROW_ASSIGNABLE_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 650 "metafns.gperf"
+#line 652 "metafns.gperf"
       {"is_nothrow_destructible_type", METAFN_IS_NOTHROW_DESTRUCTIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 477 "metafns.gperf"
+#line 478 "metafns.gperf"
       {"is_public", METAFN_IS_PUBLIC, METAFN_KIND_BOOL_INFO,},
-#line 489 "metafns.gperf"
+#line 490 "metafns.gperf"
       {"is_noexcept", METAFN_IS_NOEXCEPT, METAFN_KIND_BOOL_INFO,},
-#line 575 "metafns.gperf"
+#line 576 "metafns.gperf"
       {"extract", METAFN_EXTRACT, METAFN_KIND_TEMPLATE_PARM_INFO,},
-#line 695 "metafns.gperf"
+#line 697 "metafns.gperf"
       {"variant_alternative", METAFN_VARIANT_ALTERNATIVE, 
METAFN_KIND_INFO_SIZE_T_TINFO,},
-#line 613 "metafns.gperf"
+#line 614 "metafns.gperf"
       {"is_polymorphic_type", METAFN_IS_POLYMORPHIC_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 513 "metafns.gperf"
+#line 514 "metafns.gperf"
       {"is_function", METAFN_IS_FUNCTION, METAFN_KIND_BOOL_INFO,},
-#line 510 "metafns.gperf"
+#line 511 "metafns.gperf"
       {"is_namespace", METAFN_IS_NAMESPACE, METAFN_KIND_BOOL_INFO,},
-#line 466 "metafns.gperf"
+#line 467 "metafns.gperf"
       {"symbol_of", METAFN_SYMBOL_OF, METAFN_KIND_STRING_VIEW_OPERATORS,},
-#line 664 "metafns.gperf"
+#line 666 "metafns.gperf"
       {"is_pointer_interconvertible_base_of_type", 
METAFN_IS_POINTER_INTERCONVERTIBLE_BASE_OF_TYPE, METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 620 "metafns.gperf"
+#line 622 "metafns.gperf"
       {"is_bounded_array_type", METAFN_IS_BOUNDED_ARRAY_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 694 "metafns.gperf"
+#line 696 "metafns.gperf"
       {"variant_size", METAFN_VARIANT_SIZE, METAFN_KIND_SIZE_T_TINFO,},
-#line 493 "metafns.gperf"
+#line 494 "metafns.gperf"
       {"is_const", METAFN_IS_CONST, METAFN_KIND_BOOL_INFO,},
-#line 539 "metafns.gperf"
+#line 540 "metafns.gperf"
       {"is_concept", METAFN_IS_CONCEPT, METAFN_KIND_BOOL_INFO,},
-#line 509 "metafns.gperf"
+#line 510 "metafns.gperf"
       {"is_type", METAFN_IS_TYPE, METAFN_KIND_BOOL_INFO,},
-#line 566 "metafns.gperf"
+#line 567 "metafns.gperf"
       {"bases_of", METAFN_BASES_OF, 
METAFN_KIND_VECTOR_INFO_INFO_ACCESS_CONTEXT,},
-#line 531 "metafns.gperf"
+#line 532 "metafns.gperf"
       {"is_function_template", METAFN_IS_FUNCTION_TEMPLATE, 
METAFN_KIND_BOOL_INFO,},
-#line 514 "metafns.gperf"
+#line 515 "metafns.gperf"
       {"is_conversion_function", METAFN_IS_CONVERSION_FUNCTION, 
METAFN_KIND_BOOL_INFO,},
-#line 628 "metafns.gperf"
+#line 630 "metafns.gperf"
       {"is_copy_assignable_type", METAFN_IS_COPY_ASSIGNABLE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 661 "metafns.gperf"
+#line 663 "metafns.gperf"
       {"is_convertible_type", METAFN_IS_CONVERTIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 651 "metafns.gperf"
+#line 653 "metafns.gperf"
       {"is_implicit_lifetime_type", METAFN_IS_IMPLICIT_LIFETIME_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 696 "metafns.gperf"
+#line 698 "metafns.gperf"
       {"type_order", METAFN_TYPE_ORDER, 
METAFN_KIND_STRONG_ORDERING_TINFO_TINFO,},
-#line 530 "metafns.gperf"
+#line 531 "metafns.gperf"
       {"is_template", METAFN_IS_TEMPLATE, METAFN_KIND_BOOL_INFO,},
-#line 642 "metafns.gperf"
+#line 644 "metafns.gperf"
       {"is_nothrow_default_constructible_type", 
METAFN_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 576 "metafns.gperf"
+#line 577 "metafns.gperf"
       {"can_substitute", METAFN_CAN_SUBSTITUTE, 
METAFN_KIND_INFO_INFO_REFLECTION_RANGE,},
-#line 535 "metafns.gperf"
+#line 536 "metafns.gperf"
       {"is_conversion_function_template", 
METAFN_IS_CONVERSION_FUNCTION_TEMPLATE, METAFN_KIND_BOOL_INFO,},
-#line 523 "metafns.gperf"
+#line 524 "metafns.gperf"
       {"is_copy_assignment", METAFN_IS_COPY_ASSIGNMENT, 
METAFN_KIND_BOOL_INFO,},
-#line 625 "metafns.gperf"
+#line 627 "metafns.gperf"
       {"is_copy_constructible_type", METAFN_IS_COPY_CONSTRUCTIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 572 "metafns.gperf"
+#line 573 "metafns.gperf"
       {"size_of", METAFN_SIZE_OF, METAFN_KIND_SIZE_T_INFO,},
-#line 474 "metafns.gperf"
+#line 475 "metafns.gperf"
       {"type_of", METAFN_TYPE_OF, METAFN_KIND_INFO_INFO,},
-#line 511 "metafns.gperf"
+#line 512 "metafns.gperf"
       {"is_type_alias", METAFN_IS_TYPE_ALIAS, METAFN_KIND_BOOL_INFO,},
-#line 623 "metafns.gperf"
+#line 625 "metafns.gperf"
       {"is_constructible_type", METAFN_IS_CONSTRUCTIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO_REFLECTION_RANGET,},
-#line 631 "metafns.gperf"
+#line 633 "metafns.gperf"
       {"is_swappable_type", METAFN_IS_SWAPPABLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 502 "metafns.gperf"
+#line 503 "metafns.gperf"
       {"has_module_linkage", METAFN_HAS_MODULE_LINKAGE, 
METAFN_KIND_BOOL_INFO,},
-#line 529 "metafns.gperf"
+#line 530 "metafns.gperf"
       {"is_vararg_function", METAFN_IS_VARARG_FUNCTION, 
METAFN_KIND_BOOL_INFO,},
-#line 520 "metafns.gperf"
+#line 521 "metafns.gperf"
       {"is_copy_constructor", METAFN_IS_COPY_CONSTRUCTOR, 
METAFN_KIND_BOOL_INFO,},
-#line 692 "metafns.gperf"
+#line 694 "metafns.gperf"
       {"tuple_size", METAFN_TUPLE_SIZE, METAFN_KIND_SIZE_T_TINFO,},
-#line 556 "metafns.gperf"
+#line 557 "metafns.gperf"
       {"variable_of", METAFN_VARIABLE_OF, METAFN_KIND_INFO_INFO,},
-#line 600 "metafns.gperf"
+#line 601 "metafns.gperf"
       {"is_reflection_type", METAFN_IS_REFLECTION_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 574 "metafns.gperf"
+#line 575 "metafns.gperf"
       {"bit_size_of", METAFN_BIT_SIZE_OF, METAFN_KIND_SIZE_T_INFO,},
-#line 603 "metafns.gperf"
+#line 604 "metafns.gperf"
       {"is_fundamental_type", METAFN_IS_FUNDAMENTAL_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 663 "metafns.gperf"
+#line 665 "metafns.gperf"
       {"is_layout_compatible_type", METAFN_IS_LAYOUT_COMPATIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 699 "metafns.gperf"
+#line 701 "metafns.gperf"
       {"current", METAFN_ACCESS_CONTEXT_CURRENT, 
METAFN_KIND_ACCESS_CONTEXT_VOID,},
-#line 562 "metafns.gperf"
+#line 563 "metafns.gperf"
       {"current_function", METAFN_CURRENT_FUNCTION, METAFN_KIND_INFO_VOID,},
-#line 538 "metafns.gperf"
+#line 539 "metafns.gperf"
       {"is_constructor_template", METAFN_IS_CONSTRUCTOR_TEMPLATE, 
METAFN_KIND_BOOL_INFO,},
-#line 686 "metafns.gperf"
+#line 688 "metafns.gperf"
       {"common_type", METAFN_COMMON_TYPE, METAFN_KIND_INFO_REFLECTION_RANGET,},
-#line 629 "metafns.gperf"
+#line 631 "metafns.gperf"
       {"is_move_assignable_type", METAFN_IS_MOVE_ASSIGNABLE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 687 "metafns.gperf"
+#line 689 "metafns.gperf"
       {"common_reference", METAFN_COMMON_REFERENCE, 
METAFN_KIND_INFO_REFLECTION_RANGET,},
-#line 693 "metafns.gperf"
+#line 695 "metafns.gperf"
       {"tuple_element", METAFN_TUPLE_ELEMENT, METAFN_KIND_INFO_SIZE_T_TINFO,},
-#line 580 "metafns.gperf"
+#line 581 "metafns.gperf"
       {"reflect_function", METAFN_REFLECT_FUNCTION, 
METAFN_KIND_INFO_TEMPLATE_PARM_REF,},
-#line 500 "metafns.gperf"
+#line 501 "metafns.gperf"
       {"has_automatic_storage_duration", 
METAFN_HAS_AUTOMATIC_STORAGE_DURATION, METAFN_KIND_BOOL_INFO,},
-#line 524 "metafns.gperf"
+#line 525 "metafns.gperf"
       {"is_move_assignment", METAFN_IS_MOVE_ASSIGNMENT, 
METAFN_KIND_BOOL_INFO,},
-#line 518 "metafns.gperf"
+#line 519 "metafns.gperf"
       {"is_constructor", METAFN_IS_CONSTRUCTOR, METAFN_KIND_BOOL_INFO,},
-#line 549 "metafns.gperf"
+#line 550 "metafns.gperf"
       {"has_parent", METAFN_HAS_PARENT, METAFN_KIND_BOOL_INFO,},
-#line 626 "metafns.gperf"
+#line 628 "metafns.gperf"
       {"is_move_constructible_type", METAFN_IS_MOVE_CONSTRUCTIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 649 "metafns.gperf"
+#line 651 "metafns.gperf"
       {"is_nothrow_swappable_type", METAFN_IS_NOTHROW_SWAPPABLE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 610 "metafns.gperf"
+#line 611 "metafns.gperf"
       {"is_trivially_copyable_type", METAFN_IS_TRIVIALLY_COPYABLE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 601 "metafns.gperf"
+#line 602 "metafns.gperf"
       {"is_reference_type", METAFN_IS_REFERENCE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 593 "metafns.gperf"
+#line 594 "metafns.gperf"
       {"is_rvalue_reference_type", METAFN_IS_RVALUE_REFERENCE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 648 "metafns.gperf"
+#line 650 "metafns.gperf"
       {"is_nothrow_swappable_with_type", 
METAFN_IS_NOTHROW_SWAPPABLE_WITH_TYPE, METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 633 "metafns.gperf"
+#line 635 "metafns.gperf"
       {"is_trivially_constructible_type", 
METAFN_IS_TRIVIALLY_CONSTRUCTIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO_REFLECTION_RANGET,},
-#line 630 "metafns.gperf"
+#line 632 "metafns.gperf"
       {"is_swappable_with_type", METAFN_IS_SWAPPABLE_WITH_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 638 "metafns.gperf"
+#line 640 "metafns.gperf"
       {"is_trivially_copy_assignable_type", 
METAFN_IS_TRIVIALLY_COPY_ASSIGNABLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 688 "metafns.gperf"
+#line 690 "metafns.gperf"
       {"underlying_type", METAFN_UNDERLYING_TYPE, METAFN_KIND_INFO_TINFO,},
-#line 635 "metafns.gperf"
+#line 637 "metafns.gperf"
       {"is_trivially_copy_constructible_type", 
METAFN_IS_TRIVIALLY_COPY_CONSTRUCTIBLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 607 "metafns.gperf"
+#line 608 "metafns.gperf"
       {"is_member_pointer_type", METAFN_IS_MEMBER_POINTER_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 577 "metafns.gperf"
+#line 578 "metafns.gperf"
       {"substitute", METAFN_SUBSTITUTE, 
METAFN_KIND_INFO_INFO_REFLECTION_RANGE,},
-#line 555 "metafns.gperf"
+#line 556 "metafns.gperf"
       {"parameters_of", METAFN_PARAMETERS_OF, METAFN_KIND_VECTOR_INFO_INFO,},
-#line 521 "metafns.gperf"
+#line 522 "metafns.gperf"
       {"is_move_constructor", METAFN_IS_MOVE_CONSTRUCTOR, 
METAFN_KIND_BOOL_INFO,},
-#line 548 "metafns.gperf"
+#line 549 "metafns.gperf"
       {"has_default_member_initializer", 
METAFN_HAS_DEFAULT_MEMBER_INITIALIZER, METAFN_KIND_BOOL_INFO,},
-#line 517 "metafns.gperf"
+#line 518 "metafns.gperf"
       {"is_special_member_function", METAFN_IS_SPECIAL_MEMBER_FUNCTION, 
METAFN_KIND_BOOL_INFO,},
-#line 612 "metafns.gperf"
+#line 613 "metafns.gperf"
       {"is_empty_type", METAFN_IS_EMPTY_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 627 "metafns.gperf"
+#line 629 "metafns.gperf"
       {"is_assignable_type", METAFN_IS_ASSIGNABLE_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 592 "metafns.gperf"
+#line 593 "metafns.gperf"
       {"is_lvalue_reference_type", METAFN_IS_LVALUE_REFERENCE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 528 "metafns.gperf"
+#line 529 "metafns.gperf"
       {"has_default_argument", METAFN_HAS_DEFAULT_ARGUMENT, 
METAFN_KIND_BOOL_INFO,},
-#line 690 "metafns.gperf"
+#line 692 "metafns.gperf"
       {"unwrap_reference", METAFN_UNWRAP_REFERENCE, METAFN_KIND_INFO_TINFO,},
-#line 522 "metafns.gperf"
+#line 523 "metafns.gperf"
       {"is_assignment", METAFN_IS_ASSIGNMENT, METAFN_KIND_BOOL_INFO,},
-#line 609 "metafns.gperf"
+#line 610 "metafns.gperf"
       {"is_volatile_type", METAFN_IS_VOLATILE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 543 "metafns.gperf"
+#line 544 "metafns.gperf"
       {"is_class_member", METAFN_IS_CLASS_MEMBER, METAFN_KIND_BOOL_INFO,},
-#line 602 "metafns.gperf"
+#line 603 "metafns.gperf"
       {"is_arithmetic_type", METAFN_IS_ARITHMETIC_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 544 "metafns.gperf"
+#line 545 "metafns.gperf"
       {"is_namespace_member", METAFN_IS_NAMESPACE_MEMBER, 
METAFN_KIND_BOOL_INFO,},
-#line 565 "metafns.gperf"
+#line 566 "metafns.gperf"
       {"members_of", METAFN_MEMBERS_OF, 
METAFN_KIND_VECTOR_INFO_INFO_ACCESS_CONTEXT,},
-#line 478 "metafns.gperf"
+#line 479 "metafns.gperf"
       {"is_protected", METAFN_IS_PROTECTED, METAFN_KIND_BOOL_INFO,},
-#line 505 "metafns.gperf"
+#line 506 "metafns.gperf"
       {"has_linkage", METAFN_HAS_LINKAGE, METAFN_KIND_BOOL_INFO,},
-#line 469 "metafns.gperf"
+#line 470 "metafns.gperf"
       {"identifier_of", METAFN_IDENTIFIER_OF, METAFN_KIND_STRING_VIEW_INFO,},
-#line 677 "metafns.gperf"
+#line 679 "metafns.gperf"
       {"add_rvalue_reference", METAFN_ADD_RVALUE_REFERENCE, 
METAFN_KIND_INFO_TINFO,},
-#line 553 "metafns.gperf"
+#line 554 "metafns.gperf"
       {"template_of", METAFN_TEMPLATE_OF, METAFN_KIND_INFO_INFO,},
-#line 512 "metafns.gperf"
+#line 513 "metafns.gperf"
       {"is_namespace_alias", METAFN_IS_NAMESPACE_ALIAS, 
METAFN_KIND_BOOL_INFO,},
-#line 657 "metafns.gperf"
+#line 659 "metafns.gperf"
       {"extent", METAFN_EXTENT, METAFN_KIND_SIZE_T_TINFO_UNSIGNED,},
-#line 596 "metafns.gperf"
+#line 597 "metafns.gperf"
       {"is_enum_type", METAFN_IS_ENUM_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 533 "metafns.gperf"
+#line 534 "metafns.gperf"
       {"is_class_template", METAFN_IS_CLASS_TEMPLATE, METAFN_KIND_BOOL_INFO,},
-#line 608 "metafns.gperf"
+#line 619 "metafns.gperf"
+      {"is_structural_type", METAFN_IS_STRUCTURAL_TYPE, 
METAFN_KIND_BOOL_TINFO,},
+#line 609 "metafns.gperf"
       {"is_const_type", METAFN_IS_CONST_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 564 "metafns.gperf"
+#line 565 "metafns.gperf"
       {"current_namespace", METAFN_CURRENT_NAMESPACE, METAFN_KIND_INFO_VOID,},
-#line 488 "metafns.gperf"
+#line 489 "metafns.gperf"
       {"is_explicit", METAFN_IS_EXPLICIT, METAFN_KIND_BOOL_INFO,},
-#line 683 "metafns.gperf"
+#line 685 "metafns.gperf"
       {"add_pointer", METAFN_ADD_POINTER, METAFN_KIND_INFO_TINFO,},
-#line 639 "metafns.gperf"
+#line 641 "metafns.gperf"
       {"is_trivially_move_assignable_type", 
METAFN_IS_TRIVIALLY_MOVE_ASSIGNABLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 506 "metafns.gperf"
+#line 507 "metafns.gperf"
       {"is_complete_type", METAFN_IS_COMPLETE_TYPE, METAFN_KIND_BOOL_INFO,},
-#line 636 "metafns.gperf"
+#line 638 "metafns.gperf"
       {"is_trivially_move_constructible_type", 
METAFN_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 605 "metafns.gperf"
+#line 606 "metafns.gperf"
       {"is_scalar_type", METAFN_IS_SCALAR_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 481 "metafns.gperf"
+#line 482 "metafns.gperf"
       {"is_pure_virtual", METAFN_IS_PURE_VIRTUAL, METAFN_KIND_BOOL_INFO,},
-#line 526 "metafns.gperf"
+#line 527 "metafns.gperf"
       {"is_function_parameter", METAFN_IS_FUNCTION_PARAMETER, 
METAFN_KIND_BOOL_INFO,},
-#line 507 "metafns.gperf"
+#line 508 "metafns.gperf"
       {"is_enumerable_type", METAFN_IS_ENUMERABLE_TYPE, 
METAFN_KIND_BOOL_INFO,},
-#line 599 "metafns.gperf"
+#line 600 "metafns.gperf"
       {"is_function_type", METAFN_IS_FUNCTION_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 550 "metafns.gperf"
+#line 551 "metafns.gperf"
       {"parent_of", METAFN_PARENT_OF, METAFN_KIND_INFO_INFO,},
-#line 545 "metafns.gperf"
+#line 546 "metafns.gperf"
       {"is_nonstatic_data_member", METAFN_IS_NONSTATIC_DATA_MEMBER, 
METAFN_KIND_BOOL_INFO,},
-#line 542 "metafns.gperf"
+#line 543 "metafns.gperf"
       {"is_structured_binding", METAFN_IS_STRUCTURED_BINDING, 
METAFN_KIND_BOOL_INFO,},
-#line 495 "metafns.gperf"
+#line 496 "metafns.gperf"
       {"is_mutable_member", METAFN_IS_MUTABLE_MEMBER, METAFN_KIND_BOOL_INFO,},
-#line 637 "metafns.gperf"
+#line 639 "metafns.gperf"
       {"is_trivially_assignable_type", METAFN_IS_TRIVIALLY_ASSIGNABLE_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 624 "metafns.gperf"
+#line 626 "metafns.gperf"
       {"is_default_constructible_type", METAFN_IS_DEFAULT_CONSTRUCTIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 527 "metafns.gperf"
+#line 528 "metafns.gperf"
       {"is_explicit_object_parameter", METAFN_IS_EXPLICIT_OBJECT_PARAMETER, 
METAFN_KIND_BOOL_INFO,},
-#line 673 "metafns.gperf"
+#line 675 "metafns.gperf"
       {"add_volatile", METAFN_ADD_VOLATILE, METAFN_KIND_INFO_TINFO,},
-#line 563 "metafns.gperf"
+#line 564 "metafns.gperf"
       {"current_class", METAFN_CURRENT_CLASS, METAFN_KIND_INFO_VOID,},
-#line 570 "metafns.gperf"
+#line 571 "metafns.gperf"
       {"enumerators_of", METAFN_ENUMERATORS_OF, METAFN_KIND_VECTOR_INFO_INFO,},
-#line 491 "metafns.gperf"
+#line 492 "metafns.gperf"
       {"is_enumerator", METAFN_IS_ENUMERATOR, METAFN_KIND_BOOL_INFO,},
-#line 541 "metafns.gperf"
+#line 542 "metafns.gperf"
       {"is_object", METAFN_IS_OBJECT, METAFN_KIND_BOOL_INFO,},
-#line 472 "metafns.gperf"
+#line 473 "metafns.gperf"
       {"u8display_string_of", METAFN_U8DISPLAY_STRING_OF, 
METAFN_KIND_U8STRING_VIEW_INFO,},
-#line 595 "metafns.gperf"
+#line 596 "metafns.gperf"
       {"is_member_function_pointer_type", 
METAFN_IS_MEMBER_FUNCTION_POINTER_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 652 "metafns.gperf"
+#line 654 "metafns.gperf"
       {"has_virtual_destructor", METAFN_HAS_VIRTUAL_DESTRUCTOR, 
METAFN_KIND_BOOL_TINFO,},
-#line 655 "metafns.gperf"
+#line 657 "metafns.gperf"
       {"reference_converts_from_temporary", 
METAFN_REFERENCE_CONVERTS_FROM_TEMPORARY, METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 519 "metafns.gperf"
+#line 520 "metafns.gperf"
       {"is_default_constructor", METAFN_IS_DEFAULT_CONSTRUCTOR, 
METAFN_KIND_BOOL_INFO,},
-#line 604 "metafns.gperf"
+#line 605 "metafns.gperf"
       {"is_object_type", METAFN_IS_OBJECT_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 578 "metafns.gperf"
+#line 579 "metafns.gperf"
       {"reflect_constant", METAFN_REFLECT_CONSTANT, 
METAFN_KIND_INFO_TEMPLATE_PARM,},
-#line 525 "metafns.gperf"
+#line 526 "metafns.gperf"
       {"is_destructor", METAFN_IS_DESTRUCTOR, METAFN_KIND_BOOL_INFO,},
-#line 482 "metafns.gperf"
+#line 483 "metafns.gperf"
       {"is_override", METAFN_IS_OVERRIDE, METAFN_KIND_BOOL_INFO,},
-#line 654 "metafns.gperf"
+#line 656 "metafns.gperf"
       {"reference_constructs_from_temporary", 
METAFN_REFERENCE_CONSTRUCTS_FROM_TEMPORARY, METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 557 "metafns.gperf"
+#line 558 "metafns.gperf"
       {"return_type_of", METAFN_RETURN_TYPE_OF, METAFN_KIND_INFO_INFO,},
-#line 676 "metafns.gperf"
+#line 678 "metafns.gperf"
       {"add_lvalue_reference", METAFN_ADD_LVALUE_REFERENCE, 
METAFN_KIND_INFO_TINFO,},
-#line 476 "metafns.gperf"
+#line 477 "metafns.gperf"
       {"constant_of", METAFN_CONSTANT_OF, METAFN_KIND_INFO_INFO,},
-#line 671 "metafns.gperf"
+#line 673 "metafns.gperf"
       {"remove_cv", METAFN_REMOVE_CV, METAFN_KIND_INFO_TINFO,},
-#line 640 "metafns.gperf"
+#line 642 "metafns.gperf"
       {"is_trivially_destructible_type", 
METAFN_IS_TRIVIALLY_DESTRUCTIBLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 674 "metafns.gperf"
+#line 676 "metafns.gperf"
       {"add_cv", METAFN_ADD_CV, METAFN_KIND_INFO_TINFO,},
-#line 616 "metafns.gperf"
+#line 617 "metafns.gperf"
       {"is_aggregate_type", METAFN_IS_AGGREGATE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 581 "metafns.gperf"
+#line 582 "metafns.gperf"
       {"reflect_constant_string", METAFN_REFLECT_CONSTANT_STRING, 
METAFN_KIND_INFO_INPUT_RANGE,},
-#line 554 "metafns.gperf"
+#line 555 "metafns.gperf"
       {"template_arguments_of", METAFN_TEMPLATE_ARGUMENTS_OF, 
METAFN_KIND_VECTOR_INFO_INFO,},
-#line 569 "metafns.gperf"
+#line 570 "metafns.gperf"
       {"subobjects_of", METAFN_SUBOBJECTS_OF, 
METAFN_KIND_VECTOR_INFO_INFO_ACCESS_CONTEXT,},
-#line 571 "metafns.gperf"
+#line 572 "metafns.gperf"
       {"offset_of", METAFN_OFFSET_OF, METAFN_KIND_MEMBER_OFFSET_INFO,},
-#line 634 "metafns.gperf"
+#line 636 "metafns.gperf"
       {"is_trivially_default_constructible_type", 
METAFN_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 675 "metafns.gperf"
+#line 677 "metafns.gperf"
       {"remove_reference", METAFN_REMOVE_REFERENCE, METAFN_KIND_INFO_TINFO,},
-#line 534 "metafns.gperf"
+#line 535 "metafns.gperf"
       {"is_alias_template", METAFN_IS_ALIAS_TEMPLATE, METAFN_KIND_BOOL_INFO,},
-#line 679 "metafns.gperf"
+#line 681 "metafns.gperf"
       {"make_unsigned", METAFN_MAKE_UNSIGNED, METAFN_KIND_INFO_TINFO,},
-#line 665 "metafns.gperf"
+#line 667 "metafns.gperf"
       {"is_invocable_type", METAFN_IS_INVOCABLE_TYPE, 
METAFN_KIND_BOOL_TINFO_REFLECTION_RANGET,},
-#line 622 "metafns.gperf"
+#line 624 "metafns.gperf"
       {"is_scoped_enum_type", METAFN_IS_SCOPED_ENUM_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 546 "metafns.gperf"
+#line 547 "metafns.gperf"
       {"is_static_member", METAFN_IS_STATIC_MEMBER, METAFN_KIND_BOOL_INFO,},
-#line 672 "metafns.gperf"
+#line 674 "metafns.gperf"
       {"add_const", METAFN_ADD_CONST, METAFN_KIND_INFO_TINFO,},
-#line 632 "metafns.gperf"
+#line 634 "metafns.gperf"
       {"is_destructible_type", METAFN_IS_DESTRUCTIBLE_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 598 "metafns.gperf"
+#line 599 "metafns.gperf"
       {"is_class_type", METAFN_IS_CLASS_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 680 "metafns.gperf"
+#line 682 "metafns.gperf"
       {"remove_extent", METAFN_REMOVE_EXTENT, METAFN_KIND_INFO_TINFO,},
-#line 666 "metafns.gperf"
+#line 668 "metafns.gperf"
       {"is_invocable_r_type", METAFN_IS_INVOCABLE_R_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO_REFLECTION_RANGET,},
-#line 558 "metafns.gperf"
+#line 559 "metafns.gperf"
       {"is_accessible", METAFN_IS_ACCESSIBLE, 
METAFN_KIND_BOOL_INFO_ACCESS_CONTEXT,},
-#line 465 "metafns.gperf"
+#line 466 "metafns.gperf"
       {"operator_of", METAFN_OPERATOR_OF, METAFN_KIND_OPERATORS_INFO,},
-#line 590 "metafns.gperf"
+#line 591 "metafns.gperf"
       {"is_array_type", METAFN_IS_ARRAY_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 669 "metafns.gperf"
+#line 671 "metafns.gperf"
       {"remove_const", METAFN_REMOVE_CONST, METAFN_KIND_INFO_TINFO,},
-#line 497 "metafns.gperf"
-      {"is_rvalue_reference_qualified", METAFN_IS_RVALUE_REFERENCE_QUALIFIED, 
METAFN_KIND_BOOL_INFO,},
 #line 498 "metafns.gperf"
+      {"is_rvalue_reference_qualified", METAFN_IS_RVALUE_REFERENCE_QUALIFIED, 
METAFN_KIND_BOOL_INFO,},
+#line 499 "metafns.gperf"
       {"has_static_storage_duration", METAFN_HAS_STATIC_STORAGE_DURATION, 
METAFN_KIND_BOOL_INFO,},
-#line 681 "metafns.gperf"
+#line 683 "metafns.gperf"
       {"remove_all_extents", METAFN_REMOVE_ALL_EXTENTS, 
METAFN_KIND_INFO_TINFO,},
-#line 503 "metafns.gperf"
+#line 504 "metafns.gperf"
       {"has_external_linkage", METAFN_HAS_EXTERNAL_LINKAGE, 
METAFN_KIND_BOOL_INFO,},
-#line 684 "metafns.gperf"
+#line 686 "metafns.gperf"
       {"remove_cvref", METAFN_REMOVE_CVREF, METAFN_KIND_INFO_TINFO,},
-#line 492 "metafns.gperf"
+#line 493 "metafns.gperf"
       {"is_annotation", METAFN_IS_ANNOTATION, METAFN_KIND_BOOL_INFO,},
-#line 682 "metafns.gperf"
+#line 684 "metafns.gperf"
       {"remove_pointer", METAFN_REMOVE_POINTER, METAFN_KIND_INFO_TINFO,},
-#line 496 "metafns.gperf"
+#line 497 "metafns.gperf"
       {"is_lvalue_reference_qualified", METAFN_IS_LVALUE_REFERENCE_QUALIFIED, 
METAFN_KIND_BOOL_INFO,},
-#line 660 "metafns.gperf"
+#line 662 "metafns.gperf"
       {"is_virtual_base_of_type", METAFN_IS_VIRTUAL_BASE_OF_TYPE, 
METAFN_KIND_BOOL_TINFO_TINFO,},
-#line 584 "metafns.gperf"
+#line 585 "metafns.gperf"
       {"is_data_member_spec", METAFN_IS_DATA_MEMBER_SPEC, 
METAFN_KIND_BOOL_INFO,},
-#line 618 "metafns.gperf"
+#line 620 "metafns.gperf"
       {"is_signed_type", METAFN_IS_SIGNED_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 614 "metafns.gperf"
+#line 615 "metafns.gperf"
       {"is_abstract_type", METAFN_IS_ABSTRACT_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 480 "metafns.gperf"
+#line 481 "metafns.gperf"
       {"is_virtual", METAFN_IS_VIRTUAL, METAFN_KIND_BOOL_INFO,},
-#line 471 "metafns.gperf"
+#line 472 "metafns.gperf"
       {"display_string_of", METAFN_DISPLAY_STRING_OF, 
METAFN_KIND_STRING_VIEW_INFO,},
-#line 594 "metafns.gperf"
+#line 595 "metafns.gperf"
       {"is_member_object_pointer_type", METAFN_IS_MEMBER_OBJECT_POINTER_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 691 "metafns.gperf"
+#line 693 "metafns.gperf"
       {"unwrap_ref_decay", METAFN_UNWRAP_REF_DECAY, METAFN_KIND_INFO_TINFO,},
-#line 617 "metafns.gperf"
+#line 618 "metafns.gperf"
       {"is_consteval_only_type", METAFN_IS_CONSTEVAL_ONLY_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 606 "metafns.gperf"
+#line 607 "metafns.gperf"
       {"is_compound_type", METAFN_IS_COMPOUND_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 467 "metafns.gperf"
+#line 468 "metafns.gperf"
       {"u8symbol_of", METAFN_U8SYMBOL_OF, 
METAFN_KIND_U8STRING_VIEW_OPERATORS,},
-#line 484 "metafns.gperf"
+#line 485 "metafns.gperf"
       {"is_deleted", METAFN_IS_DELETED, METAFN_KIND_BOOL_INFO,},
-#line 589 "metafns.gperf"
+#line 590 "metafns.gperf"
       {"is_floating_point_type", METAFN_IS_FLOATING_POINT_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 537 "metafns.gperf"
+#line 538 "metafns.gperf"
       {"is_literal_operator_template", METAFN_IS_LITERAL_OPERATOR_TEMPLATE, 
METAFN_KIND_BOOL_INFO,},
-#line 485 "metafns.gperf"
+#line 486 "metafns.gperf"
       {"is_defaulted", METAFN_IS_DEFAULTED, METAFN_KIND_BOOL_INFO,},
-#line 583 "metafns.gperf"
+#line 584 "metafns.gperf"
       {"data_member_spec", METAFN_DATA_MEMBER_SPEC, 
METAFN_KIND_INFO_TINFO_DATA_MEMBER_OPTIONS,},
-#line 475 "metafns.gperf"
+#line 476 "metafns.gperf"
       {"object_of", METAFN_OBJECT_OF, METAFN_KIND_INFO_INFO,},
-#line 700 "metafns.gperf"
+#line 702 "metafns.gperf"
       {"_S_exception_cvt_to_utf8", METAFN_EXCEPTION__S_EXCEPTION_CVT_TO_UTF8, 
METAFN_KIND_U8STRING_VIEW_INPUT_RANGE,},
-#line 701 "metafns.gperf"
+#line 703 "metafns.gperf"
       {"_S_exception_cvt_from_utf8", 
METAFN_EXCEPTION__S_EXCEPTION_CVT_FROM_UTF8, 
METAFN_KIND_STRING_VIEW_INPUT_RANGE,},
-#line 483 "metafns.gperf"
+#line 484 "metafns.gperf"
       {"is_final", METAFN_IS_FINAL, METAFN_KIND_BOOL_INFO,},
-#line 516 "metafns.gperf"
+#line 517 "metafns.gperf"
       {"is_literal_operator", METAFN_IS_LITERAL_OPERATOR, 
METAFN_KIND_BOOL_INFO,},
-#line 487 "metafns.gperf"
+#line 488 "metafns.gperf"
       {"is_user_declared", METAFN_IS_USER_DECLARED, METAFN_KIND_BOOL_INFO,},
-#line 552 "metafns.gperf"
+#line 553 "metafns.gperf"
       {"has_template_arguments", METAFN_HAS_TEMPLATE_ARGUMENTS, 
METAFN_KIND_BOOL_INFO,},
-#line 515 "metafns.gperf"
+#line 516 "metafns.gperf"
       {"is_operator_function", METAFN_IS_OPERATOR_FUNCTION, 
METAFN_KIND_BOOL_INFO,},
-#line 689 "metafns.gperf"
+#line 691 "metafns.gperf"
       {"invoke_result", METAFN_INVOKE_RESULT, 
METAFN_KIND_INFO_TINFO_REFLECTION_RANGET,},
-#line 582 "metafns.gperf"
+#line 583 "metafns.gperf"
       {"reflect_constant_array", METAFN_REFLECT_CONSTANT_ARRAY, 
METAFN_KIND_INFO_INPUT_RANGE,},
-#line 504 "metafns.gperf"
+#line 505 "metafns.gperf"
       {"has_c_language_linkage", METAFN_HAS_C_LANGUAGE_LINKAGE, 
METAFN_KIND_BOOL_INFO,},
-#line 536 "metafns.gperf"
+#line 537 "metafns.gperf"
       {"is_operator_function_template", METAFN_IS_OPERATOR_FUNCTION_TEMPLATE, 
METAFN_KIND_BOOL_INFO,},
-#line 588 "metafns.gperf"
+#line 589 "metafns.gperf"
       {"is_integral_type", METAFN_IS_INTEGRAL_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 653 "metafns.gperf"
+#line 655 "metafns.gperf"
       {"has_unique_object_representations", 
METAFN_HAS_UNIQUE_OBJECT_REPRESENTATIONS, METAFN_KIND_BOOL_TINFO,},
-#line 499 "metafns.gperf"
+#line 500 "metafns.gperf"
       {"has_thread_storage_duration", METAFN_HAS_THREAD_STORAGE_DURATION, 
METAFN_KIND_BOOL_INFO,},
-#line 560 "metafns.gperf"
-      {"has_inaccessible_bases", METAFN_HAS_INACCESSIBLE_BASES, 
METAFN_KIND_BOOL_INFO_ACCESS_CONTEXT,},
 #line 561 "metafns.gperf"
+      {"has_inaccessible_bases", METAFN_HAS_INACCESSIBLE_BASES, 
METAFN_KIND_BOOL_INFO_ACCESS_CONTEXT,},
+#line 562 "metafns.gperf"
       {"has_inaccessible_subobjects", METAFN_HAS_INACCESSIBLE_SUBOBJECTS, 
METAFN_KIND_BOOL_INFO_ACCESS_CONTEXT,},
-#line 678 "metafns.gperf"
+#line 680 "metafns.gperf"
       {"make_signed", METAFN_MAKE_SIGNED, METAFN_KIND_INFO_TINFO,},
-#line 559 "metafns.gperf"
+#line 560 "metafns.gperf"
       {"has_inaccessible_nonstatic_data_members", 
METAFN_HAS_INACCESSIBLE_NONSTATIC_DATA_MEMBERS, 
METAFN_KIND_BOOL_INFO_ACCESS_CONTEXT,},
-#line 670 "metafns.gperf"
+#line 672 "metafns.gperf"
       {"remove_volatile", METAFN_REMOVE_VOLATILE, METAFN_KIND_INFO_TINFO,},
-#line 579 "metafns.gperf"
+#line 580 "metafns.gperf"
       {"reflect_object", METAFN_REFLECT_OBJECT, 
METAFN_KIND_INFO_TEMPLATE_PARM_REF,},
-#line 611 "metafns.gperf"
+#line 612 "metafns.gperf"
       {"is_standard_layout_type", METAFN_IS_STANDARD_LAYOUT_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 685 "metafns.gperf"
+#line 687 "metafns.gperf"
       {"decay", METAFN_DECAY, METAFN_KIND_INFO_TINFO,},
-#line 621 "metafns.gperf"
+#line 623 "metafns.gperf"
       {"is_unbounded_array_type", METAFN_IS_UNBOUNDED_ARRAY_TYPE, 
METAFN_KIND_BOOL_TINFO,},
-#line 568 "metafns.gperf"
+#line 569 "metafns.gperf"
       {"nonstatic_data_members_of", METAFN_NONSTATIC_DATA_MEMBERS_OF, 
METAFN_KIND_VECTOR_INFO_INFO_ACCESS_CONTEXT,},
-#line 597 "metafns.gperf"
+#line 598 "metafns.gperf"
       {"is_union_type", METAFN_IS_UNION_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 468 "metafns.gperf"
+#line 469 "metafns.gperf"
       {"has_identifier", METAFN_HAS_IDENTIFIER, METAFN_KIND_BOOL_INFO,},
-#line 567 "metafns.gperf"
+#line 568 "metafns.gperf"
       {"static_data_members_of", METAFN_STATIC_DATA_MEMBERS_OF, 
METAFN_KIND_VECTOR_INFO_INFO_ACCESS_CONTEXT,},
-#line 615 "metafns.gperf"
+#line 616 "metafns.gperf"
       {"is_final_type", METAFN_IS_FINAL_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 551 "metafns.gperf"
+#line 552 "metafns.gperf"
       {"dealias", METAFN_DEALIAS, METAFN_KIND_INFO_INFO,},
-#line 698 "metafns.gperf"
+#line 700 "metafns.gperf"
       {"annotations_of_with_type", METAFN_ANNOTATIONS_OF_WITH_TYPE, 
METAFN_KIND_VECTOR_INFO_INFO_INFO,},
-#line 585 "metafns.gperf"
+#line 586 "metafns.gperf"
       {"define_aggregate", METAFN_DEFINE_AGGREGATE, 
METAFN_KIND_INFO_INFO_REFLECTION_RANGE,},
-#line 490 "metafns.gperf"
+#line 491 "metafns.gperf"
       {"is_bit_field", METAFN_IS_BIT_FIELD, METAFN_KIND_BOOL_INFO,},
-#line 697 "metafns.gperf"
+#line 699 "metafns.gperf"
       {"annotations_of", METAFN_ANNOTATIONS_OF, METAFN_KIND_VECTOR_INFO_INFO,},
-#line 473 "metafns.gperf"
+#line 474 "metafns.gperf"
       {"source_location_of", METAFN_SOURCE_LOCATION_OF, 
METAFN_KIND_SOURCE_LOCATION_INFO,},
-#line 573 "metafns.gperf"
+#line 574 "metafns.gperf"
       {"alignment_of", METAFN_ALIGNMENT_OF, METAFN_KIND_SIZE_T_INFO,},
-#line 501 "metafns.gperf"
+#line 502 "metafns.gperf"
       {"has_internal_linkage", METAFN_HAS_INTERNAL_LINKAGE, 
METAFN_KIND_BOOL_INFO,},
-#line 470 "metafns.gperf"
+#line 471 "metafns.gperf"
       {"u8identifier_of", METAFN_U8IDENTIFIER_OF, 
METAFN_KIND_U8STRING_VIEW_INFO,},
-#line 619 "metafns.gperf"
+#line 621 "metafns.gperf"
       {"is_unsigned_type", METAFN_IS_UNSIGNED_TYPE, METAFN_KIND_BOOL_TINFO,},
-#line 486 "metafns.gperf"
+#line 487 "metafns.gperf"
       {"is_user_provided", METAFN_IS_USER_PROVIDED, METAFN_KIND_BOOL_INFO,}
     };
 #if (defined __GNUC__ && __GNUC__ + (__GNUC_MINOR__ >= 6) > 4) || (defined 
__clang__ && __clang_major__ >= 3)
@@ -1108,50 +1111,50 @@ metafn_lookup::find (const char *str, size_t len)
        95,  96,  -1,  97,  98,  99,  -1,  -1, 100, 101,
       102,  -1,  -1,  -1,  -1,  -1,  -1, 103,  -1,  -1,
        -1, 104,  -1, 105,  -1, 106, 107,  -1, 108,  -1,
-      109, 110, 111,  -1,  -1,  -1, 112, 113,  -1, 114,
-       -1, 115,  -1, 116, 117,  -1, 118,  -1,  -1, 119,
-      120, 121, 122,  -1, 123,  -1,  -1,  -1, 124, 125,
-       -1,  -1,  -1,  -1,  -1,  -1, 126,  -1,  -1,  -1,
-       -1,  -1, 127, 128, 129,  -1, 130, 131,  -1,  -1,
-       -1,  -1,  -1, 132, 133,  -1,  -1, 134, 135, 136,
-       -1, 137, 138,  -1,  -1,  -1, 139, 140,  -1,  -1,
-       -1,  -1,  -1, 141,  -1,  -1, 142,  -1, 143,  -1,
-      144,  -1,  -1, 145, 146, 147, 148,  -1, 149,  -1,
-      150, 151, 152, 153,  -1,  -1, 154, 155, 156, 157,
-      158,  -1, 159, 160,  -1,  -1, 161,  -1,  -1, 162,
-       -1, 163,  -1,  -1, 164, 165, 166, 167, 168,  -1,
-       -1,  -1,  -1, 169,  -1, 170, 171,  -1,  -1,  -1,
-       -1, 172,  -1,  -1, 173,  -1, 174,  -1,  -1,  -1,
-       -1,  -1, 175,  -1,  -1, 176, 177,  -1,  -1,  -1,
-       -1,  -1,  -1,  -1,  -1,  -1,  -1, 178, 179, 180,
-       -1,  -1,  -1,  -1, 181,  -1,  -1,  -1,  -1, 182,
-       -1,  -1,  -1,  -1,  -1, 183,  -1,  -1,  -1, 184,
-       -1, 185, 186, 187,  -1,  -1,  -1,  -1,  -1,  -1,
-       -1,  -1,  -1,  -1, 188,  -1, 189,  -1,  -1, 190,
-       -1,  -1,  -1,  -1, 191, 192, 193,  -1,  -1, 194,
-       -1,  -1, 195,  -1,  -1,  -1, 196,  -1, 197,  -1,
-       -1, 198,  -1, 199,  -1,  -1,  -1,  -1,  -1, 200,
-      201, 202, 203,  -1, 204,  -1,  -1, 205,  -1,  -1,
-      206,  -1, 207,  -1,  -1,  -1,  -1,  -1, 208,  -1,
+      109, 110, 111, 112,  -1,  -1, 113, 114,  -1, 115,
+       -1, 116,  -1, 117, 118,  -1, 119,  -1,  -1, 120,
+      121, 122, 123,  -1, 124,  -1,  -1,  -1, 125, 126,
+       -1,  -1,  -1,  -1,  -1,  -1, 127,  -1,  -1,  -1,
+       -1,  -1, 128, 129, 130,  -1, 131, 132,  -1,  -1,
+       -1,  -1,  -1, 133, 134,  -1,  -1, 135, 136, 137,
+       -1, 138, 139,  -1,  -1,  -1, 140, 141,  -1,  -1,
+       -1,  -1,  -1, 142,  -1,  -1, 143,  -1, 144,  -1,
+      145,  -1,  -1, 146, 147, 148, 149,  -1, 150,  -1,
+      151, 152, 153, 154,  -1,  -1, 155, 156, 157, 158,
+      159,  -1, 160, 161,  -1,  -1, 162,  -1,  -1, 163,
+       -1, 164,  -1,  -1, 165, 166, 167, 168, 169,  -1,
+       -1,  -1,  -1, 170,  -1, 171, 172,  -1,  -1,  -1,
+       -1, 173,  -1,  -1, 174,  -1, 175,  -1,  -1,  -1,
+       -1,  -1, 176,  -1,  -1, 177, 178,  -1,  -1,  -1,
+       -1,  -1,  -1,  -1,  -1,  -1,  -1, 179, 180, 181,
+       -1,  -1,  -1,  -1, 182,  -1,  -1,  -1,  -1, 183,
+       -1,  -1,  -1,  -1,  -1, 184,  -1,  -1,  -1, 185,
+       -1, 186, 187, 188,  -1,  -1,  -1,  -1,  -1,  -1,
+       -1,  -1,  -1,  -1, 189,  -1, 190,  -1,  -1, 191,
+       -1,  -1,  -1,  -1, 192, 193, 194,  -1,  -1, 195,
+       -1,  -1, 196,  -1,  -1,  -1, 197,  -1, 198,  -1,
+       -1, 199,  -1, 200,  -1,  -1,  -1,  -1,  -1, 201,
+      202, 203, 204,  -1, 205,  -1,  -1, 206,  -1,  -1,
+      207,  -1, 208,  -1,  -1,  -1,  -1,  -1, 209,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-       -1,  -1,  -1, 209,  -1,  -1,  -1,  -1,  -1, 210,
-       -1, 211,  -1,  -1,  -1,  -1,  -1,  -1, 212,  -1,
-       -1,  -1,  -1, 213,  -1,  -1,  -1,  -1,  -1,  -1,
-       -1, 214,  -1,  -1,  -1, 215,  -1,  -1,  -1, 216,
-      217,  -1,  -1, 218,  -1,  -1,  -1,  -1, 219,  -1,
-       -1,  -1,  -1,  -1,  -1,  -1,  -1, 220,  -1,  -1,
+       -1,  -1,  -1, 210,  -1,  -1,  -1,  -1,  -1, 211,
+       -1, 212,  -1,  -1,  -1,  -1,  -1,  -1, 213,  -1,
+       -1,  -1,  -1, 214,  -1,  -1,  -1,  -1,  -1,  -1,
+       -1, 215,  -1,  -1,  -1, 216,  -1,  -1,  -1, 217,
+      218,  -1,  -1, 219,  -1,  -1,  -1,  -1, 220,  -1,
+       -1,  -1,  -1,  -1,  -1,  -1,  -1, 221,  -1,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-       -1,  -1,  -1,  -1,  -1, 221,  -1,  -1,  -1,  -1,
-      222,  -1,  -1,  -1,  -1, 223,  -1,  -1,  -1,  -1,
-       -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 224,  -1,
-       -1,  -1, 225, 226,  -1,  -1,  -1,  -1, 227,  -1,
-      228,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 229,  -1,
+       -1,  -1,  -1,  -1,  -1, 222,  -1,  -1,  -1,  -1,
+      223,  -1,  -1,  -1,  -1, 224,  -1,  -1,  -1,  -1,
+       -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 225,  -1,
+       -1,  -1, 226, 227,  -1,  -1,  -1,  -1, 228,  -1,
+      229,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 230,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-       -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 230,  -1,
+       -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 231,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-       -1,  -1, 231,  -1,  -1, 232,  -1,  -1,  -1,  -1,
-       -1,  -1,  -1,  -1,  -1,  -1, 233,  -1,  -1, 234,
+       -1,  -1, 232,  -1,  -1, 233,  -1,  -1,  -1,  -1,
+       -1,  -1,  -1,  -1,  -1,  -1, 234,  -1,  -1, 235,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
@@ -1161,10 +1164,10 @@ metafn_lookup::find (const char *str, size_t len)
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-       -1,  -1,  -1, 235,  -1,  -1,  -1,  -1,  -1,  -1,
+       -1,  -1,  -1, 236,  -1,  -1,  -1,  -1,  -1,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
        -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-      236
+      237
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index e4cef5228e3e..df7f0b54b5b5 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -4352,6 +4352,14 @@ eval_is_consteval_only_type (tree type)
     return boolean_false_node;
 }
 
+/* Process std::meta::is_structural_type.  */
+
+static tree
+eval_is_structural_type (location_t loc, tree type)
+{
+  return eval_type_trait (loc, type, CPTK_IS_STRUCTURAL);
+}
+
 /* Process std::meta::is_signed_type.  */
 
 static tree
@@ -7989,6 +7997,8 @@ process_metafunction (const constexpr_ctx *ctx, tree fun, 
tree call,
       return eval_is_aggregate_type (h);
     case METAFN_IS_CONSTEVAL_ONLY_TYPE:
       return eval_is_consteval_only_type (h);
+    case METAFN_IS_STRUCTURAL_TYPE:
+      return eval_is_structural_type (loc, h);
     case METAFN_IS_SIGNED_TYPE:
       return eval_is_signed_type (h);
     case METAFN_IS_UNSIGNED_TYPE:
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index ac08b598f3d0..abd1156a2dc1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -14173,6 +14173,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
     case CPTK_IS_CONSTEVAL_ONLY:
       return consteval_only_p (type1);
 
+    case CPTK_IS_STRUCTURAL:
+      return structural_type_p (type1);
+
     /* __array_rank, __builtin_type_order and __builtin_structured_binding_size
        are handled in finish_trait_expr.  */
     case CPTK_RANK:
@@ -14354,6 +14357,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, 
tree type1, tree type2)
     case CPTK_IS_TRIVIAL:
     case CPTK_IS_TRIVIALLY_COPYABLE:
     case CPTK_IS_CONSTEVAL_ONLY:
+    case CPTK_IS_STRUCTURAL:
     case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
       if (!check_trait_type (type1, /* kind = */ 2))
        return error_mark_node;
diff --git a/gcc/testsuite/g++.dg/reflect/eh1.C 
b/gcc/testsuite/g++.dg/reflect/eh1.C
index 10eba7b2a8dd..ed4eeb087617 100644
--- a/gcc/testsuite/g++.dg/reflect/eh1.C
+++ b/gcc/testsuite/g++.dg/reflect/eh1.C
@@ -257,6 +257,9 @@ eval (int n)
     case 84:
       unwrap_ref_decay (^^n);
       break;
+    case 85:
+      is_structural_type (^^n);
+      break;
    default:
       break;
     }
@@ -353,3 +356,4 @@ static_assert (test (81));
 static_assert (test (82));
 static_assert (test (83));
 static_assert (test (84));
+static_assert (test (85));
diff --git a/gcc/testsuite/g++.dg/reflect/eh2.C 
b/gcc/testsuite/g++.dg/reflect/eh2.C
index 21f98796dfe3..bb601f186498 100644
--- a/gcc/testsuite/g++.dg/reflect/eh2.C
+++ b/gcc/testsuite/g++.dg/reflect/eh2.C
@@ -89,3 +89,4 @@ static_assert ((is_swappable_type (^^i), true)); // { 
dg-error "non-constant|unc
 static_assert ((is_nothrow_swappable_type (^^i), true)); // { dg-error 
"non-constant|uncaught exception" }
 static_assert ((unwrap_reference (^^i), true)); // { dg-error 
"non-constant|uncaught exception" }
 static_assert ((unwrap_ref_decay (^^i), true)); // { dg-error 
"non-constant|uncaught exception" }
+static_assert ((is_structural_type (^^i), true)); // { dg-error 
"non-constant|uncaught exception" }
diff --git a/gcc/testsuite/g++.dg/reflect/type_trait14.C 
b/gcc/testsuite/g++.dg/reflect/type_trait14.C
new file mode 100644
index 000000000000..7aa1d5f1dd36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/type_trait14.C
@@ -0,0 +1,61 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+// Test reflection type traits [meta.reflection.traits], type properties.
+
+#include <meta>
+using namespace std::meta;
+
+struct A { constexpr A () : a (42) {} mutable int a; };
+struct B { constexpr B () {} A b; };
+struct C : public A { constexpr C () {} };
+struct D {};
+struct E : protected D { constexpr E () {} };
+struct F { constexpr F () : f (42) {} int f; };
+struct G { F a; int b[2]; constexpr G () : b{0,1} {} };
+enum EnumType { e0 };
+class ClassType { };
+struct NType { int i; int j; virtual ~NType (); };
+struct TType { int i; private: int j; };
+struct SLType { int i; int j; ~SLType (); };
+struct PODType { int i; int j; };
+struct LType { int _M_i; constexpr LType (int __i) : _M_i(__i) { } };
+struct LTypeDerived : public LType { constexpr LTypeDerived (int __i) : 
LType(__i) { } };
+struct NLType {
+  int _M_i;
+  NLType () : _M_i(0) { }
+  constexpr NLType (int __i) : _M_i(__i) { }
+  NLType (const NLType &__other) : _M_i(__other._M_i) { }
+  ~NLType () { _M_i = 0; }
+};
+
+static_assert (is_structural_type (^^int));
+static_assert (is_structural_type (^^float));
+static_assert (is_structural_type (^^const float));
+static_assert (is_structural_type (^^EnumType));
+static_assert (is_structural_type (^^int*));
+static_assert (is_structural_type (^^int(*)(int)));
+static_assert (is_structural_type (^^int (ClassType::*)));
+static_assert (is_structural_type (^^int (ClassType::*) (int)));
+static_assert (is_structural_type (^^std::nullptr_t));
+static_assert (is_structural_type (^^info));
+static_assert (is_structural_type (^^int&));
+static_assert (is_structural_type (^^NLType&));
+static_assert (is_structural_type (^^PODType));
+static_assert (is_structural_type (^^const LType));
+static_assert (is_structural_type (^^LTypeDerived));
+static_assert (is_structural_type (^^D));
+static_assert (is_structural_type (^^F));
+static_assert (is_structural_type (^^G));
+
+static_assert (!is_structural_type (^^int&&));
+static_assert (!is_structural_type (^^int[2]));
+static_assert (!is_structural_type (^^TType));
+static_assert (!is_structural_type (^^NType));
+static_assert (!is_structural_type (^^SLType));
+static_assert (!is_structural_type (^^LType[5]));
+static_assert (!is_structural_type (^^NLType));
+static_assert (!is_structural_type (^^NLType[5]));
+static_assert (!is_structural_type (^^A));
+static_assert (!is_structural_type (^^const B));
+static_assert (!is_structural_type (^^C));
+static_assert (!is_structural_type (^^E));
diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 998223306e25..1265f01757c9 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -2364,6 +2364,15 @@ ftms = {
   };
 };
 
+ftms = {
+  name = is_structural;
+  values = {
+    v = 202603;
+    cxxmin = 26;
+    extra_cond = "__has_builtin(__builtin_is_structural)";
+  };
+};
+
 // Standard test specifications.
 stds[97] = ">= 199711L";
 stds[03] = ">= 199711L";
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index cb3b9b0997e8..00f352089f7a 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2635,4 +2635,14 @@
 #endif /* !defined(__cpp_lib_simd) */
 #undef __glibcxx_want_simd
 
+#if !defined(__cpp_lib_is_structural)
+# if (__cplusplus >  202302L) && (__has_builtin(__builtin_is_structural))
+#  define __glibcxx_is_structural 202603L
+#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_structural)
+#   define __cpp_lib_is_structural 202603L
+#  endif
+# endif
+#endif /* !defined(__cpp_lib_is_structural) */
+#undef __glibcxx_want_is_structural
+
 #undef __glibcxx_want_all
diff --git a/libstdc++-v3/include/std/meta b/libstdc++-v3/include/std/meta
index 5b2dc58bdfe8..e855a31900e5 100644
--- a/libstdc++-v3/include/std/meta
+++ b/libstdc++-v3/include/std/meta
@@ -471,6 +471,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     consteval bool is_final_type(info);
     consteval bool is_aggregate_type(info);
     consteval bool is_consteval_only_type(info);
+#if __glibcxx_is_structural >= 202603L
+    consteval bool is_structural_type(info);
+#endif
     consteval bool is_signed_type(info);
     consteval bool is_unsigned_type(info);
     consteval bool is_bounded_array_type(info);
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index bba7a3fd03d2..38be1b0e09d3 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -55,6 +55,7 @@
 #define __glibcxx_want_is_null_pointer
 #define __glibcxx_want_is_pointer_interconvertible
 #define __glibcxx_want_is_scoped_enum
+#define __glibcxx_want_is_structural
 #define __glibcxx_want_is_swappable
 #define __glibcxx_want_is_virtual_base_of
 #define __glibcxx_want_logical_traits
@@ -3924,6 +3925,23 @@ template<typename _Ret, typename _Fn, typename... _Args>
       = __builtin_is_consteval_only(_Tp);
 #endif
 
+#if __cpp_lib_is_structural >= 202603L // C++ >= 26
+  /// is_structural - true if the type is a structural type.
+  /// @since C++26
+  template<typename _Tp>
+    struct is_structural
+    : bool_constant<__builtin_is_structural(_Tp)>
+    { };
+
+  /** is_structural_v - true if the type is a structural only type.
+   *  @ingroup variable_templates
+   *  @since C++26
+   */
+  template<typename _Tp>
+    inline constexpr bool is_structural_v
+      = __builtin_is_structural(_Tp);
+#endif
+
   /** * Remove references and cv-qualifiers.
    * @since C++20
    * @{
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index a7e88945c2f9..662f4405456e 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -2255,6 +2255,9 @@ export namespace std
     using std::meta::is_final_type;
     using std::meta::is_aggregate_type;
     using std::meta::is_consteval_only_type;
+#if __glibcxx_is_structural >= 202603L
+    using std::meta::is_structural_type;
+#endif
     using std::meta::is_signed_type;
     using std::meta::is_unsigned_type;
     using std::meta::is_bounded_array_type;
@@ -3578,6 +3581,10 @@ export namespace std
   using std::is_consteval_only_v;
 #endif
 #endif
+#if __glibcxx_is_structural >= 202603L
+  using std::is_structural;
+  using std::is_structural_v;
+#endif
 }
 
 // <typeindex>
diff --git 
a/libstdc++-v3/testsuite/20_util/is_structural/requirements/explicit_instantiation.cc
 
b/libstdc++-v3/testsuite/20_util/is_structural/requirements/explicit_instantiation.cc
new file mode 100644
index 000000000000..a8d2545c2def
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/20_util/is_structural/requirements/explicit_instantiation.cc
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+namespace std
+{
+  typedef short test_type;
+  template struct is_structural<test_type>;
+}
diff --git 
a/libstdc++-v3/testsuite/20_util/is_structural/requirements/typedefs.cc 
b/libstdc++-v3/testsuite/20_util/is_structural/requirements/typedefs.cc
new file mode 100644
index 000000000000..7ce089316653
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_structural/requirements/typedefs.cc
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::is_structural<int>             test_type;
+  typedef test_type::value_type               value_type;
+  typedef test_type::type                     type;
+  typedef test_type::type::value_type         type_value_type;
+  typedef test_type::type::type               type_type;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_structural/value.cc 
b/libstdc++-v3/testsuite/20_util/is_structural/value.cc
new file mode 100644
index 000000000000..b63d71043a09
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_structural/value.cc
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++26 } }
+
+#include <type_traits>
+#include <testsuite_tr1.h>
+
+void test01()
+{
+  using std::is_structural;
+  using namespace __gnu_test;
+  struct A { constexpr A () : a (42) {} mutable int a; };
+  struct B { constexpr B () {} A b; };
+  struct C : public A { constexpr C () {} };
+  struct D {};
+  struct E : protected D { constexpr E () {} };
+  struct F { constexpr F () : f (42) {} int f; };
+  struct G { F a; int b[2]; constexpr G () : b{0,1} {} };
+
+  static_assert(test_category<is_structural, int>(true), "");
+  static_assert(test_category<is_structural, float>(true), "");
+  static_assert(test_category<is_structural, const float>(true), "");
+  static_assert(test_category<is_structural, EnumType>(true), "");
+  static_assert(test_category<is_structural, int*>(true), "");
+  static_assert(test_category<is_structural, int(*)(int)>(true), "");
+  static_assert(test_category<is_structural, int (ClassType::*)>(true), "");
+  static_assert(test_category<is_structural, int (ClassType::*) (int)>(true), 
"");
+  static_assert(test_category<is_structural, std::nullptr_t>(true), "");
+#if __cpp_impl_reflection >= 202506L
+  static_assert(test_category<is_structural, decltype(^^::)>(true), "");
+#endif
+  static_assert(test_category<is_structural, int&>(true), "");
+  static_assert(test_category<is_structural, NLType&>(true), "");
+  static_assert(test_category<is_structural, PODType>(true), "");
+  static_assert(test_category<is_structural, const LType>(true), "");
+  static_assert(test_category<is_structural, LTypeDerived>(true), "");
+  static_assert(test_category<is_structural, D>(true), "");
+  static_assert(test_category<is_structural, F>(true), "");
+  static_assert(test_category<is_structural, G>(true), "");
+
+  static_assert(test_category<is_structural, int&&>(false), "");
+  static_assert(test_category<is_structural, int[2]>(false), "");
+  static_assert(test_category<is_structural, TType>(false), "");
+  static_assert(test_category<is_structural, NType>(false), "");
+  static_assert(test_category<is_structural, SLType>(false), "");
+  static_assert(test_category<is_structural, LType[5]>(false), "");
+  static_assert(test_category<is_structural, NLType>(false), "");
+  static_assert(test_category<is_structural, NLType[5]>(false), "");
+  static_assert(test_category<is_structural, A>(false), "");
+  static_assert(test_category<is_structural, const B>(false), "");
+  static_assert(test_category<is_structural, C>(false), "");
+  static_assert(test_category<is_structural, E>(false), "");
+}
diff --git a/libstdc++-v3/testsuite/20_util/variable_templates_for_traits.cc 
b/libstdc++-v3/testsuite/20_util/variable_templates_for_traits.cc
index eb440a097071..0ef2bc95f780 100644
--- a/libstdc++-v3/testsuite/20_util/variable_templates_for_traits.cc
+++ b/libstdc++-v3/testsuite/20_util/variable_templates_for_traits.cc
@@ -340,6 +340,11 @@ static_assert(is_consteval_only_v<decltype(^^int)>
 static_assert(!is_consteval_only_v<int> && !is_consteval_only<int>::value, "");
 #endif
 
+#if __cpp_lib_is_structural >= 202603L
+static_assert(is_structural_v<int> && is_structural<int>::value, "");
+static_assert(!is_structural_v<int &&> && !is_structural<int &&>::value, "");
+#endif
+
 static_assert(negation_v<false_type>, "");
 static_assert(!negation_v<true_type>, "");
 static_assert(conjunction_v<>, "");

Reply via email to