[PATCH 1/2] libstdc++: Use format_to for chrono ostream insertion [PR111052]

Anlai Lu agicy@qq.com
Mon Jun 29 12:29:35 GMT 2026


Replace `os << std::format(...)` with `std::format_to(ostreambuf_iterator, ...)`
in chrono operator<< overloads.  This avoids creating a temporary std::string
for the formatted output, instead writing directly to the stream buffer.

This addresses the TODO in the chrono formatter about using format_to
instead of format for ostream insertion (PR libstdc++/111052).  When
combined with a subsequent _Iter_sink<ostreambuf_iterator> specialization,
this also benefits from zero-copy writing directly to the streambuf's
put area.

libstdc++-v3/ChangeLog:

	* include/bits/chrono_io.h (operator<<): Use format_to with
	ostreambuf_iterator instead of os << format.  Check for write
	failure and set badbit on the stream.

Signed-off-by: Anlai Lu <agicy@qq.com>
---
 libstdc++-v3/include/bits/chrono_io.h | 102 +++++++++++++++++++++-----
 1 file changed, 83 insertions(+), 19 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index f8bb485d1..2656bd9c4 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -3635,7 +3635,10 @@ namespace __detail
       if (__d.ok())
 	__s = __s.substr(0, 6);
       auto __u = (unsigned)__d;
-      __os << std::vformat(__s, make_format_args<_Ctx>(__u));
+      auto __it = std::vformat_to(std::ostreambuf_iterator<_CharT>(__os),
+				  __s, make_format_args<_Ctx>(__u));
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
       return __os;
     }
 
@@ -3661,12 +3664,21 @@ namespace __detail
       using _Str = basic_string_view<_CharT>;
       _Str __s = _GLIBCXX_WIDEN("{:L%b}{} is not a valid month");
       if (__m.ok())
-	__os << std::vformat(__os.getloc(), __s.substr(0, 6),
-			     make_format_args<_Ctx>(__m));
+	{
+	  auto __it = std::vformat_to(std::ostreambuf_iterator<_CharT>(__os),
+				      __os.getloc(), __s.substr(0, 6),
+				      make_format_args<_Ctx>(__m));
+	  if (__it.failed())
+	    __os.setstate(ios_base::badbit);
+	}
       else
 	{
 	  auto __u = (unsigned)__m;
-	  __os << std::vformat(__s.substr(6), make_format_args<_Ctx>(__u));
+	  auto __it = std::vformat_to(std::ostreambuf_iterator<_CharT>(__os),
+				      __s.substr(6),
+				      make_format_args<_Ctx>(__u));
+	  if (__it.failed())
+	    __os.setstate(ios_base::badbit);
 	}
       return __os;
     }
@@ -3699,7 +3711,11 @@ namespace __detail
 	__s.remove_prefix(1);
       else
 	__i = -__i;
-      __os << std::vformat(__s, make_format_args<_Ctx>(__i));
+      auto __it = std::vformat_to(std::ostreambuf_iterator<_CharT>(__os),
+		  		  __s,
+		  		  make_format_args<_Ctx>(__i));
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
       return __os;
     }
 
@@ -3725,12 +3741,21 @@ namespace __detail
       using _Str = basic_string_view<_CharT>;
       _Str __s = _GLIBCXX_WIDEN("{:L%a}{} is not a valid weekday");
       if (__wd.ok())
-	__os << std::vformat(__os.getloc(), __s.substr(0, 6),
-			     make_format_args<_Ctx>(__wd));
+	{
+	  auto __it = std::vformat_to(std::ostreambuf_iterator<_CharT>(__os),
+				      __os.getloc(), __s.substr(0, 6),
+				      make_format_args<_Ctx>(__wd));
+	  if (__it.failed())
+	    __os.setstate(ios_base::badbit);
+	}
       else
 	{
 	  auto __c = __wd.c_encoding();
-	  __os << std::vformat(__s.substr(6), make_format_args<_Ctx>(__c));
+	  auto __it = std::vformat_to(std::ostreambuf_iterator<_CharT>(__os),
+				      __s.substr(6),
+				      make_format_args<_Ctx>(__c));
+	  if (__it.failed())
+	    __os.setstate(ios_base::badbit);
 	}
       return __os;
     }
@@ -3764,7 +3789,10 @@ namespace __detail
       basic_string_view<_CharT> __s
 	= _GLIBCXX_WIDEN("[ is not a valid index]");
       __os2 << __s[0];
-      __os2 << std::format(_GLIBCXX_WIDEN("{}"), __i);
+      auto __it_idx = std::format_to(std::ostreambuf_iterator<_CharT>(__os2),
+				     _GLIBCXX_WIDEN("{}"), __i);
+      if (__it_idx.failed())
+	__os2.setstate(ios_base::badbit);
       if (__i >= 1 && __i <= 5)
 	__os2 << __s.back();
       else
@@ -3909,8 +3937,11 @@ namespace __detail
       using _Ctx = __format::__format_context<_CharT>;
       using _Str = basic_string_view<_CharT>;
       _Str __s = _GLIBCXX_WIDEN("{:%F} is not a valid date");
-      __os << std::vformat(__ymd.ok() ? __s.substr(0, 5) : __s,
-			   make_format_args<_Ctx>(__ymd));
+      auto __it = std::vformat_to(std::ostreambuf_iterator<_CharT>(__os),
+				  __ymd.ok() ? __s.substr(0, 5) : __s,
+				  make_format_args<_Ctx>(__ymd));
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
       return __os;
     }
 
@@ -3994,7 +4025,12 @@ namespace __detail
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const hh_mm_ss<_Duration>& __hms)
     {
-      return __os << format(__os.getloc(), _GLIBCXX_WIDEN("{:L%T}"), __hms);
+      auto __it = std::format_to(std::ostreambuf_iterator<_CharT>(__os),
+				 __os.getloc(),
+				 _GLIBCXX_WIDEN("{:L%T}"), __hms);
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
+      return __os;
     }
 
 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
@@ -4003,7 +4039,11 @@ namespace __detail
     basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __i)
     {
-      return __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{}"), __i);
+      auto __it = std::format_to(std::ostreambuf_iterator<_CharT>(__os),
+				 __os.getloc(), _GLIBCXX_WIDEN("{}"), __i);
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
+      return __os;
     }
 
   /// Writes a local_info object to an ostream in an unspecified format.
@@ -4033,7 +4073,11 @@ namespace __detail
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const zoned_time<_Duration, _TimeZonePtr>& __t)
     {
-      __os << format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T %Z}"), __t);
+      auto __it = std::format_to(std::ostreambuf_iterator<_CharT>(__os),
+				 __os.getloc(),
+				 _GLIBCXX_WIDEN("{:L%F %T %Z}"), __t);
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
       return __os;
     }
 #endif
@@ -4045,7 +4089,11 @@ namespace __detail
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const sys_time<_Duration>& __tp)
     {
-      __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __tp);
+      auto __it = std::format_to(std::ostreambuf_iterator<_CharT>(__os),
+				 __os.getloc(),
+				 _GLIBCXX_WIDEN("{:L%F %T}"), __tp);
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
       return __os;
     }
 
@@ -4090,7 +4138,11 @@ namespace __detail
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const utc_time<_Duration>& __t)
     {
-      __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
+      auto __it = std::format_to(std::ostreambuf_iterator<_CharT>(__os),
+				 __os.getloc(),
+				 _GLIBCXX_WIDEN("{:L%F %T}"), __t);
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
       return __os;
     }
 
@@ -4125,7 +4177,11 @@ namespace __detail
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const tai_time<_Duration>& __t)
     {
-      __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
+      auto __it = std::format_to(std::ostreambuf_iterator<_CharT>(__os),
+				 __os.getloc(),
+				 _GLIBCXX_WIDEN("{:L%F %T}"), __t);
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
       return __os;
     }
 
@@ -4164,7 +4220,11 @@ namespace __detail
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const gps_time<_Duration>& __t)
     {
-      __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
+      auto __it = std::format_to(std::ostreambuf_iterator<_CharT>(__os),
+				 __os.getloc(),
+				 _GLIBCXX_WIDEN("{:L%F %T}"), __t);
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
       return __os;
     }
 
@@ -4202,7 +4262,11 @@ namespace __detail
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const file_time<_Duration>& __t)
     {
-      __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
+      auto __it = std::format_to(std::ostreambuf_iterator<_CharT>(__os),
+				 __os.getloc(),
+				 _GLIBCXX_WIDEN("{:L%F %T}"), __t);
+      if (__it.failed())
+	__os.setstate(ios_base::badbit);
       return __os;
     }
 
-- 
2.34.1



More information about the Libstdc++ mailing list