https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108619
--- Comment #16 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The releases/gcc-14 branch has been updated by Jonathan Wakely <r...@gcc.gnu.org>: https://gcc.gnu.org/g:1be3e4e43839d313364ffa99012ada41b4fae8da commit r14-10705-g1be3e4e43839d313364ffa99012ada41b4fae8da 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. On trunk all members of std::allocator_traits were rewritten in terms of 'if constexpr' using variable templates and the detection idiom. For the release branch this backport only changes the 'construct' member. 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 helper used for noexcept-specifiers still needs to be a pair of overloads using enable_if. libstdc++-v3/ChangeLog: PR libstdc++/108619 * include/bits/alloc_traits.h (__allocator_traits_base): Add variable templates for detecting whether the allocator has a construct member, or if placement new can be used instead. (allocator_traits::__construct_helper): Remove. (allocator_traits::__has_construct): Remove. (allocator_traits::construct): 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. (cherry picked from commit 8cf51d7516b92b352c358c14ab4e456ae53c3371)