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