* [committed] libstdc++: Rework std::format support for wchar_t
@ 2023-08-17 20:31 Jonathan Wakely
2023-08-18 8:44 ` [committed] libstdc++: Fix incomplete rework of wchar_t support in std::format Jonathan Wakely
0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Wakely @ 2023-08-17 20:31 UTC (permalink / raw)
To: libstdc++, gcc-patches
Tested x86_64-linux. Pushed to trunk.
-- >8 --
This changes how std::format creates wide strings, by replacing uses of
std::ctype<wchar_t>::widen with the recently-added __to_wstring_numeric
helper function. This removes the dependency on the locale, which should
only be used for locale-specific formats such as {:Ld}.
Also disable all the wide string formatting support if the
_GLIBCXX_USE_WCHAR_T macro is not defined. This is consistent with other
wchar_t support being disabled if the library is built without that
macro defined.
libstdc++-v3/ChangeLog:
* include/std/format [_GLIBCXX_USE_WCHAR_T]: Guard all wide
string formatters with this macro.
(__formatter_int::_M_format_int, __formatter_fp::format)
(formatter<const void*, C>::format): Use __to_wstring_numeric
instead of std::ctype::widen.
(__formatter_fp::_M_localize): Use hardcoded wchar_t values
instead of std::ctype::widen.
* testsuite/std/format/functions/format.cc: Add more checks for
wstring formatting of arithmetic types.
---
libstdc++-v3/include/std/format | 108 ++++++++++++------
.../testsuite/std/format/functions/format.cc | 10 ++
2 files changed, 82 insertions(+), 36 deletions(-)
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 0d7d3d16420..79f810acce3 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -79,8 +79,10 @@ namespace __format
using format_context
= basic_format_context<__format::_Sink_iter<char>, char>;
+#ifdef _GLIBCXX_USE_WCHAR_T
using wformat_context
= basic_format_context<__format::_Sink_iter<wchar_t>, wchar_t>;
+#endif
// [format.args], class template basic_format_args
template<typename _Context> class basic_format_args;
@@ -118,9 +120,11 @@ namespace __format
template<typename... _Args>
using format_string = basic_format_string<char, type_identity_t<_Args>...>;
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename... _Args>
using wformat_string
= basic_format_string<wchar_t, type_identity_t<_Args>...>;
+#endif
// [format.formatter], formatter
@@ -181,7 +185,9 @@ namespace __format
// [format.parse.ctx], class template basic_format_parse_context
template<typename _CharT> class basic_format_parse_context;
using format_parse_context = basic_format_parse_context<char>;
+#ifdef _GLIBCXX_USE_WCHAR_T
using wformat_parse_context = basic_format_parse_context<wchar_t>;
+#endif
template<typename _CharT>
class basic_format_parse_context
@@ -745,8 +751,13 @@ namespace __format
bool _M_hasval = false;
};
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _CharT>
concept __char = same_as<_CharT, char> || same_as<_CharT, wchar_t>;
+#else
+ template<typename _CharT>
+ concept __char = same_as<_CharT, char>;
+#endif
template<__char _CharT>
struct __formatter_str
@@ -1125,26 +1136,20 @@ namespace __format
{
size_t __width = _M_spec._M_get_width(__fc);
- _Optional_locale __loc;
-
basic_string_view<_CharT> __str;
if constexpr (is_same_v<char, _CharT>)
__str = __narrow_str;
else
{
- __loc = __fc.locale();
- auto& __ct = use_facet<ctype<_CharT>>(__loc.value());
size_t __n = __narrow_str.size();
auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
- __ct.widen(__narrow_str.data(), __narrow_str.data() + __n, __p);
+ __to_wstring_numeric(__narrow_str.data(), __n, __p);
__str = {__p, __n};
}
if (_M_spec._M_localized)
{
- if constexpr (is_same_v<char, _CharT>)
- __loc = __fc.locale();
- const auto& __l = __loc.value();
+ const auto& __l = __fc.locale();
if (__l.name() != "C")
{
auto& __np = use_facet<numpunct<_CharT>>(__l);
@@ -1612,35 +1617,19 @@ namespace __format
}
}
- // TODO move everything below to a new member function that
- // doesn't depend on _Fp type.
-
-
- _Optional_locale __loc;
basic_string<_CharT> __wstr;
basic_string_view<_CharT> __str;
if constexpr (is_same_v<_CharT, char>)
__str = __narrow_str;
else
{
- __loc = __fc.locale();
- auto& __ct = use_facet<ctype<_CharT>>(__loc.value());
- const char* __data = __narrow_str.data();
- auto __overwrite = [&__data, &__ct](_CharT* __p, size_t __n)
- {
- __ct.widen(__data, __data + __n, __p);
- return __n;
- };
- _S_resize_and_overwrite(__wstr, __narrow_str.size(), __overwrite);
+ __wstr = std::__to_wstring_numeric(__narrow_str);
__str = __wstr;
}
if (_M_spec._M_localized)
{
- if constexpr (is_same_v<char, _CharT>)
- __wstr = _M_localize(__str, __expc, __fc.locale());
- else
- __wstr = _M_localize(__str, __expc, __loc.value());
+ __wstr = _M_localize(__str, __expc, __fc.locale());
if (!__wstr.empty())
__str = __wstr;
}
@@ -1697,9 +1686,24 @@ namespace __format
}
else
{
- const auto& __ct = use_facet<ctype<_CharT>>(__loc);
- __dot = __ct.widen('.');
- __exp = __ct.widen(__expc);
+ __dot = L'.';
+ switch (__expc)
+ {
+ case 'e':
+ __exp = L'e';
+ break;
+ case 'E':
+ __exp = L'E';
+ break;
+ case 'p':
+ __exp = L'p';
+ break;
+ case 'P':
+ __exp = L'P';
+ break;
+ default:
+ __builtin_unreachable();
+ }
}
if (__grp.empty() && __point == __dot)
@@ -1737,7 +1741,7 @@ namespace __format
} // namespace __format
/// @endcond
- // Format a character.
+ /// Format a character.
template<__format::__char _CharT>
struct formatter<_CharT, _CharT>
{
@@ -1774,7 +1778,8 @@ namespace __format
__format::__formatter_int<_CharT> _M_f;
};
- // Format a char value for wide character output.
+#ifdef _GLIBCXX_USE_WCHAR_T
+ /// Format a char value for wide character output.
template<>
struct formatter<char, wchar_t>
{
@@ -1808,6 +1813,7 @@ namespace __format
private:
__format::__formatter_int<wchar_t> _M_f;
};
+#endif // USE_WCHAR_T
/** Format a string.
* @{
@@ -1903,6 +1909,7 @@ namespace __format
__format::__formatter_str<char> _M_f;
};
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _Traits, typename _Alloc>
struct formatter<basic_string<wchar_t, _Traits, _Alloc>, wchar_t>
{
@@ -1926,6 +1933,7 @@ namespace __format
private:
__format::__formatter_str<wchar_t> _M_f;
};
+#endif // USE_WCHAR_T
template<typename _Traits>
struct formatter<basic_string_view<char, _Traits>, char>
@@ -1951,6 +1959,7 @@ namespace __format
__format::__formatter_str<char> _M_f;
};
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _Traits>
struct formatter<basic_string_view<wchar_t, _Traits>, wchar_t>
{
@@ -1974,6 +1983,7 @@ namespace __format
private:
__format::__formatter_str<wchar_t> _M_f;
};
+#endif // USE_WCHAR_T
/// @}
/// Format an integer.
@@ -2144,10 +2154,8 @@ namespace __format
__str = string_view(__buf, __n);
else
{
- const std::locale& __loc = __fc.locale();
- auto& __ct = use_facet<ctype<_CharT>>(__loc);
auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
- __ct.widen(__buf, __buf + __n, __p);
+ __to_wstring_numeric(__buf, __n, __p);
__str = wstring_view(__p, __n);
}
@@ -3698,25 +3706,33 @@ namespace __format
vformat_to(_Out __out, string_view __fmt, format_args __args)
{ return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _Out> requires output_iterator<_Out, const wchar_t&>
[[__gnu__::__always_inline__]]
inline _Out
vformat_to(_Out __out, wstring_view __fmt, wformat_args __args)
{ return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
+#endif
template<typename _Out> requires output_iterator<_Out, const char&>
[[__gnu__::__always_inline__]]
inline _Out
vformat_to(_Out __out, const locale& __loc, string_view __fmt,
format_args __args)
- { return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc); }
+ {
+ return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
+ }
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _Out> requires output_iterator<_Out, const wchar_t&>
[[__gnu__::__always_inline__]]
inline _Out
vformat_to(_Out __out, const locale& __loc, wstring_view __fmt,
wformat_args __args)
- { return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc); }
+ {
+ return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
+ }
+#endif
[[nodiscard]]
inline string
@@ -3727,6 +3743,7 @@ namespace __format
return std::move(__buf).get();
}
+#ifdef _GLIBCXX_USE_WCHAR_T
[[nodiscard]]
inline wstring
vformat(wstring_view __fmt, wformat_args __args)
@@ -3735,6 +3752,7 @@ namespace __format
std::vformat_to(__buf.out(), __fmt, __args);
return std::move(__buf).get();
}
+#endif
[[nodiscard]]
inline string
@@ -3745,6 +3763,7 @@ namespace __format
return std::move(__buf).get();
}
+#ifdef _GLIBCXX_USE_WCHAR_T
[[nodiscard]]
inline wstring
vformat(const locale& __loc, wstring_view __fmt, wformat_args __args)
@@ -3753,6 +3772,7 @@ namespace __format
std::vformat_to(__buf.out(), __loc, __fmt, __args);
return std::move(__buf).get();
}
+#endif
template<typename... _Args>
[[nodiscard]]
@@ -3760,11 +3780,13 @@ namespace __format
format(format_string<_Args...> __fmt, _Args&&... __args)
{ return std::vformat(__fmt.get(), std::make_format_args(__args...)); }
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename... _Args>
[[nodiscard]]
inline wstring
format(wformat_string<_Args...> __fmt, _Args&&... __args)
{ return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); }
+#endif
template<typename... _Args>
[[nodiscard]]
@@ -3776,6 +3798,7 @@ namespace __format
std::make_format_args(__args...));
}
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename... _Args>
[[nodiscard]]
inline wstring
@@ -3785,6 +3808,7 @@ namespace __format
return std::vformat(__loc, __fmt.get(),
std::make_wformat_args(__args...));
}
+#endif
template<typename _Out, typename... _Args>
requires output_iterator<_Out, const char&>
@@ -3795,6 +3819,7 @@ namespace __format
std::make_format_args(std::forward<_Args>(__args)...));
}
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _Out, typename... _Args>
requires output_iterator<_Out, const wchar_t&>
inline _Out
@@ -3803,6 +3828,7 @@ namespace __format
return std::vformat_to(std::move(__out), __fmt.get(),
std::make_wformat_args(std::forward<_Args>(__args)...));
}
+#endif
template<typename _Out, typename... _Args>
requires output_iterator<_Out, const char&>
@@ -3814,6 +3840,7 @@ namespace __format
std::make_format_args(std::forward<_Args>(__args)...));
}
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _Out, typename... _Args>
requires output_iterator<_Out, const wchar_t&>
inline _Out
@@ -3823,6 +3850,7 @@ namespace __format
return std::vformat_to(std::move(__out), __loc, __fmt.get(),
std::make_wformat_args(std::forward<_Args>(__args)...));
}
+#endif
template<typename _Out, typename... _Args>
requires output_iterator<_Out, const char&>
@@ -3836,6 +3864,7 @@ namespace __format
return std::move(__sink)._M_finish();
}
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _Out, typename... _Args>
requires output_iterator<_Out, const wchar_t&>
inline format_to_n_result<_Out>
@@ -3847,6 +3876,7 @@ namespace __format
std::make_wformat_args(__args...));
return std::move(__sink)._M_finish();
}
+#endif
template<typename _Out, typename... _Args>
requires output_iterator<_Out, const char&>
@@ -3860,6 +3890,7 @@ namespace __format
return std::move(__sink)._M_finish();
}
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _Out, typename... _Args>
requires output_iterator<_Out, const wchar_t&>
inline format_to_n_result<_Out>
@@ -3871,6 +3902,7 @@ namespace __format
std::make_wformat_args(__args...));
return std::move(__sink)._M_finish();
}
+#endif
/// @cond undocumented
namespace __format
@@ -3927,6 +3959,7 @@ namespace __format
return __buf.count();
}
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename... _Args>
[[nodiscard]]
inline size_t
@@ -3937,6 +3970,7 @@ namespace __format
std::make_wformat_args(std::forward<_Args>(__args)...));
return __buf.count();
}
+#endif
template<typename... _Args>
[[nodiscard]]
@@ -3950,6 +3984,7 @@ namespace __format
return __buf.count();
}
+#ifdef _GLIBCXX_USE_WCHAR_T
template<typename... _Args>
[[nodiscard]]
inline size_t
@@ -3961,6 +3996,7 @@ namespace __format
std::make_wformat_args(std::forward<_Args>(__args)...));
return __buf.count();
}
+#endif
#if __cpp_lib_format_ranges
// [format.range], formatting of ranges
diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc b/libstdc++-v3/testsuite/std/format/functions/format.cc
index 59ed3be8baa..59d327fccee 100644
--- a/libstdc++-v3/testsuite/std/format/functions/format.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
@@ -274,6 +274,16 @@ test_wchar()
VERIFY( s == L"0.0625" );
s = std::format(L"{}", 0.25);
VERIFY( s == L"0.25" );
+ s = std::format(L"{:+a} {:A}", 0x1.23p45, -0x1.abcdefp-15);
+ VERIFY( s == L"+1.23p+45 -1.ABCDEFP-15" );
+
+ double inf = std::numeric_limits<double>::infinity();
+ double nan = std::numeric_limits<double>::quiet_NaN();
+ s = std::format(L"{0} {0:F} {1} {1:E}", -inf, -nan);
+ VERIFY( s == L"-inf -INF -nan -NAN" );
+
+ s = std::format(L"{0:#b} {0:#B} {0:#x} {0:#X}", 99);
+ VERIFY( s == L"0b1100011 0B1100011 0x63 0X63" );
}
void
--
2.41.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [committed] libstdc++: Fix incomplete rework of wchar_t support in std::format
2023-08-17 20:31 [committed] libstdc++: Rework std::format support for wchar_t Jonathan Wakely
@ 2023-08-18 8:44 ` Jonathan Wakely
2023-08-18 11:31 ` [committed] libstdc++: Replace non-type-dependent uses of wchar_t in <format> and <chrono> Jonathan Wakely
0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Wakely @ 2023-08-18 8:44 UTC (permalink / raw)
To: libstdc++, gcc-patches
Tested x86_64-linux. Pushed to trunk.
-- >8 --
r14-3300-g023a62b77f999b left make_wformat_args and some uses of
std::wformat_context unguarded by _GLIBCXX_USE_WCHAR_T.
libstdc++-v3/ChangeLog:
* include/bits/chrono_io.h (operator<<): Use __format_context.
* include/std/format (__format::__format_context): New alias
template.
[!_GLIBCXX_USE_WCHAR_T] (wformat_args, make_wformat_arg):
Disable.
---
libstdc++-v3/include/bits/chrono_io.h | 15 +++++----------
libstdc++-v3/include/std/format | 13 +++++++++----
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index 05caa64fb7c..e16302baf84 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -2263,8 +2263,7 @@ namespace __detail
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d)
{
- using _Ctx = __conditional_t<is_same_v<_CharT, char>,
- format_context, wformat_context>;
+ using _Ctx = __format::__format_context<_CharT>;
using _Str = basic_string_view<_CharT>;
_Str __s = _GLIBCXX_WIDEN("{:02d} is not a valid day");
if (__d.ok())
@@ -2291,8 +2290,7 @@ namespace __detail
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m)
{
- using _Ctx = __conditional_t<is_same_v<_CharT, char>,
- format_context, wformat_context>;
+ using _Ctx = __format::__format_context<_CharT>;
using _Str = basic_string_view<_CharT>;
_Str __s = _GLIBCXX_WIDEN("{:L%b}{} is not a valid month");
if (__m.ok())
@@ -2322,8 +2320,7 @@ namespace __detail
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y)
{
- using _Ctx = __conditional_t<is_same_v<_CharT, char>,
- format_context, wformat_context>;
+ using _Ctx = __format::__format_context<_CharT>;
using _Str = basic_string_view<_CharT>;
_Str __s = _GLIBCXX_WIDEN("-{:04d} is not a valid year");
if (__y.ok())
@@ -2355,8 +2352,7 @@ namespace __detail
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd)
{
- using _Ctx = __conditional_t<is_same_v<_CharT, char>,
- format_context, wformat_context>;
+ using _Ctx = __format::__format_context<_CharT>;
using _Str = basic_string_view<_CharT>;
_Str __s = _GLIBCXX_WIDEN("{:L%a}{} is not a valid weekday");
if (__wd.ok())
@@ -2544,8 +2540,7 @@ namespace __detail
operator<<(basic_ostream<_CharT, _Traits>& __os,
const year_month_day& __ymd)
{
- using _Ctx = __conditional_t<is_same_v<_CharT, char>,
- format_context, wformat_context>;
+ 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,
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 13f700a10bf..0b1ae8201af 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -74,20 +74,23 @@ namespace __format
// Output iterator that writes to a type-erase character sink.
template<typename _CharT>
class _Sink_iter;
+
+ template<typename _CharT>
+ using __format_context = basic_format_context<_Sink_iter<_CharT>, _CharT>;
} // namespace __format
/// @endcond
- using format_context
- = basic_format_context<__format::_Sink_iter<char>, char>;
+ using format_context = __format::__format_context<char>;
#ifdef _GLIBCXX_USE_WCHAR_T
- using wformat_context
- = basic_format_context<__format::_Sink_iter<wchar_t>, wchar_t>;
+ using wformat_context = __format::__format_context<wchar_t>;
#endif
// [format.args], class template basic_format_args
template<typename _Context> class basic_format_args;
using format_args = basic_format_args<format_context>;
+#ifdef _GLIBCXX_USE_WCHAR_T
using wformat_args = basic_format_args<wformat_context>;
+#endif
// [format.arguments], arguments
// [format.arg], class template basic_format_arg
@@ -3505,12 +3508,14 @@ namespace __format
return _Store(__fmt_args...);
}
+#ifdef _GLIBCXX_USE_WCHAR_T
/// Capture formatting arguments for use by `std::vformat` (for wide output).
template<typename... _Args>
[[nodiscard,__gnu__::__always_inline__]]
inline auto
make_wformat_args(_Args&&... __args) noexcept
{ return std::make_format_args<wformat_context>(__args...); }
+#endif
/// @cond undocumented
namespace __format
--
2.41.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [committed] libstdc++: Replace non-type-dependent uses of wchar_t in <format> and <chrono>
2023-08-18 8:44 ` [committed] libstdc++: Fix incomplete rework of wchar_t support in std::format Jonathan Wakely
@ 2023-08-18 11:31 ` Jonathan Wakely
0 siblings, 0 replies; 3+ messages in thread
From: Jonathan Wakely @ 2023-08-18 11:31 UTC (permalink / raw)
To: libstdc++, gcc-patches
This should be really fixed now!
Tested x86_64-linux. Pushed to trunk.
-- >8 --
This is one more piece of the rework to make wchar_t support in
std::format depend on _GLIBCXX_USE_WCHAR_T.
In <format> the __to_wstring_numeric function is called with arguments
that aren't type-dependent, so a declaration needs to be available, or
the calls need to be guarded by _GLIBCXX_USE_WCHAR_T.
In <chrono> there is a similarly non-type-dependent call to std::format
with a wchar_t format string, which is ill-formed when the wchar_t
overloads of std::format are not declared. Use _GLIBCXX_WIDEN to make it
type-dependent.
libstdc++-v3/ChangeLog:
* include/bits/chrono_io.h (operator<<): Make uses of wide
strings with streams and std::format type-dependent on _CharT.
* include/std/format [!_GLIBCXX_USE_WCHAR_T] Do not use
__to_wstring_numeric.
---
libstdc++-v3/include/bits/chrono_io.h | 17 ++++++-----------
libstdc++-v3/include/std/format | 10 ++++++++--
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index e16302baf84..d558802e7d8 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -2390,15 +2390,14 @@ namespace __detail
__os2.imbue(__os.getloc());
__os2 << __wdi.weekday();
const auto __i = __wdi.index();
- if constexpr (is_same_v<_CharT, char>)
- __os2 << std::format("[{}", __i);
- else
- __os2 << std::format(L"[{}", __i);
- basic_string_view<_CharT> __s = _GLIBCXX_WIDEN(" is not a valid index]");
+ basic_string_view<_CharT> __s
+ = _GLIBCXX_WIDEN("[ is not a valid index]");
+ __os2 << __s[0];
+ __os2 << std::format(_GLIBCXX_WIDEN("{}"), __i);
if (__i >= 1 && __i <= 5)
__os2 << __s.back();
else
- __os2 << __s;
+ __os2 << __s.substr(1);
__os << __os2.view();
return __os;
}
@@ -2457,11 +2456,7 @@ namespace __detail
// As above, just write straight to a stringstream, as if by "{:L}/last"
basic_stringstream<_CharT> __os2;
__os2.imbue(__os.getloc());
- __os2 << __mdl.month();
- if constexpr (is_same_v<_CharT, char>)
- __os2 << "/last";
- else
- __os2 << L"/last";
+ __os2 << __mdl.month() << _GLIBCXX_WIDEN("/last");
__os << __os2.view();
return __os;
}
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 0b1ae8201af..648f847ad96 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -1142,13 +1142,15 @@ namespace __format
basic_string_view<_CharT> __str;
if constexpr (is_same_v<char, _CharT>)
__str = __narrow_str;
+#ifdef _GLIBCXX_USE_WCHAR_T
else
{
size_t __n = __narrow_str.size();
auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
- __to_wstring_numeric(__narrow_str.data(), __n, __p);
+ std::__to_wstring_numeric(__narrow_str.data(), __n, __p);
__str = {__p, __n};
}
+#endif
if (_M_spec._M_localized)
{
@@ -1624,11 +1626,13 @@ namespace __format
basic_string_view<_CharT> __str;
if constexpr (is_same_v<_CharT, char>)
__str = __narrow_str;
+#ifdef _GLIBCXX_USE_WCHAR_T
else
{
__wstr = std::__to_wstring_numeric(__narrow_str);
__str = __wstr;
}
+#endif
if (_M_spec._M_localized)
{
@@ -2290,12 +2294,14 @@ namespace __format
basic_string_view<_CharT> __str;
if constexpr (is_same_v<_CharT, char>)
__str = string_view(__buf, __n);
+#ifdef _GLIBCXX_USE_WCHAR_T
else
{
auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
- __to_wstring_numeric(__buf, __n, __p);
+ std::__to_wstring_numeric(__buf, __n, __p);
__str = wstring_view(__p, __n);
}
+#endif
#if _GLIBCXX_P2518R3
if (_M_spec._M_zero_fill)
--
2.41.0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-08-18 11:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-17 20:31 [committed] libstdc++: Rework std::format support for wchar_t Jonathan Wakely
2023-08-18 8:44 ` [committed] libstdc++: Fix incomplete rework of wchar_t support in std::format Jonathan Wakely
2023-08-18 11:31 ` [committed] libstdc++: Replace non-type-dependent uses of wchar_t in <format> and <chrono> Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).