[PATCH v1] libstdc++: Apply LWG4351 to CTAD of span/mdspan.

Luc Grosheintz luc.grosheintz@gmail.com
Mon Sep 8 08:19:47 GMT 2025



On 9/7/25 5:34 PM, Jonathan Wakely wrote:
> On Sat, 6 Sept 2025 at 14:12, Luc Grosheintz wrote:
>>
>> The concept __integral_constant_like doesn't consider traits with a
>> boolean member `value` as an integer constant. This is done to reject
>> various completely unrelated traits like is_const, is_abstract, etc.
>>
>> LWG4351 adjusts the check to strip references and cv qualifiers before
>> checking if `value` is bool. The immediate context is constant_wrapper
>> which defines:
>>
>>      template<...>
>>      struct constant_wrapper
>>      {
>>        static constexpr const auto& value = ...;
>>      };
>>
>> Without LWG4351, std::cw<true> and std::cw<false> would both be
>> considered integer constants (by __integral_constant_like); but both
>> std::{true,false}_type are not considered integer constants. Hence,
>> LWG4351 removes inconsistent behaviour between std::integral_constant
>> and std::constant_wrapper.
> 
> Thanks, the patch looks good but I'd like to wait before pushing it
> until LWG have seen the issue. I'll start a prioritization poll for
> the issue tomorrow, and see if anybody points out a reason why the
> issue is wrong and shouldn't be fixed (I don't expect that to happen
> though).
> 

Thank you for the explanation. That makes sense and if someone
wants to experiment they can use trunk and this patch (though
this patch is probably applied quicker with an editor than
through git am).

> 
>>
>> libstdc++-v3/ChangeLog:
>>
>>          * include/std/span (__integral_constant_like): Use
>>          remove_cvref_t before checking if _Tp::value is boolean.
>>          * testsuite/23_containers/mdspan/extents/misc.cc: Update test.
>>          * testsuite/23_containers/mdspan/mdspan.cc: Ditto.
>>          * testsuite/23_containers/span/deduction.cc: Ditto.
>>
>> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
>> ---
>>   libstdc++-v3/include/std/span                               | 4 +++-
>>   libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc | 2 +-
>>   libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc       | 3 +--
>>   libstdc++-v3/testsuite/23_containers/span/deduction.cc      | 2 +-
>>   4 files changed, 6 insertions(+), 5 deletions(-)
>>
>> diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
>> index f9aa3c77e8e..58089113565 100644
>> --- a/libstdc++-v3/include/std/span
>> +++ b/libstdc++-v3/include/std/span
>> @@ -479,10 +479,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>     // deduction guides
>>     namespace __detail
>>     {
>> +    // _GLIBCXX_RESOLVE_LIB_DEFECTS
>> +    // 4351. integral-constant-like needs more remove_cvref_t
>>       template<typename _Tp>
>>         concept __integral_constant_like =
>>          is_integral_v<remove_cvref_t<decltype(_Tp::value)>>
>> -       && !is_same_v<bool, remove_const_t<decltype(_Tp::value)>>
>> +       && !is_same_v<bool, remove_cvref_t<decltype(_Tp::value)>>
>>          && convertible_to<_Tp, decltype(_Tp::value)>
>>          && equality_comparable_with<_Tp, decltype(_Tp::value)>
>>          && bool_constant<_Tp() == _Tp::value>::value
>> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
>> index 94086653a74..33d6f947f0b 100644
>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
>> @@ -121,7 +121,7 @@ test_deduction_from_constant()
>>     verify(std::extents(1, c2), std::extents<size_t, dyn, 2>{1});
>>     verify(std::extents(c2), std::extents<size_t, 2>{});
>>     verify(std::extents(1, c2), std::extents<size_t, dyn, 2>{1});
>> -  verify(std::extents(std::cw<true>, c2), std::extents<size_t, 1, 2>{});
>> +  verify(std::extents(std::cw<true>, c2), std::extents<size_t, dyn, 2>{1});
>>   #endif
>>     return true;
>>   }
>> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> index ca100b4f314..a92a0554417 100644
>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> @@ -304,8 +304,7 @@ test_from_pointer_and_constant()
>>     auto c3 = std::constant_wrapper<3>{};
>>     verify(std::mdspan(ptr, 2, c3), std::extents(2, i3));
>>     verify(std::mdspan(ptr, 2, std::cw<3>), std::extents(2, i3));
>> -  verify(std::mdspan(ptr, std::cw<true>, std::cw<3>),
>> -        std::extents(std::cw<1>, i3));
>> +  verify(std::mdspan(ptr, std::cw<true>, std::cw<3>), std::extents(1, i3));
>>   #endif
>>     return true;
>>   }
>> diff --git a/libstdc++-v3/testsuite/23_containers/span/deduction.cc b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
>> index e958ad5d6db..55a586254e8 100644
>> --- a/libstdc++-v3/testsuite/23_containers/span/deduction.cc
>> +++ b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
>> @@ -99,6 +99,6 @@ test01()
>>     static_assert( is_static_span<long, 4>(s17) );
>>
>>     std::span s18(a.data(), std::cw<true>);
>> -  static_assert( is_static_span<long, 1>(s18) );
>> +  static_assert( is_dynamic_span<long>(s18) );
>>   #endif
>>   }
>> --
>> 2.51.0
>>
> 



More information about the Libstdc++ mailing list