libstdc++: Constrain std::vector default constructor [PR113841]

This is needed to avoid errors outside the immediate context when
evaluating is_default_constructible_v<vector<T, A>> when A is not
default constructible.

To avoid diagnostic regressions for 23_containers/vector/48101_neg.cc we
need to make the std::allocator<cv T> partial specializations default
constructible, which they probably should have been anyway.

libstdc++-v3/ChangeLog:

	PR libstdc++/113841
	* include/bits/allocator.h (allocator<cv T>): Add default
	constructor to partial specializations for cv-qualified types.
	* include/bits/stl_vector.h (_Vector_impl::_Vector_impl()):
	Constrain so that it's only present if the allocator is default
	constructible.
	* include/bits/stl_bvector.h (_Bvector_impl::_Bvector_impl()):
	Likewise.
	* testsuite/23_containers/vector/cons/113841.cc: New test.
This commit is contained in:
Jonathan Wakely 2024-02-09 17:06:20 +00:00
parent 8539c5610a
commit 142cc4c223
4 changed files with 43 additions and 0 deletions

View File

@ -254,6 +254,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
public:
typedef _Tp value_type;
allocator() { }
template<typename _Up> allocator(const allocator<_Up>&) { }
};
@ -262,6 +263,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
public:
typedef _Tp value_type;
allocator() { }
template<typename _Up> allocator(const allocator<_Up>&) { }
};
@ -270,6 +272,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
public:
typedef _Tp value_type;
allocator() { }
template<typename _Up> allocator(const allocator<_Up>&) { }
};
/// @endcond

View File

@ -593,6 +593,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX20_CONSTEXPR
_Bvector_impl() _GLIBCXX_NOEXCEPT_IF(
is_nothrow_default_constructible<_Bit_alloc_type>::value)
#if __cpp_concepts
requires is_default_constructible_v<_Bit_alloc_type>
#endif
: _Bit_alloc_type()
{ }

View File

@ -135,6 +135,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX20_CONSTEXPR
_Vector_impl() _GLIBCXX_NOEXCEPT_IF(
is_nothrow_default_constructible<_Tp_alloc_type>::value)
#if __cpp_lib_concepts
requires is_default_constructible_v<_Tp_alloc_type>
#endif
: _Tp_alloc_type()
{ }

View File

@ -0,0 +1,34 @@
// { dg-do compile { target c++20 } }
#include <vector>
template<typename T>
struct Alloc
{
using value_type = T;
Alloc(int) { } // not default constructible
template<typename U> Alloc(const Alloc<U>&) { }
T* allocate(std::size_t n) { return std::allocator<T>().allocate(n); }
void deallocate(T* p, std::size_t n) { std::allocator<T>().deallocate(p, n); }
};
template<typename T> struct wrap { T t; };
template<typename T> void do_adl(T&) { }
void test_pr113841()
{
using test_type = std::vector<int, Alloc<int>>;
std::pair<const int, wrap<test_type>>* h = nullptr;
do_adl(h);
}
void test_pr113841_bool()
{
using test_type = std::vector<bool, Alloc<bool>>;
std::pair<const int, wrap<test_type>>* h = nullptr;
do_adl(h);
}