[PATCH] libstdc++: implement constexpr memory algorithms

Giuseppe D'Angelo giuseppe.dangelo@kdab.com
Tue Feb 25 17:23:47 GMT 2025


Hello,

Thanks for the review!

On 20/02/2025 17:22, Patrick Palka wrote:
> On Sun, 16 Feb 2025, Giuseppe D'Angelo wrote:
> 
>> Hello,
>>
>> the attached patch implements the C++26 papers that add `constexpr` to the
>> specialized memory algorithms (the uninitialized_* family). Tested on x86-64
>> Linux.
>>
>> Thank you,
>> -- 
>> Giuseppe D'Angelo
>>
> 
>> Subject: [PATCH] libstdc++: implement constexpr memory algorithms
>>
>> This commit adds support for C++26's constexpr specialized memory
>> algorithms, introduced by P2283R2, P3508R0, P3369R0.
>>
>> The uninitialized_default, value, copy, move and fill algorithms are
>> affected, in all of their variants (iterator-based, range-based and _n
>> versions.)
>>
>> The changes are mostly mechanical -- add `constexpr` to a number of
>> signatures. I've introduced a helper macro to conditionally expand to
>> `constexpr` only in C++26 and above modes. The internal helper guard
>> class for range algorithms instead can be marked unconditionally.
>>
>> uninitialized_fill is the only algorithm where I had to add a branch to
>> a constexpr-friendly version (already existing).
> 
> Seems the patch also adds code to uninitialized_copy and
> uninitialized_fill_n?

Whops, sorry, didn't spot them when I reviewed the diff. You're right.

>>     template<typename _T1>
>> +#if __cpp_constexpr >= 202406L // >= C++26
>> +    _GLIBCXX26_CONSTEXPR
>> +#endif
> 
> Maybe we can get away with unconditionally declaring this
> _GLIBCXX26_CONSTEXPR?  If the compiler doesn't support constexpr
> placement new then the 'constexpr' would be silently dropped at
> instantiation time.  This would be in line with C++23 P2448R2 which
> made it no longer IFNDR to declare a constexpr function template
> for which no specialization is actually constexpr.

It's fundamentally a judgement / compatibility call.

The patch adding the _GLIBCXX26_CONSTEXPR macro is pending here
https://gcc.gnu.org/pipermail/libstdc++/2025-January/060265.html
and checks for __cplusplus >= 202400L.

According to cppreference only Clang >= 19 fully implements P2448R2, but 
Clang 17 and 18 already advertise C++26 compatibility under __cplusplus 
set to 202400.

On the other hand the ad-hoc _GLIBCXX26_CONSTEXPR_RAW_MEMORY_ALGORITHMS 
has a more stringent version check (uses the feature-testing macro, 
which in turn checks for the right value of __cpp_constexpr).

Is switching to _GLIBCXX26_CONSTEXPR going to create compatibility 
problems? If not, I'll do the change.


>> +
>>   namespace std _GLIBCXX_VISIBILITY(default)
>>   {
>>   _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> @@ -226,6 +232,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>      *  Like std::copy, but does not require an initialized output range.
>>     */
>>     template<typename _InputIterator, typename _ForwardIterator>
>> +    _GLIBCXX26_CONSTEXPR_RAW_MEMORY_ALGORITHMS
>>       inline _ForwardIterator
>>       uninitialized_copy(_InputIterator __first, _InputIterator __last,
>>   		       _ForwardIterator __result)
>> @@ -256,6 +263,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>         using _Src = decltype(std::__niter_base(__first));
>>         using _ValT = typename iterator_traits<_ForwardIterator>::value_type;
>>   
>> +
>> +      if (__is_constant_evaluated())
> 
> We typically call __is_constant_evaluated fully qualified (though I
> don't remember why since it's not eligible for ADL?)

Ack, will fix.

> 
>> +	return std::__do_uninit_copy(__first, __last, __result);
> 
> I guess we could instead guard the memcpy code path preceding the
> existing call to __do_uninit_copy with !std::__is_constant_evaluated(),
> rather than adding this new call.  But that doesn't seem significantly
> cleaner and I'm personally OK with your approach :)
> 
> Same for uninitialized_fill and uninitialized_fill_n

I'm wagering this is the simplest implementation strategy for most 
constexpr-ified algorithms -- first thing, check if we're called during 
constant evaluation, if so dispatch to a constexpr-friendly implementation.


Thank you,

-- 
Giuseppe D'Angelo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4244 bytes
Desc: S/MIME Cryptographic Signature
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250225/c82e706b/attachment.p7s>


More information about the Libstdc++ mailing list