diff mbox series

[committed] libstdc++: Constrain std::basic_string default constructor [PR113841]

Message ID 20240801210933.386029-1-jwakely@redhat.com
State New
Headers show
Series [committed] libstdc++: Constrain std::basic_string default constructor [PR113841] | expand

Commit Message

Jonathan Wakely Aug. 1, 2024, 9:08 p.m. UTC
I added similar constraints to std::vector recently. The same problem
exists for std::string, so this fixes it.

Tested x86_64-linux. Pushed to trunk.

-- >8 --

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

This change is not sufficient to solve the problem because there are a
large number of member functions which have a default argument that
constructs an allocator.

libstdc++-v3/ChangeLog:

	PR libstdc++/113841
	* include/bits/basic_string.h (basic_string::basic_string()):
	Constrain so that it's only present if the allocator is default
	constructible.
	* include/bits/cow_string.h (basic_string::basic_string()):
	Likewise.
	* testsuite/21_strings/basic_string/cons/113841.cc: New test.
---
 libstdc++-v3/include/bits/basic_string.h      |  3 ++
 libstdc++-v3/include/bits/cow_string.h        |  5 ++++
 .../21_strings/basic_string/cons/113841.cc    | 28 +++++++++++++++++++
 3 files changed, 36 insertions(+)
 create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/cons/113841.cc
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 8a695a494ef..944bd230704 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -526,6 +526,9 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
       _GLIBCXX20_CONSTEXPR
       basic_string()
       _GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Alloc>::value)
+#if __cpp_concepts && __glibcxx_type_trait_variable_templates
+      requires is_default_constructible_v<_Alloc>
+#endif
       : _M_dataplus(_M_local_data())
       {
 	_M_init_local_buf();
diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h
index 75a2d887ad6..2298844f38d 100644
--- a/libstdc++-v3/include/bits/cow_string.h
+++ b/libstdc++-v3/include/bits/cow_string.h
@@ -515,6 +515,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       basic_string()
 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
       _GLIBCXX_NOEXCEPT
+#endif
+#if __cpp_concepts && __glibcxx_type_trait_variable_templates
+      requires is_default_constructible_v<_Alloc>
+#endif
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
       : _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc())
 #else
       : _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc())
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/113841.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/113841.cc
new file mode 100644
index 00000000000..5a08610ea14
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/113841.cc
@@ -0,0 +1,28 @@ 
+// { dg-do compile { target c++20 } }
+
+#include <string>
+
+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 Tr = std::char_traits<char>;
+  using test_type = std::basic_string<char, Tr, Alloc<char>>;
+  std::pair<const int, wrap<test_type>>* h = nullptr;
+  do_adl(h);
+}