aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r--libstdc++-v3/include/bits/formatfwd.h95
-rw-r--r--libstdc++-v3/include/bits/stl_queue.h14
-rw-r--r--libstdc++-v3/include/bits/stl_stack.h9
-rw-r--r--libstdc++-v3/include/bits/stl_tree.h106
-rw-r--r--libstdc++-v3/include/bits/version.def3
-rw-r--r--libstdc++-v3/include/bits/version.h3
-rw-r--r--libstdc++-v3/include/std/format333
-rw-r--r--libstdc++-v3/include/std/future66
-rw-r--r--libstdc++-v3/include/std/queue80
-rw-r--r--libstdc++-v3/include/std/stack48
-rw-r--r--libstdc++-v3/include/std/thread45
11 files changed, 493 insertions, 309 deletions
diff --git a/libstdc++-v3/include/bits/formatfwd.h b/libstdc++-v3/include/bits/formatfwd.h
index a6b5ac8..12ae2ad 100644
--- a/libstdc++-v3/include/bits/formatfwd.h
+++ b/libstdc++-v3/include/bits/formatfwd.h
@@ -37,6 +37,12 @@
// <bits/version.h> must have been included before this header:
#ifdef __glibcxx_format // C++ >= 20 && HOSTED
+#include <concepts>
+#include <type_traits>
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
+# include <bits/ranges_base.h> // input_range, range_reference_t
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -50,6 +56,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// [format.formatter], formatter
template<typename _Tp, typename _CharT = char> struct formatter;
+/// @cond undocumented
+ [[noreturn]]
+ inline void
+ __throw_format_error(const char* __what);
+
namespace __format
{
#ifdef _GLIBCXX_USE_WCHAR_T
@@ -60,9 +71,89 @@ namespace __format
concept __char = same_as<_CharT, char>;
#endif
- template<__char _CharT>
- struct __formatter_int;
+ enum _Align {
+ _Align_default,
+ _Align_left,
+ _Align_right,
+ _Align_centre,
+ };
+
+ template<typename _CharT> struct _Spec;
+
+ template<__char _CharT> struct __formatter_str;
+ template<__char _CharT> struct __formatter_int;
+ template<__char _CharT> struct __formatter_ptr;
+
+ template<typename _Tp, typename _Context,
+ typename _Formatter
+ = typename _Context::template formatter_type<remove_const_t<_Tp>>,
+ typename _ParseContext
+ = basic_format_parse_context<typename _Context::char_type>>
+ concept __parsable_with
+ = semiregular<_Formatter>
+ && requires (_Formatter __f, _ParseContext __pc)
+ {
+ { __f.parse(__pc) } -> same_as<typename _ParseContext::iterator>;
+ };
+
+ template<typename _Tp, typename _Context,
+ typename _Formatter
+ = typename _Context::template formatter_type<remove_const_t<_Tp>>,
+ typename _ParseContext
+ = basic_format_parse_context<typename _Context::char_type>>
+ concept __formattable_with
+ = semiregular<_Formatter>
+ && requires (const _Formatter __cf, _Tp&& __t, _Context __fc)
+ {
+ { __cf.format(__t, __fc) } -> same_as<typename _Context::iterator>;
+ };
+
+ // An unspecified output iterator type used in the `formattable` concept.
+ template<typename _CharT>
+ struct _Iter_for;
+ template<typename _CharT>
+ using _Iter_for_t = typename _Iter_for<_CharT>::type;
+
+ template<typename _Tp, typename _CharT,
+ typename _Context = basic_format_context<_Iter_for_t<_CharT>, _CharT>>
+ concept __formattable_impl
+ = __parsable_with<_Tp, _Context> && __formattable_with<_Tp, _Context>;
+
+ template<typename _Formatter>
+ concept __has_debug_format = requires(_Formatter __f)
+ {
+ __f.set_debug_format();
+ };
+} // namespace __format
+/// @endcond
+
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
+ // [format.formattable], concept formattable
+ template<typename _Tp, typename _CharT>
+ concept formattable
+ = __format::__formattable_impl<remove_reference_t<_Tp>, _CharT>;
+
+ template<typename _Tp, __format::__char _CharT = char>
+ requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT>
+ class range_formatter;
+
+/// @cond undocumented
+namespace __format
+{
+ template<typename _Rg, typename _CharT>
+ concept __const_formattable_range
+ = ranges::input_range<const _Rg>
+ && formattable<ranges::range_reference_t<const _Rg>, _CharT>;
+
+ template<typename _Rg, typename _CharT>
+ using __maybe_const_range
+ = __conditional_t<__const_formattable_range<_Rg, _CharT>, const _Rg, _Rg>;
+
+ template<typename _Tp, typename _CharT>
+ using __maybe_const
+ = __conditional_t<formattable<const _Tp, _CharT>, const _Tp, _Tp>;
}
+#endif // format_ranges
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h
index 554e076..a3a8bc1 100644
--- a/libstdc++-v3/include/bits/stl_queue.h
+++ b/libstdc++-v3/include/bits/stl_queue.h
@@ -70,6 +70,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+#if __glibcxx_format_ranges
+ template<typename, typename> class formatter;
+#endif
+
/**
* @brief A standard container giving FIFO behavior.
*
@@ -369,6 +373,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(c, __q.c);
}
#endif // __cplusplus >= 201103L
+
+#if __glibcxx_format_ranges
+ friend class formatter<queue<_Tp, _Sequence>, char>;
+ friend class formatter<queue<_Tp, _Sequence>, wchar_t>;
+#endif
};
#if __cpp_deduction_guides >= 201606
@@ -898,6 +907,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(comp, __pq.comp);
}
#endif // __cplusplus >= 201103L
+
+#if __glibcxx_format_ranges
+ friend class formatter<priority_queue<_Tp, _Sequence, _Compare>, char>;
+ friend class formatter<priority_queue<_Tp, _Sequence, _Compare>, wchar_t>;
+#endif
};
#if __cpp_deduction_guides >= 201606
diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h
index 7b32464..27c79d6 100644
--- a/libstdc++-v3/include/bits/stl_stack.h
+++ b/libstdc++-v3/include/bits/stl_stack.h
@@ -70,6 +70,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+#if __glibcxx_format_ranges
+ template<typename, typename> class formatter;
+#endif
+
/**
* @brief A standard container giving FILO behavior.
*
@@ -343,6 +347,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(c, __s.c);
}
#endif // __cplusplus >= 201103L
+
+#if __glibcxx_format_ranges
+ friend class formatter<stack<_Tp, _Sequence>, char>;
+ friend class formatter<stack<_Tp, _Sequence>, wchar_t>;
+#endif
};
#if __cpp_deduction_guides >= 201606
diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index 6b35f99..6caf937 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -1390,27 +1390,25 @@ namespace __rb_tree
_M_end() const _GLIBCXX_NOEXCEPT
{ return this->_M_impl._M_header._M_base_ptr(); }
- static const _Key&
- _S_key(const _Node& __node)
- {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2542. Missing const requirements for associative containers
+ template<typename _Key1, typename _Key2>
+ bool
+ _M_key_compare(const _Key1& __k1, const _Key2& __k2) const
+ {
#if __cplusplus >= 201103L
- // If we're asking for the key we're presumably using the comparison
- // object, and so this is a good place to sanity check it.
- static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},
- "comparison object must be invocable "
- "with two arguments of key type");
-# if __cplusplus >= 201703L
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 2542. Missing const requirements for associative containers
- if constexpr (__is_invocable<_Compare&, const _Key&, const _Key&>{})
+ // Enforce this here with a user-friendly message.
static_assert(
- is_invocable_v<const _Compare&, const _Key&, const _Key&>,
- "comparison object must be invocable as const");
-# endif // C++17
-#endif // C++11
+ __is_invocable<const _Compare&, const _Key&, const _Key&>::value,
+ "comparison object must be invocable with two arguments of key type"
+ );
+#endif
+ return _M_impl._M_key_compare(__k1, __k2);
+ }
- return _KeyOfValue()(*__node._M_valptr());
- }
+ static const _Key&
+ _S_key(const _Node& __node)
+ { return _KeyOfValue()(*__node._M_valptr()); }
static const _Key&
_S_key(_Base_ptr __x)
@@ -1933,7 +1931,7 @@ namespace __rb_tree
_M_find_tr(const _Kt& __k) const
{
const_iterator __j(_M_lower_bound_tr(__k));
- if (__j != end() && _M_impl._M_key_compare(__k, _S_key(__j._M_node)))
+ if (__j != end() && _M_key_compare(__k, _S_key(__j._M_node)))
__j = end();
return __j;
}
@@ -1955,7 +1953,7 @@ namespace __rb_tree
auto __x = _M_begin();
auto __y = _M_end();
while (__x)
- if (!_M_impl._M_key_compare(_S_key(__x), __k))
+ if (!_M_key_compare(_S_key(__x), __k))
{
__y = __x;
__x = _S_left(__x);
@@ -1973,7 +1971,7 @@ namespace __rb_tree
auto __x = _M_begin();
auto __y = _M_end();
while (__x)
- if (_M_impl._M_key_compare(__k, _S_key(__x)))
+ if (_M_key_compare(__k, _S_key(__x)))
{
__y = __x;
__x = _S_left(__x);
@@ -2474,8 +2472,8 @@ namespace __rb_tree
_NodeGen& __node_gen)
{
bool __insert_left = (__x || __p == _M_end()
- || _M_impl._M_key_compare(_KeyOfValue()(__v),
- _S_key(__p)));
+ || _M_key_compare(_KeyOfValue()(__v),
+ _S_key(__p)));
_Base_ptr __z =
__node_gen(_GLIBCXX_FORWARD(_Arg, __v))->_M_base_ptr();
@@ -2500,8 +2498,8 @@ namespace __rb_tree
#endif
{
bool __insert_left = (__p == _M_end()
- || !_M_impl._M_key_compare(_S_key(__p),
- _KeyOfValue()(__v)));
+ || !_M_key_compare(_S_key(__p),
+ _KeyOfValue()(__v)));
_Base_ptr __z =
_M_create_node(_GLIBCXX_FORWARD(_Arg, __v))->_M_base_ptr();
@@ -2529,7 +2527,7 @@ namespace __rb_tree
while (__x)
{
__y = __x;
- __x = !_M_impl._M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ?
+ __x = !_M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ?
_S_left(__x) : _S_right(__x);
}
return _M_insert_lower(__y, _GLIBCXX_FORWARD(_Arg, __v));
@@ -2601,7 +2599,7 @@ namespace __rb_tree
const _Key& __k) const
{
while (__x)
- if (!_M_impl._M_key_compare(_S_key(__x), __k))
+ if (!_M_key_compare(_S_key(__x), __k))
__y = __x, __x = _S_left(__x);
else
__x = _S_right(__x);
@@ -2617,7 +2615,7 @@ namespace __rb_tree
const _Key& __k) const
{
while (__x)
- if (_M_impl._M_key_compare(__k, _S_key(__x)))
+ if (_M_key_compare(__k, _S_key(__x)))
__y = __x, __x = _S_left(__x);
else
__x = _S_right(__x);
@@ -2639,9 +2637,9 @@ namespace __rb_tree
_Base_ptr __y = _M_end();
while (__x)
{
- if (_M_impl._M_key_compare(_S_key(__x), __k))
+ if (_M_key_compare(_S_key(__x), __k))
__x = _S_right(__x);
- else if (_M_impl._M_key_compare(__k, _S_key(__x)))
+ else if (_M_key_compare(__k, _S_key(__x)))
__y = __x, __x = _S_left(__x);
else
{
@@ -2671,9 +2669,9 @@ namespace __rb_tree
_Base_ptr __y = _M_end();
while (__x)
{
- if (_M_impl._M_key_compare(_S_key(__x), __k))
+ if (_M_key_compare(_S_key(__x), __k))
__x = _S_right(__x);
- else if (_M_impl._M_key_compare(__k, _S_key(__x)))
+ else if (_M_key_compare(__k, _S_key(__x)))
__y = __x, __x = _S_left(__x);
else
{
@@ -2737,7 +2735,7 @@ namespace __rb_tree
while (__x)
{
__y = __x;
- __comp = _M_impl._M_key_compare(__k, _S_key(__x));
+ __comp = _M_key_compare(__k, _S_key(__x));
__x = __comp ? _S_left(__x) : _S_right(__x);
}
iterator __j = iterator(__y);
@@ -2748,7 +2746,7 @@ namespace __rb_tree
else
--__j;
}
- if (_M_impl._M_key_compare(_S_key(__j._M_node), __k))
+ if (_M_key_compare(_S_key(__j._M_node), __k))
return _Res(__x, __y);
return _Res(__j._M_node, _Base_ptr());
}
@@ -2768,8 +2766,7 @@ namespace __rb_tree
while (__x)
{
__y = __x;
- __x = _M_impl._M_key_compare(__k, _S_key(__x)) ?
- _S_left(__x) : _S_right(__x);
+ __x = _M_key_compare(__k, _S_key(__x)) ? _S_left(__x) : _S_right(__x);
}
return _Res(__x, __y);
}
@@ -2838,19 +2835,18 @@ namespace __rb_tree
// end()
if (__position._M_node == _M_end())
{
- if (size() > 0
- && _M_impl._M_key_compare(_S_key(_M_rightmost()), __k))
+ if (size() > 0 && _M_key_compare(_S_key(_M_rightmost()), __k))
return _Res(_Base_ptr(), _M_rightmost());
else
return _M_get_insert_unique_pos(__k);
}
- else if (_M_impl._M_key_compare(__k, _S_key(__position._M_node)))
+ else if (_M_key_compare(__k, _S_key(__position._M_node)))
{
// First, try before...
iterator __before(__position._M_node);
if (__position._M_node == _M_leftmost()) // begin()
return _Res(_M_leftmost(), _M_leftmost());
- else if (_M_impl._M_key_compare(_S_key((--__before)._M_node), __k))
+ else if (_M_key_compare(_S_key((--__before)._M_node), __k))
{
if (!_S_right(__before._M_node))
return _Res(_Base_ptr(), __before._M_node);
@@ -2860,13 +2856,13 @@ namespace __rb_tree
else
return _M_get_insert_unique_pos(__k);
}
- else if (_M_impl._M_key_compare(_S_key(__position._M_node), __k))
+ else if (_M_key_compare(_S_key(__position._M_node), __k))
{
// ... then try after.
iterator __after(__position._M_node);
if (__position._M_node == _M_rightmost())
return _Res(_Base_ptr(), _M_rightmost());
- else if (_M_impl._M_key_compare(__k, _S_key((++__after)._M_node)))
+ else if (_M_key_compare(__k, _S_key((++__after)._M_node)))
{
if (!_S_right(__position._M_node))
return _Res(_Base_ptr(), __position._M_node);
@@ -2923,18 +2919,18 @@ namespace __rb_tree
if (__position._M_node == _M_end())
{
if (size() > 0
- && !_M_impl._M_key_compare(__k, _S_key(_M_rightmost())))
+ && !_M_key_compare(__k, _S_key(_M_rightmost())))
return _Res(_Base_ptr(), _M_rightmost());
else
return _M_get_insert_equal_pos(__k);
}
- else if (!_M_impl._M_key_compare(_S_key(__position._M_node), __k))
+ else if (!_M_key_compare(_S_key(__position._M_node), __k))
{
// First, try before...
iterator __before(__position._M_node);
if (__position._M_node == _M_leftmost()) // begin()
return _Res(_M_leftmost(), _M_leftmost());
- else if (!_M_impl._M_key_compare(__k, _S_key((--__before)._M_node)))
+ else if (!_M_key_compare(__k, _S_key((--__before)._M_node)))
{
if (!_S_right(__before._M_node))
return _Res(_Base_ptr(), __before._M_node);
@@ -2950,7 +2946,7 @@ namespace __rb_tree
iterator __after(__position._M_node);
if (__position._M_node == _M_rightmost())
return _Res(_Base_ptr(), _M_rightmost());
- else if (!_M_impl._M_key_compare(_S_key((++__after)._M_node), __k))
+ else if (!_M_key_compare(_S_key((++__after)._M_node), __k))
{
if (!_S_right(__position._M_node))
return _Res(_Base_ptr(), __position._M_node);
@@ -2999,8 +2995,7 @@ namespace __rb_tree
-> iterator
{
bool __insert_left = (__x || __p == _M_end()
- || _M_impl._M_key_compare(_S_key(__z),
- _S_key(__p)));
+ || _M_key_compare(_S_key(__z), _S_key(__p)));
_Base_ptr __base_z = __z->_M_base_ptr();
_Node_traits::_S_insert_and_rebalance
@@ -3017,8 +3012,7 @@ namespace __rb_tree
-> iterator
{
bool __insert_left = (__p == _M_end()
- || !_M_impl._M_key_compare(_S_key(__p),
- _S_key(__z)));
+ || !_M_key_compare(_S_key(__p), _S_key(__z)));
_Base_ptr __base_z = __z->_M_base_ptr();
_Node_traits::_S_insert_and_rebalance
@@ -3039,7 +3033,7 @@ namespace __rb_tree
while (__x)
{
__y = __x;
- __x = !_M_impl._M_key_compare(_S_key(__x), _S_key(__z)) ?
+ __x = !_M_key_compare(_S_key(__x), _S_key(__z)) ?
_S_left(__x) : _S_right(__x);
}
return _M_insert_lower_node(__y, __z);
@@ -3151,8 +3145,7 @@ namespace __rb_tree
{
iterator __j(_M_lower_bound(_M_begin(), _M_end(), __k));
return (__j == end()
- || _M_impl._M_key_compare(__k,
- _S_key(__j._M_node))) ? end() : __j;
+ || _M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j;
}
template<typename _Key, typename _Val, typename _KeyOfValue,
@@ -3164,8 +3157,7 @@ namespace __rb_tree
{
const_iterator __j(_M_lower_bound(_M_begin(), _M_end(), __k));
return (__j == end()
- || _M_impl._M_key_compare(__k,
- _S_key(__j._M_node))) ? end() : __j;
+ || _M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j;
}
template<typename _Key, typename _Val, typename _KeyOfValue,
@@ -3205,9 +3197,9 @@ namespace __rb_tree
|| (__R && __R->_M_color == _S_red))
return false;
- if (__L && _M_impl._M_key_compare(_S_key(__x), _S_key(__L)))
+ if (__L && _M_key_compare(_S_key(__x), _S_key(__L)))
return false;
- if (__R && _M_impl._M_key_compare(_S_key(__R), _S_key(__x)))
+ if (__R && _M_key_compare(_S_key(__R), _S_key(__x)))
return false;
if (!__L && !__R && _Rb_tree_black_count(__x, _M_root()) != __len)
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 0afaf0d..737b3f4 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1416,9 +1416,8 @@ ftms = {
// 202207 P2286R8 Formatting Ranges
// 202207 P2585R1 Improving default container formatting
// LWG3750 Too many papers bump __cpp_lib_format
- no_stdname = true; // TODO remove
values = {
- v = 1; // TODO 202207
+ v = 202207;
cxxmin = 23;
hosted = yes;
};
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 980fee6..59ff0ce 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1562,8 +1562,9 @@
#if !defined(__cpp_lib_format_ranges)
# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED
-# define __glibcxx_format_ranges 1L
+# define __glibcxx_format_ranges 202207L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_format_ranges)
+# define __cpp_lib_format_ranges 202207L
# endif
# endif
#endif /* !defined(__cpp_lib_format_ranges) && defined(__glibcxx_want_format_ranges) */
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index e557e10..86c93f0 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -117,6 +117,11 @@ namespace __format
template<typename _CharT>
class _Sink_iter;
+ // An unspecified output iterator type used in the `formattable` concept.
+ template<typename _CharT>
+ struct _Iter_for
+ { using type = back_insert_iterator<basic_string<_CharT>>; };
+
template<typename _CharT>
using __format_context = basic_format_context<_Sink_iter<_CharT>, _CharT>;
@@ -135,6 +140,7 @@ namespace __format
template<typename, typename...> friend struct std::basic_format_string;
};
+
} // namespace __format
/// @endcond
@@ -485,13 +491,6 @@ namespace __format
_Pres_esc = 0xf, // For strings, charT and ranges
};
- enum _Align {
- _Align_default,
- _Align_left,
- _Align_right,
- _Align_centre,
- };
-
enum _Sign {
_Sign_default,
_Sign_plus,
@@ -1434,6 +1433,13 @@ namespace __format
static constexpr _Pres_type _AsBool = _Pres_s;
static constexpr _Pres_type _AsChar = _Pres_c;
+ __formatter_int() = default;
+
+ constexpr
+ __formatter_int(_Spec<_CharT> __spec) noexcept
+ : _M_spec(__spec)
+ { }
+
constexpr typename basic_format_parse_context<_CharT>::iterator
_M_do_parse(basic_format_parse_context<_CharT>& __pc, _Pres_type __type)
{
@@ -2381,6 +2387,134 @@ namespace __format
_Spec<_CharT> _M_spec{};
};
+ template<__format::__char _CharT>
+ struct __formatter_ptr
+ {
+ __formatter_ptr() = default;
+
+ constexpr
+ __formatter_ptr(_Spec<_CharT> __spec) noexcept
+ : _M_spec(__spec)
+ { }
+
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ {
+ __format::_Spec<_CharT> __spec{};
+ const auto __last = __pc.end();
+ auto __first = __pc.begin();
+
+ auto __finalize = [this, &__spec] {
+ _M_spec = __spec;
+ };
+
+ auto __finished = [&] {
+ if (__first == __last || *__first == '}')
+ {
+ __finalize();
+ return true;
+ }
+ return false;
+ };
+
+ if (__finished())
+ return __first;
+
+ __first = __spec._M_parse_fill_and_align(__first, __last);
+ if (__finished())
+ return __first;
+
+// _GLIBCXX_RESOLVE_LIB_DEFECTS
+// P2510R3 Formatting pointers
+#if __glibcxx_format >= 202304L
+ __first = __spec._M_parse_zero_fill(__first, __last);
+ if (__finished())
+ return __first;
+#endif
+
+ __first = __spec._M_parse_width(__first, __last, __pc);
+
+ if (__first != __last)
+ {
+ if (*__first == 'p')
+ ++__first;
+#if __glibcxx_format >= 202304L
+ else if (*__first == 'P')
+ {
+ __spec._M_type = __format::_Pres_P;
+ ++__first;
+ }
+#endif
+ }
+
+ if (__finished())
+ return __first;
+
+ __format::__failed_to_parse_format_spec();
+ }
+
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const void* __v, basic_format_context<_Out, _CharT>& __fc) const
+ {
+ auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v);
+ char __buf[2 + sizeof(__v) * 2];
+ auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf),
+ __u, 16);
+ int __n = __ptr - __buf;
+ __buf[0] = '0';
+ __buf[1] = 'x';
+#if __glibcxx_format >= 202304L
+ if (_M_spec._M_type == __format::_Pres_P)
+ {
+ __buf[1] = 'X';
+ for (auto __p = __buf + 2; __p != __ptr; ++__p)
+#if __has_builtin(__builtin_toupper)
+ *__p = __builtin_toupper(*__p);
+#else
+ *__p = std::toupper(*__p);
+#endif
+ }
+#endif
+
+ 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));
+ std::__to_wstring_numeric(__buf, __n, __p);
+ __str = wstring_view(__p, __n);
+ }
+#endif
+
+#if __glibcxx_format >= 202304L
+ if (_M_spec._M_zero_fill)
+ {
+ size_t __width = _M_spec._M_get_width(__fc);
+ if (__width <= __str.size())
+ return __format::__write(__fc.out(), __str);
+
+ auto __out = __fc.out();
+ // Write "0x" or "0X" prefix before zero-filling.
+ __out = __format::__write(std::move(__out), __str.substr(0, 2));
+ __str.remove_prefix(2);
+ size_t __nfill = __width - __n;
+ return __format::__write_padded(std::move(__out), __str,
+ __format::_Align_right,
+ __nfill, _CharT('0'));
+ }
+#endif
+
+ return __format::__write_padded_as_spec(__str, __n, __fc, _M_spec,
+ __format::_Align_right);
+ }
+
+ private:
+ __format::_Spec<_CharT> _M_spec{};
+ };
+
} // namespace __format
/// @endcond
@@ -2845,120 +2979,15 @@ namespace __format
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- {
- __format::_Spec<_CharT> __spec{};
- const auto __last = __pc.end();
- auto __first = __pc.begin();
-
- auto __finalize = [this, &__spec] {
- _M_spec = __spec;
- };
-
- auto __finished = [&] {
- if (__first == __last || *__first == '}')
- {
- __finalize();
- return true;
- }
- return false;
- };
-
- if (__finished())
- return __first;
-
- __first = __spec._M_parse_fill_and_align(__first, __last);
- if (__finished())
- return __first;
-
-// _GLIBCXX_RESOLVE_LIB_DEFECTS
-// P2510R3 Formatting pointers
-#if __glibcxx_format >= 202304L
- __first = __spec._M_parse_zero_fill(__first, __last);
- if (__finished())
- return __first;
-#endif
-
- __first = __spec._M_parse_width(__first, __last, __pc);
-
- if (__first != __last)
- {
- if (*__first == 'p')
- ++__first;
-#if __glibcxx_format >= 202304L
- else if (*__first == 'P')
- {
- __spec._M_type = __format::_Pres_P;
- ++__first;
- }
-#endif
- }
-
- if (__finished())
- return __first;
-
- __format::__failed_to_parse_format_spec();
- }
+ { return _M_f.parse(__pc); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const void* __v, basic_format_context<_Out, _CharT>& __fc) const
- {
- auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v);
- char __buf[2 + sizeof(__v) * 2];
- auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf),
- __u, 16);
- int __n = __ptr - __buf;
- __buf[0] = '0';
- __buf[1] = 'x';
-#if __glibcxx_format >= 202304L
- if (_M_spec._M_type == __format::_Pres_P)
- {
- __buf[1] = 'X';
- for (auto __p = __buf + 2; __p != __ptr; ++__p)
-#if __has_builtin(__builtin_toupper)
- *__p = __builtin_toupper(*__p);
-#else
- *__p = std::toupper(*__p);
-#endif
- }
-#endif
-
- 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));
- std::__to_wstring_numeric(__buf, __n, __p);
- __str = wstring_view(__p, __n);
- }
-#endif
-
-#if __glibcxx_format >= 202304L
- if (_M_spec._M_zero_fill)
- {
- size_t __width = _M_spec._M_get_width(__fc);
- if (__width <= __str.size())
- return __format::__write(__fc.out(), __str);
-
- auto __out = __fc.out();
- // Write "0x" or "0X" prefix before zero-filling.
- __out = __format::__write(std::move(__out), __str.substr(0, 2));
- __str.remove_prefix(2);
- size_t __nfill = __width - __n;
- return __format::__write_padded(std::move(__out), __str,
- __format::_Align_right,
- __nfill, _CharT('0'));
- }
-#endif
-
- return __format::__write_padded_as_spec(__str, __n, __fc, _M_spec,
- __format::_Align_right);
- }
+ { return _M_f.format(__v, __fc); }
private:
- __format::_Spec<_CharT> _M_spec{};
+ __format::__formatter_ptr<_CharT> _M_f;
};
template<__format::__char _CharT>
@@ -2977,7 +3006,7 @@ namespace __format
{ return _M_f.format(__v, __fc); }
private:
- formatter<const void*, _CharT> _M_f;
+ __format::__formatter_ptr<_CharT> _M_f;
};
template<__format::__char _CharT>
@@ -2996,7 +3025,7 @@ namespace __format
{ return _M_f.format(nullptr, __fc); }
private:
- formatter<const void*, _CharT> _M_f;
+ __format::__formatter_ptr<_CharT> _M_f;
};
/// @}
@@ -3024,59 +3053,6 @@ namespace __format
: private formatter<__format::__disabled, wchar_t> { };
#endif
-/// @cond undocumented
-namespace __format
-{
- template<typename _Tp, typename _Context,
- typename _Formatter
- = typename _Context::template formatter_type<remove_const_t<_Tp>>,
- typename _ParseContext
- = basic_format_parse_context<typename _Context::char_type>>
- concept __parsable_with
- = semiregular<_Formatter>
- && requires (_Formatter __f, _ParseContext __pc)
- {
- { __f.parse(__pc) } -> same_as<typename _ParseContext::iterator>;
- };
-
- template<typename _Tp, typename _Context,
- typename _Formatter
- = typename _Context::template formatter_type<remove_const_t<_Tp>>,
- typename _ParseContext
- = basic_format_parse_context<typename _Context::char_type>>
- concept __formattable_with
- = semiregular<_Formatter>
- && requires (const _Formatter __cf, _Tp&& __t, _Context __fc)
- {
- { __cf.format(__t, __fc) } -> same_as<typename _Context::iterator>;
- };
-
- // An unspecified output iterator type used in the `formattable` concept.
- template<typename _CharT>
- using _Iter_for = back_insert_iterator<basic_string<_CharT>>;
-
- template<typename _Tp, typename _CharT,
- typename _Context = basic_format_context<_Iter_for<_CharT>, _CharT>>
- concept __formattable_impl
- = __parsable_with<_Tp, _Context> && __formattable_with<_Tp, _Context>;
-
- template<typename _Formatter>
- concept __has_debug_format = requires(_Formatter __f)
- {
- __f.set_debug_format();
- };
-
-} // namespace __format
-/// @endcond
-
-#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
- // [format.formattable], concept formattable
- template<typename _Tp, typename _CharT>
- concept formattable
- = __format::__formattable_impl<remove_reference_t<_Tp>, _CharT>;
-
-#endif // format_ranges
-
/// An iterator after the last character written, and the number of
/// characters that would have been written.
template<typename _Out>
@@ -5250,26 +5226,13 @@ namespace __format
return __format::__write_padded_as_spec(__str, __width, __fc, __spec);
}
- template<typename _Rg, typename _CharT>
- concept __const_formattable_range
- = ranges::input_range<const _Rg>
- && formattable<ranges::range_reference_t<const _Rg>, _CharT>;
-
// _Rg& and const _Rg& are both formattable and use same formatter
// specialization for their references.
template<typename _Rg, typename _CharT>
concept __simply_formattable_range
= __const_formattable_range<_Rg, _CharT>
&& same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>,
- remove_cvref_t<ranges::range_reference_t<const _Rg>>>;
-
- template<typename _Rg, typename _CharT>
- using __maybe_const_range
- = __conditional_t<__const_formattable_range<_Rg, _CharT>, const _Rg, _Rg>;
-
- template<typename _Tp, typename _CharT>
- using __maybe_const
- = __conditional_t<formattable<const _Tp, _CharT>, const _Tp, _Tp>;
+ remove_cvref_t<ranges::range_reference_t<const _Rg>>>;
template<size_t _Pos, typename _Tp, typename _CharT>
struct __indexed_formatter_storage
@@ -5493,7 +5456,7 @@ namespace __format
};
// [format.range.formatter], class template range_formatter
- template<typename _Tp, __format::__char _CharT = char>
+ template<typename _Tp, __format::__char _CharT>
requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT>
class range_formatter
{
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index b7ab233..0806900 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -1486,12 +1486,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)> final
: __future_base::_Task_state_base<_Res(_Args...)>
{
+#ifdef __cpp_lib_is_invocable // C++ >= 17
+ static_assert(is_invocable_r_v<_Res, _Fn&, _Args...>);
+#else
+ static_assert(__is_invocable<_Fn&, _Args...>::value,
+ "_Fn& is invocable with _Args...");
+#endif
+
template<typename _Fn2>
_Task_state(_Fn2&& __fn, const _Alloc& __a)
: _Task_state_base<_Res(_Args...)>(__a),
_M_impl(std::forward<_Fn2>(__fn), __a)
{ }
+ template<typename _Fn2>
+ static shared_ptr<_Task_state_base<_Res(_Args...)>>
+ _S_create(_Fn2&& __fn, const _Alloc& __a)
+ {
+ return std::allocate_shared<_Task_state>(__a,
+ std::forward<_Fn2>(__fn),
+ __a);
+ }
+
private:
virtual void
_M_run(_Args&&... __args)
@@ -1515,7 +1531,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
virtual shared_ptr<_Task_state_base<_Res(_Args...)>>
- _M_reset();
+ _M_reset()
+ { return _S_create(std::move(_M_impl._M_fn), _M_impl); }
struct _Impl : _Alloc
{
@@ -1525,38 +1542,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Fn _M_fn;
} _M_impl;
};
-
- template<typename _Signature, typename _Fn,
- typename _Alloc = std::allocator<int>>
- shared_ptr<__future_base::_Task_state_base<_Signature>>
- __create_task_state(_Fn&& __fn, const _Alloc& __a = _Alloc())
- {
- typedef typename decay<_Fn>::type _Fn2;
- typedef __future_base::_Task_state<_Fn2, _Alloc, _Signature> _State;
- return std::allocate_shared<_State>(__a, std::forward<_Fn>(__fn), __a);
- }
-
- template<typename _Fn, typename _Alloc, typename _Res, typename... _Args>
- shared_ptr<__future_base::_Task_state_base<_Res(_Args...)>>
- __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)>::_M_reset()
- {
- return __create_task_state<_Res(_Args...)>(std::move(_M_impl._M_fn),
- static_cast<_Alloc&>(_M_impl));
- }
/// @endcond
/// packaged_task
template<typename _Res, typename... _ArgTypes>
class packaged_task<_Res(_ArgTypes...)>
{
- typedef __future_base::_Task_state_base<_Res(_ArgTypes...)> _State_type;
+ using _State_type = __future_base::_Task_state_base<_Res(_ArgTypes...)>;
shared_ptr<_State_type> _M_state;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3039. Unnecessary decay in thread and packaged_task
template<typename _Fn, typename _Fn2 = __remove_cvref_t<_Fn>>
- using __not_same
- = typename enable_if<!is_same<packaged_task, _Fn2>::value>::type;
+ using __not_same = __enable_if_t<!is_same<packaged_task, _Fn2>::value>;
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4154. The Mandates for std::packaged_task's constructor
+ // from a callable entity should consider decaying.
+ template<typename _Fn, typename _Alloc = std::allocator<int>>
+ using _Task_state
+ = __future_base::_Task_state<__decay_t<_Fn>, _Alloc,
+ _Res(_ArgTypes...)>;
public:
// Construction and destruction
@@ -1565,16 +1571,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Fn, typename = __not_same<_Fn>>
explicit
packaged_task(_Fn&& __fn)
- : _M_state(
- __create_task_state<_Res(_ArgTypes...)>(std::forward<_Fn>(__fn)))
- {
-#ifdef __cpp_lib_is_invocable // C++ >= 17
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 4154. The Mandates for std::packaged_task's constructor
- // from a callable entity should consider decaying
- static_assert(is_invocable_r_v<_Res, decay_t<_Fn>&, _ArgTypes...>);
-#endif
- }
+ : _M_state(_Task_state<_Fn>::_S_create(std::forward<_Fn>(__fn), {}))
+ { }
#if __cplusplus < 201703L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -1583,8 +1581,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 2921. packaged_task and type-erased allocators
template<typename _Fn, typename _Alloc, typename = __not_same<_Fn>>
packaged_task(allocator_arg_t, const _Alloc& __a, _Fn&& __fn)
- : _M_state(__create_task_state<_Res(_ArgTypes...)>(
- std::forward<_Fn>(__fn), __a))
+ : _M_state(_Task_state<_Fn, _Alloc>::_S_create(std::forward<_Fn>(__fn),
+ __a))
{ }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
diff --git a/libstdc++-v3/include/std/queue b/libstdc++-v3/include/std/queue
index 74b6c07..9052589 100644
--- a/libstdc++-v3/include/std/queue
+++ b/libstdc++-v3/include/std/queue
@@ -61,14 +61,88 @@
#include <bits/requires_hosted.h> // containers
+#define __glibcxx_want_adaptor_iterator_pair_constructor
+#define __glibcxx_want_containers_ranges
+#include <bits/version.h>
+
#include <deque>
#include <vector>
#include <bits/stl_heap.h>
#include <bits/stl_function.h>
#include <bits/stl_queue.h>
-#define __glibcxx_want_adaptor_iterator_pair_constructor
-#define __glibcxx_want_containers_ranges
-#include <bits/version.h>
+#ifdef __glibcxx_format_ranges // C++ >= 23 && HOSTED
+#include <bits/formatfwd.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ // Standard does not constrain accepted _CharT, we do so we can
+ // befriend specializations.
+ template<__format::__char _CharT, typename _Tp,
+ formattable<_CharT> _Container>
+ struct formatter<queue<_Tp, _Container>, _CharT>
+ {
+ private:
+ using __maybe_const_adaptor
+ = __conditional_t<
+ __format::__const_formattable_range<_Container, _CharT>,
+ const queue<_Tp, _Container>, queue<_Tp, _Container>>;
+
+ public:
+ // Standard declares this as template accepting unconstrained
+ // ParseContext type.
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ { return _M_f.parse(__pc); }
+
+ // Standard declares this as template accepting unconstrained
+ // FormatContext type.
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(__maybe_const_adaptor& __a,
+ basic_format_context<_Out, _CharT>& __fc) const
+ { return _M_f.format(__a.c, __fc); }
+
+ private:
+ // Standard uses formatter<ref_view<_Container>, _CharT>.
+ range_formatter<_Tp, _CharT> _M_f;
+ };
+
+ template<__format::__char _CharT, typename _Tp,
+ formattable<_CharT> _Container, typename _Compare>
+ struct formatter<priority_queue<_Tp, _Container, _Compare>, _CharT>
+ {
+ private:
+ using __maybe_const_adaptor
+ = __conditional_t<
+ __format::__const_formattable_range<_Container, _CharT>,
+ const priority_queue<_Tp, _Container, _Compare>,
+ priority_queue<_Tp, _Container, _Compare>>;
+
+ public:
+ // Standard declares this as template accepting unconstrained
+ // ParseContext type.
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ { return _M_f.parse(__pc); }
+
+ // Standard declares this as template accepting unconstrained
+ // FormatContext type.
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(__maybe_const_adaptor& __a,
+ basic_format_context<_Out, _CharT>& __fc) const
+ { return _M_f.format(__a.c, __fc); }
+
+ private:
+ // Standard uses formatter<ref_view<_Container>, _CharT>.
+ range_formatter<_Tp, _CharT> _M_f;
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // __glibcxx_format_ranges
+
#endif /* _GLIBCXX_QUEUE */
diff --git a/libstdc++-v3/include/std/stack b/libstdc++-v3/include/std/stack
index 5cea476..a57a5a0 100644
--- a/libstdc++-v3/include/std/stack
+++ b/libstdc++-v3/include/std/stack
@@ -61,11 +61,53 @@
#include <bits/requires_hosted.h> // containers
-#include <deque>
-#include <bits/stl_stack.h>
-
#define __glibcxx_want_adaptor_iterator_pair_constructor
#define __glibcxx_want_containers_ranges
#include <bits/version.h>
+#include <deque>
+#include <bits/stl_stack.h>
+
+#ifdef __glibcxx_format_ranges // C++ >= 23 && HOSTED
+#include <bits/formatfwd.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ // Standard does not constrain accepted _CharT, we do so we can
+ // befriend specializations.
+ template<__format::__char _CharT, typename _Tp,
+ formattable<_CharT> _Container>
+ struct formatter<stack<_Tp, _Container>, _CharT>
+ {
+ private:
+ using __maybe_const_adaptor
+ = __conditional_t<
+ __format::__const_formattable_range<_Container, _CharT>,
+ const stack<_Tp, _Container>, stack<_Tp, _Container>>;
+
+ public:
+ // Standard declares this as template accepting unconstrained
+ // ParseContext type.
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ { return _M_f.parse(__pc); }
+
+ // Standard declares this as template accepting unconstrained
+ // FormatContext type.
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(__maybe_const_adaptor& __a,
+ basic_format_context<_Out, _CharT>& __fc) const
+ { return _M_f.format(__a.c, __fc); }
+
+ private:
+ // Standard uses formatter<ref_view<_Container>, _CharT>.
+ range_formatter<_Tp, _CharT> _M_f;
+ };
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // __glibcxx_format_ranges
+
+
#endif /* _GLIBCXX_STACK */
diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread
index d2f91ad..0de08c0 100644
--- a/libstdc++-v3/include/std/thread
+++ b/libstdc++-v3/include/std/thread
@@ -297,7 +297,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif // __cpp_lib_jthread
#ifdef __cpp_lib_formatters // C++ >= 23
- template<typename _CharT>
+ // We deviate from the standard, that does not put requirements
+ // on _CharT here.
+ template<__format::__char _CharT>
requires is_pointer_v<thread::native_handle_type>
|| is_integral_v<thread::native_handle_type>
class formatter<thread::id, _CharT>
@@ -307,6 +309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
parse(basic_format_parse_context<_CharT>& __pc)
{
__format::_Spec<_CharT> __spec{};
+ __spec._M_align = __format::_Align_right;
const auto __last = __pc.end();
auto __first = __pc.begin();
@@ -334,36 +337,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__finished())
return __first;
- __throw_format_error("format error: invalid format-spec for "
- "std::thread::id");
+ std::__throw_format_error("format error: invalid format-spec for "
+ "std::thread::id");
}
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(thread::id __id, basic_format_context<_Out, _CharT>& __fc) const
{
- basic_string_view<_CharT> __sv;
- if constexpr (is_same_v<_CharT, char>)
- __sv = "{}thread::id of a non-executing thread";
- else
- __sv = L"{}thread::id of a non-executing thread";
- basic_string<_CharT> __str;
+
if (__id == thread::id())
- __sv.remove_prefix(2);
- else
{
- using _FmtStr = __format::_Runtime_format_string<_CharT>;
- // Convert non-void pointers to const void* for formatted output.
- using __output_type
- = __conditional_t<is_pointer_v<thread::native_handle_type>,
- const void*,
- thread::native_handle_type>;
- auto __o = static_cast<__output_type>(__id._M_thread);
- __sv = __str = std::format(_FmtStr(__sv.substr(0, 2)), __o);
+ const _CharT* __msg;
+ if constexpr (is_same_v<_CharT, char>)
+ __msg = "thread::id of a non-executing thread";
+ else
+ __msg = L"thread::id of a non-executing thread";
+
+ __format::__formatter_str<_CharT> __formatter(_M_spec);
+ return __formatter.format(__msg, __fc);
}
- return __format::__write_padded_as_spec(__sv, __sv.size(),
- __fc, _M_spec,
- __format::_Align_right);
+
+ using _HandleFormatter
+ = __conditional_t<is_pointer_v<thread::native_handle_type>,
+ __format::__formatter_ptr<_CharT>,
+ __format::__formatter_int<_CharT>>;
+
+ _HandleFormatter __formatter(_M_spec);
+ return __formatter.format(__id._M_thread, __fc);
}
private: