https://gcc.gnu.org/g:f6f137f134d66ec4ec94dee046a269af9f282b87

commit r16-8394-gf6f137f134d66ec4ec94dee046a269af9f282b87
Author: Jakub Jelinek <[email protected]>
Date:   Wed Apr 1 19:15:51 2026 +0200

    libstdc++: Attempt to implement LWG4537 - Improve define_static_array
    
    The following patch attempts to implement
    https://cplusplus.github.io/LWG/lwg-active.html#4537
    
    I've also added tests for the returned type.
    
    2026-04-01  Jakub Jelinek  <[email protected]>
    
            * include/std/meta (std::meta::__detail::__statically_sized): New
            concept.
            (std::meta::define_static_array): Change return type to auto.  If
            __statically_sized<_Rg>, return span with ranges::size(__r) as
            second argument.
    
            * g++.dg/reflect/define_static_array1.C (l): Another variable
            with define_static_array test from array<int, 0>.
            Add static assertions for types of the define_static_array results.
    
    Reviewed-by: Jonathan Wakely <[email protected]>

Diff:
---
 .../g++.dg/reflect/define_static_array1.C          | 15 ++++++++++
 libstdc++-v3/include/std/meta                      | 33 ++++++++++++++++++----
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/gcc/testsuite/g++.dg/reflect/define_static_array1.C 
b/gcc/testsuite/g++.dg/reflect/define_static_array1.C
index 61a6a53c9082..d9256091231b 100644
--- a/gcc/testsuite/g++.dg/reflect/define_static_array1.C
+++ b/gcc/testsuite/g++.dg/reflect/define_static_array1.C
@@ -22,6 +22,7 @@ constexpr auto h = std::define_static_array (fa.subspan (1, 
4) | std::views::rev
 constexpr auto i = std::define_static_array (std::vector <V> { V { 1, 2, 3 }, 
V { 2, 3, 4 }, V { 3, 4, 5 } });
 constexpr auto j = std::define_static_array (std::vector <long long> {});
 constexpr auto k = std::define_static_array 
(std::meta::nonstatic_data_members_of (^^V, std::meta::access_context::current 
()));
+constexpr auto l = std::define_static_array (std::array <int, 0> {});
 static_assert (a.data () == std::define_static_string ("abcd") && a.size () == 
5);
 static_assert (b.data () == std::define_static_string (U"abcd\0ef\N{LATIN 
CAPITAL LETTER AE}")
               && b.size () == sizeof (U"abcd\0ef\N{LATIN CAPITAL LETTER AE}") 
/ sizeof (char32_t));
@@ -40,6 +41,20 @@ static_assert (h.data () == std::define_static_array 
(std::vector <int> { 5, 4,
 static_assert (i.size () == 3);
 static_assert (j.data () == nullptr && j.size () == 0);
 static_assert (k.size () == 3 && k[0] == ^^V::a && k[1] == ^^V::b && k[2] == 
^^V::c);
+static_assert (l.data () == nullptr && l.size () == 0);
+// LWG4537 - Improve define_static_array
+static_assert (type_of (^^a) == ^^const std::span <const char, 5>);
+static_assert (type_of (^^b) == ^^const std::span <const char32_t, sizeof 
(U"abcd\0ef\N{LATIN CAPITAL LETTER AE}") / sizeof (char32_t)>);
+static_assert (type_of (^^c) == ^^const std::span <const char, 
std::dynamic_extent>);
+static_assert (type_of (^^d) == ^^const std::span <const int, 4>);
+static_assert (type_of (^^e) == ^^const std::span <const float, 6>);
+static_assert (type_of (^^f) == ^^const std::span <const int, 
std::dynamic_extent>);
+static_assert (type_of (^^g) == ^^const std::span <const int, 
std::dynamic_extent>);
+static_assert (type_of (^^h) == ^^const std::span <const int, 
std::dynamic_extent>);
+static_assert (type_of (^^i) == ^^const std::span <const V, 
std::dynamic_extent>);
+static_assert (type_of (^^j) == ^^const std::span <const long long, 
std::dynamic_extent>);
+static_assert (type_of (^^k) == ^^const std::span <const std::meta::info, 
std::dynamic_extent>);
+static_assert (type_of (^^l) == ^^const std::span <const int, 0>);
 
 int
 main ()
diff --git a/libstdc++-v3/include/std/meta b/libstdc++-v3/include/std/meta
index 20cfba10b9f9..5b2dc58bdfe8 100644
--- a/libstdc++-v3/include/std/meta
+++ b/libstdc++-v3/include/std/meta
@@ -638,18 +638,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return meta::extract<const ranges::range_value_t<_Rg>*>(__str);
     }
 
+  namespace __detail
+  {
+    template<typename _Rg>
+    concept __statically_sized
+      = requires(_Rg&& __r) {
+       static_cast<char(*)[static_cast<size_t>(ranges::size(__r))
+                           >= 0]>(nullptr);
+      };
+  } // namespace __detail
+
   template<ranges::input_range _Rg>
-    consteval span<const ranges::range_value_t<_Rg>>
+    consteval auto
     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));
+      if constexpr (__detail::__statically_sized<_Rg>)
+       {
+         constexpr size_t __extent = static_cast<size_t>(ranges::size(__r));
+         if constexpr (__extent)
+           return span<const _Tp,
+                       __extent>(meta::extract<const _Tp*>(__array),
+                                 meta::extent(__type, 0U));
+         else
+           return span<const _Tp, 0>();
+       }
       else
-       return span<const _Tp>();
+       {
+         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>

Reply via email to