https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108619
--- Comment #14 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jonathan Wakely <r...@gcc.gnu.org>: https://gcc.gnu.org/g:8cf51d7516b92b352c358c14ab4e456ae53c3371 commit r15-3132-g8cf51d7516b92b352c358c14ab4e456ae53c3371 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Jul 10 23:14:19 2024 +0100 libstdc++: Fix std::allocator_traits::construct constraints [PR108619] Using std::is_constructible in the constraints introduces a spurious dependency on the type being destructible, which should not be required for constructing with an allocator. The test case shows a case where the type has a private destructor, which can be destroyed by the allocator, but std::is_destructible and std::is_constructible are false. Similarly, using is_nothrow_constructible in the noexcept-specifiers for the construct members of allocator_traits and std::allocator, __gnu_cxx::__new_allocator, and __gnu_cxx::__malloc_allocator gives the wrong answer if the type isn't destructible. We need a new type trait to define those correctly, so that we only check if the placement new-expression is nothrow after using is_constructible to check that it would be well-formed. Instead of just fixing the overly restrictive constraint to check for placement new, rewrite allocator_traits in terms of 'if constexpr' using variable templates and the detection idiom. Although we can use 'if constexpr' and variable templates in C++11 with appropriate uses of diagnostic pragmas, we can't have constexpr functions with multiple return statements. This means that in C++11 mode the _S_nothrow_construct and _S_nothrow_destroy helpers used for noexcept-specifiers still need to be overlaods using enable_if. Nearly everything else can be simplified to reduce overload resolution and enable_if checks. libstdc++-v3/ChangeLog: PR libstdc++/108619 * include/bits/alloc_traits.h (__allocator_traits_base): Add variable templates for detecting which allocator operations are supported. (allocator_traits): Use 'if constexpr' instead of dispatching to overloads constrained with enable_if. (allocator_traits<allocator<T>>::construct): Use Construct if construct_at is not supported. Use __is_nothrow_new_constructible for noexcept-specifier. (allocator_traits<allocator<void>>::construct): Use __is_nothrow_new_constructible for noexcept-specifier. * include/bits/new_allocator.h (construct): Likewise. * include/ext/malloc_allocator.h (construct): Likewise. * include/std/type_traits (__is_nothrow_new_constructible): New variable template. * testsuite/20_util/allocator/89510.cc: Adjust expected results. * testsuite/ext/malloc_allocator/89510.cc: Likewise. * testsuite/ext/new_allocator/89510.cc: Likewise. * testsuite/20_util/allocator_traits/members/108619.cc: New test.