[libcxx-commits] [libcxx] [libc++] Use std::to_chars to format thread::id (PR #181624)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Thu Feb 19 03:48:11 PST 2026


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/181624

>From 350f439c408b5bfcb663e542b10aafe07a72283f Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 16 Feb 2026 11:40:25 +0100
Subject: [PATCH] [libc++] Use std::to_string to format thread::id

---
 libcxx/include/__thread/formatter.h           |  6 +----
 libcxx/include/__thread/thread.h              | 23 +++++++++++--------
 libcxx/include/future                         |  5 ++++
 libcxx/include/module.modulemap.in            |  5 +++-
 libcxx/include/thread                         |  5 ++++
 .../test/libcxx/transitive_includes/cxx26.csv | 13 -----------
 6 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/libcxx/include/__thread/formatter.h b/libcxx/include/__thread/formatter.h
index 826607d47b469..bf5b08bbcb23a 100644
--- a/libcxx/include/__thread/formatter.h
+++ b/libcxx/include/__thread/formatter.h
@@ -61,11 +61,7 @@ struct formatter<__thread_id, _CharT> {
     static_assert(!is_same_v<_Cp, void>, "unsupported thread::id type, please file a bug report");
 
     __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx);
-    if constexpr (is_pointer_v<_Tp>) {
-      __specs.__std_.__alternate_form_ = true;
-      __specs.__std_.__type_           = __format_spec::__type::__hexadecimal_lower_case;
-    }
-    return __formatter::__format_integer(reinterpret_cast<_Cp>(__get_underlying_id(__id)), __ctx, __specs);
+    return __formatter::__format_integer(__get_underlying_id(__id), __ctx, __specs);
   }
 
   __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__right};
diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h
index b2f51aa816c10..129362caaf4b0 100644
--- a/libcxx/include/__thread/thread.h
+++ b/libcxx/include/__thread/thread.h
@@ -11,12 +11,13 @@
 #define _LIBCPP___THREAD_THREAD_H
 
 #include <__assert>
+#include <__charconv/to_chars_integral.h>
 #include <__condition_variable/condition_variable.h>
 #include <__config>
 #include <__exception/terminate.h>
 #include <__functional/hash.h>
 #include <__functional/unary_function.h>
-#include <__locale>
+#include <__fwd/ostream.h>
 #include <__memory/addressof.h>
 #include <__memory/unique_ptr.h>
 #include <__mutex/mutex.h>
@@ -27,15 +28,14 @@
 #include <__type_traits/enable_if.h>
 #include <__type_traits/invoke.h>
 #include <__type_traits/is_constructible.h>
+#include <__type_traits/is_pointer.h>
 #include <__type_traits/is_same.h>
 #include <__type_traits/remove_cvref.h>
 #include <__utility/forward.h>
+#include <cstdint>
+#include <limits>
 #include <tuple>
 
-#if _LIBCPP_HAS_LOCALIZATION
-#  include <sstream>
-#endif
-
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
 #endif
@@ -147,10 +147,15 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) {
   // use a temporary stream instead and just output the thread
   // id representation as a string.
 
-  basic_ostringstream<_CharT, _Traits> __sstr;
-  __sstr.imbue(locale::classic());
-  __sstr << __id.__id_;
-  return __os << __sstr.str();
+  using __int_type = __conditional_t<is_pointer<__libcpp_thread_t>::value, uintptr_t, __libcpp_thread_t>;
+
+  static const size_t __buffer_size = numeric_limits<__libcpp_thread_t>::digits10 + 1;
+  char __buffer[__buffer_size];
+  auto __ret =
+      std::__to_chars_integral(__buffer, __buffer + __buffer_size - 1, reinterpret_cast<__int_type>(__id.__id_), 10);
+  _LIBCPP_ASSERT_INTERNAL(__ret.__ec == std::errc(), "to_chars failed!");
+  *__ret.__ptr = '\0';
+  return __os << __buffer;
 }
 #  endif // _LIBCPP_HAS_LOCALIZATION
 
diff --git a/libcxx/include/future b/libcxx/include/future
index 4084148e52af6..a99a7ae486490 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -2075,6 +2075,11 @@ _LIBCPP_POP_MACROS
 #    include <system_error>
 #    include <thread>
 #  endif
+
+#  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23
+#    include <sstream>
+#  endif
+
 #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
 
 #endif // _LIBCPP_FUTURE
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 9012ed18cbd79..03c26f6c59c4c 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -948,7 +948,10 @@ module std [system] {
       header "__charconv/to_chars_integral.h"
       export std.charconv.to_chars_result
     }
-    module to_chars_result            { header "__charconv/to_chars_result.h" }
+    module to_chars_result            {
+      header "__charconv/to_chars_result.h"
+      export std.system_error.errc
+    }
     module traits                     { header "__charconv/traits.h" }
 
     header "charconv"
diff --git a/libcxx/include/thread b/libcxx/include/thread
index 029ed418e2070..e14e47d02788b 100644
--- a/libcxx/include/thread
+++ b/libcxx/include/thread
@@ -128,6 +128,11 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time);
 #    include <system_error>
 #    include <type_traits>
 #  endif
+
+#  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23
+#    include <sstream>
+#  endif
+
 #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
 
 #endif // _LIBCPP_THREAD
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index c11fb5ac10016..d2667ece5123c 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -425,29 +425,21 @@ functional tuple
 functional typeinfo
 functional unordered_map
 functional version
-future bitset
 future cctype
 future cerrno
 future climits
-future clocale
 future compare
-future cstddef
 future cstdint
 future cstdio
-future cstdlib
 future cstring
 future ctime
 future cwchar
 future cwctype
 future initializer_list
-future ios
 future iosfwd
-future istream
 future limits
 future ratio
-future sstream
 future stdexcept
-future streambuf
 future string
 future string_view
 future tuple
@@ -1050,7 +1042,6 @@ system_error tuple
 system_error version
 thread array
 thread atomic
-thread bitset
 thread cctype
 thread cerrno
 thread climits
@@ -1065,14 +1056,10 @@ thread ctime
 thread cwchar
 thread cwctype
 thread initializer_list
-thread ios
 thread iosfwd
-thread istream
 thread limits
 thread ratio
-thread sstream
 thread stdexcept
-thread streambuf
 thread string
 thread string_view
 thread tuple



More information about the libcxx-commits mailing list