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>
