In C++26 paper P3391 has been adopted, part of which marks
std::to_string & std::to_wstring for integers as constexpr.
Since pre-cxx11 copy-on-write string is not constexpr-enabled,
restricting this constexpr-ification to cxx11 ABI strings.

libstdc++-v3/ChangeLog:

        * include/bits/basic_string.h: Mark integer to_(w)string constexpr.
        * 
testsuite/21_strings/basic_string/numeric_conversions/char/to_string_constexpr.cc:
        New test.
        * 
testsuite/21_strings/basic_string/numeric_conversions/wchar_t/to_wstring_constexpr.cc:
        New test.
---
This seems nice and disjoint from the rest so extracted it.

Guarding via _GLIBCXX_USE_CXX11_ABI, don't know if it is meaningful
to guard via constexpr_format since
https://cplusplus.github.io/LWG/issue4531
will bump a different macro.
We could also wait with this for the LWG issue to be resolved.

Tests I've been running, on x86-64 linux, with 
GLIBCXX_TESTSUITE_STDS=11,14,17,20,23,26:
```
19_diagnostics/stacktrace/output.cc
19_diagnostics/stacktrace/synopsis.cc
20_util/bitset/access/constexpr.cc
20_util/bitset/access/dr396.cc
20_util/bitset/access/to_string.cc
20_util/bitset/cons/6282.cc
20_util/bitset/cons/dr396.cc
20_util/from_chars/4.cc
20_util/from_chars/8.cc
20_util/to_chars/1.cc
21_strings/basic_string/numeric_conversions/char/dr1261.cc
21_strings/basic_string/numeric_conversions/char/stod.cc
21_strings/basic_string/numeric_conversions/char/stof.cc
21_strings/basic_string/numeric_conversions/char/stoi.cc
21_strings/basic_string/numeric_conversions/char/stol.cc
21_strings/basic_string/numeric_conversions/char/stold.cc
21_strings/basic_string/numeric_conversions/char/stoll.cc
21_strings/basic_string/numeric_conversions/char/stoul.cc
21_strings/basic_string/numeric_conversions/char/stoull.cc
21_strings/basic_string/numeric_conversions/char/to_string.cc
21_strings/basic_string/numeric_conversions/char/to_string_constexpr.cc
21_strings/basic_string/numeric_conversions/char/to_string_float.cc
21_strings/basic_string/numeric_conversions/char/to_string_int.cc
21_strings/basic_string/numeric_conversions/version.cc
21_strings/basic_string/numeric_conversions/wchar_t/dr1261.cc
21_strings/basic_string/numeric_conversions/wchar_t/stod.cc
21_strings/basic_string/numeric_conversions/wchar_t/stof.cc
21_strings/basic_string/numeric_conversions/wchar_t/stoi.cc
21_strings/basic_string/numeric_conversions/wchar_t/stol.cc
21_strings/basic_string/numeric_conversions/wchar_t/stold.cc
21_strings/basic_string/numeric_conversions/wchar_t/stoll.cc
21_strings/basic_string/numeric_conversions/wchar_t/stoul.cc
21_strings/basic_string/numeric_conversions/wchar_t/stoull.cc
21_strings/basic_string/numeric_conversions/wchar_t/to_wstring.cc
21_strings/basic_string/numeric_conversions/wchar_t/to_wstring_constexpr.cc
21_strings/basic_string/numeric_conversions/wchar_t/to_wstring_float.cc
21_strings/basic_string_view/operations/string_conversion/1.cc
27_io/filesystem/operations/copy_file_108178.cc
28_regex/basic_regex/106607.cc
experimental/net/internet/address/v4/members.cc
experimental/net/internet/address/v6/members.cc
experimental/net/internet/network/v4/members.cc
experimental/string_view/operations/to_string/1.cc
performance/26_numerics/random_dist.cc
std/ranges/adaptors/lazy_split.cc
std/ranges/adaptors/split.cc
util/regression/trait/assoc/to_string.hpp
util/regression/trait/assoc/trait.hpp
util/testsuite_fs.h
```

 libstdc++-v3/include/bits/basic_string.h      | 36 ++++++++++
 .../char/to_string_constexpr.cc               | 67 +++++++++++++++++++
 .../wchar_t/to_wstring_constexpr.cc           | 67 +++++++++++++++++++
 3 files changed, 170 insertions(+)
 create mode 100644 
libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string_constexpr.cc
 create mode 100644 
libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/to_wstring_constexpr.cc

diff --git a/libstdc++-v3/include/bits/basic_string.h 
b/libstdc++-v3/include/bits/basic_string.h
index 9bbe16507d0..948f86007ae 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -4582,6 +4582,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   // DR 1261. Insufficent overloads for to_string / to_wstring
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline string
   to_string(int __val)
 #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_INT__) <= 32
@@ -4601,6 +4604,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   }
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline string
   to_string(unsigned __val)
 #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_INT__) <= 32
@@ -4617,6 +4623,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   }
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline string
   to_string(long __val)
 #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_LONG__) <= 32
@@ -4636,6 +4645,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   }
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline string
   to_string(unsigned long __val)
 #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_LONG__) <= 32
@@ -4652,6 +4664,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   }
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline string
   to_string(long long __val)
   {
@@ -4669,6 +4684,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   }
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline string
   to_string(unsigned long long __val)
   {
@@ -4893,31 +4911,49 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 #pragma GCC diagnostic pop
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline wstring
   to_wstring(int __val)
   { return std::__to_wstring_numeric(std::to_string(__val)); }
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline wstring
   to_wstring(unsigned __val)
   { return std::__to_wstring_numeric(std::to_string(__val)); }
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline wstring
   to_wstring(long __val)
   { return std::__to_wstring_numeric(std::to_string(__val)); }
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline wstring
   to_wstring(unsigned long __val)
   { return std::__to_wstring_numeric(std::to_string(__val)); }
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline wstring
   to_wstring(long long __val)
   { return std::__to_wstring_numeric(std::to_string(__val)); }
 
   _GLIBCXX_NODISCARD
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+  _GLIBCXX26_CONSTEXPR
+#endif
   inline wstring
   to_wstring(unsigned long long __val)
   { return std::__to_wstring_numeric(std::to_string(__val)); }
diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string_constexpr.cc
 
b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string_constexpr.cc
new file mode 100644
index 00000000000..44761b7884b
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string_constexpr.cc
@@ -0,0 +1,67 @@
+// { dg-do compile { target c++26 } }
+
+#include <string>
+#include <type_traits>
+#include <testsuite_hooks.h>
+
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+
+template<typename T>
+constexpr void
+test()
+{
+  using namespace std;
+  string res;
+  T value;
+
+  value = 0;
+  res = to_string(value);
+  VERIFY( res == "0" );
+
+  value = 1;
+  res = to_string(value);
+  VERIFY( res == "1" );
+
+  value = 10;
+  res = to_string(value);
+  VERIFY( res == "10" );
+  
+  value = 3000;
+  res = to_string(value);
+  VERIFY( res == "3000" );
+
+  value = 32767;
+  res = to_string(value);
+  VERIFY( res == "32767" );
+
+  if (is_unsigned_v<T>)
+    return;
+
+  value = -1;
+  res = to_string(value);
+  VERIFY( res == "-1" );
+  
+  value = -40;
+  res = to_string(value);
+  VERIFY( res == "-40" );
+  
+  value = -32768;
+  res = to_string(value);
+  VERIFY( res == "-32768" );
+}
+
+constexpr bool
+test_all()
+{
+  test<int>();
+  test<unsigned int>();
+  test<long>();
+  test<unsigned long>();
+  test<long long>();
+  test<unsigned long long>();
+  return true;
+}
+
+static_assert(test_all());
+
+#endif
diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/to_wstring_constexpr.cc
 
b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/to_wstring_constexpr.cc
new file mode 100644
index 00000000000..8eeff3b132d
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/to_wstring_constexpr.cc
@@ -0,0 +1,67 @@
+// { dg-do compile { target c++26 } }
+
+#include <string>
+#include <type_traits>
+#include <testsuite_hooks.h>
+
+#if _GLIBCXX_USE_CXX11_ABI // cow_string is not constexpr-enabled
+
+template<typename T>
+constexpr void
+test()
+{
+  using namespace std;
+  wstring res;
+  T value;
+
+  value = 0;
+  res = to_wstring(value);
+  VERIFY( res == L"0" );
+
+  value = 1;
+  res = to_wstring(value);
+  VERIFY( res == L"1" );
+
+  value = 10;
+  res = to_wstring(value);
+  VERIFY( res == L"10" );
+  
+  value = 3000;
+  res = to_wstring(value);
+  VERIFY( res == L"3000" );
+
+  value = 32767;
+  res = to_wstring(value);
+  VERIFY( res == L"32767" );
+
+  if (is_unsigned_v<T>)
+    return;
+
+  value = -1;
+  res = to_wstring(value);
+  VERIFY( res == L"-1" );
+  
+  value = -40;
+  res = to_wstring(value);
+  VERIFY( res == L"-40" );
+  
+  value = -32768;
+  res = to_wstring(value);
+  VERIFY( res == L"-32768" );
+}
+
+constexpr bool
+test_all()
+{
+  test<int>();
+  test<unsigned int>();
+  test<long>();
+  test<unsigned long>();
+  test<long long>();
+  test<unsigned long long>();
+  return true;
+}
+
+static_assert(test_all());
+
+#endif
-- 
2.43.0

Reply via email to