aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/std
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include/std')
-rw-r--r--libstdc++-v3/include/std/algorithm1
-rw-r--r--libstdc++-v3/include/std/barrier199
-rw-r--r--libstdc++-v3/include/std/bit31
-rw-r--r--libstdc++-v3/include/std/bitset12
-rw-r--r--libstdc++-v3/include/std/charconv15
-rw-r--r--libstdc++-v3/include/std/chrono24
-rw-r--r--libstdc++-v3/include/std/complex26
-rw-r--r--libstdc++-v3/include/std/deque1
-rw-r--r--libstdc++-v3/include/std/expected4
-rw-r--r--libstdc++-v3/include/std/flat_map44
-rw-r--r--libstdc++-v3/include/std/flat_set28
-rw-r--r--libstdc++-v3/include/std/format2148
-rw-r--r--libstdc++-v3/include/std/forward_list1
-rw-r--r--libstdc++-v3/include/std/functional32
-rw-r--r--libstdc++-v3/include/std/future66
-rw-r--r--libstdc++-v3/include/std/generator10
-rw-r--r--libstdc++-v3/include/std/latch36
-rw-r--r--libstdc++-v3/include/std/list1
-rw-r--r--libstdc++-v3/include/std/map1
-rw-r--r--libstdc++-v3/include/std/mdspan1041
-rw-r--r--libstdc++-v3/include/std/memory7
-rw-r--r--libstdc++-v3/include/std/mutex2
-rw-r--r--libstdc++-v3/include/std/numeric14
-rw-r--r--libstdc++-v3/include/std/optional47
-rw-r--r--libstdc++-v3/include/std/ostream2
-rw-r--r--libstdc++-v3/include/std/print2
-rw-r--r--libstdc++-v3/include/std/queue79
-rw-r--r--libstdc++-v3/include/std/ranges13
-rw-r--r--libstdc++-v3/include/std/semaphore31
-rw-r--r--libstdc++-v3/include/std/set1
-rw-r--r--libstdc++-v3/include/std/sstream202
-rw-r--r--libstdc++-v3/include/std/stack47
-rw-r--r--libstdc++-v3/include/std/stop_token7
-rw-r--r--libstdc++-v3/include/std/string1
-rw-r--r--libstdc++-v3/include/std/thread45
-rw-r--r--libstdc++-v3/include/std/tuple24
-rw-r--r--libstdc++-v3/include/std/type_traits106
-rw-r--r--libstdc++-v3/include/std/unordered_map1
-rw-r--r--libstdc++-v3/include/std/unordered_set1
-rw-r--r--libstdc++-v3/include/std/utility2
-rw-r--r--libstdc++-v3/include/std/vector1
41 files changed, 3608 insertions, 748 deletions
diff --git a/libstdc++-v3/include/std/algorithm b/libstdc++-v3/include/std/algorithm
index 321a5e2..1563cdf 100644
--- a/libstdc++-v3/include/std/algorithm
+++ b/libstdc++-v3/include/std/algorithm
@@ -74,6 +74,7 @@
#define __glibcxx_want_ranges_contains
#define __glibcxx_want_ranges_find_last
#define __glibcxx_want_ranges_fold
+#define __glibcxx_want_ranges_starts_ends_with
#define __glibcxx_want_robust_nonmodifying_seq_ops
#define __glibcxx_want_sample
#define __glibcxx_want_shift
diff --git a/libstdc++-v3/include/std/barrier b/libstdc++-v3/include/std/barrier
index 6c3cfd4..56270c9 100644
--- a/libstdc++-v3/include/std/barrier
+++ b/libstdc++-v3/include/std/barrier
@@ -81,105 +81,142 @@ It looks different from literature pseudocode for two main reasons:
enum class __barrier_phase_t : unsigned char { };
- template<typename _CompletionF>
- class __tree_barrier
+ struct __tree_barrier_base
+ {
+ static constexpr ptrdiff_t
+ max() noexcept
+ { return __PTRDIFF_MAX__ - 1; }
+
+ protected:
+ using __atomic_phase_ref_t = std::__atomic_ref<__barrier_phase_t>;
+ using __atomic_phase_const_ref_t = std::__atomic_ref<const __barrier_phase_t>;
+ static constexpr auto __phase_alignment =
+ __atomic_phase_ref_t::required_alignment;
+
+ using __tickets_t = std::array<__barrier_phase_t, 64>;
+ struct alignas(64) /* naturally-align the heap state */ __state_t
{
- using __atomic_phase_ref_t = std::__atomic_ref<__barrier_phase_t>;
- using __atomic_phase_const_ref_t = std::__atomic_ref<const __barrier_phase_t>;
- static constexpr auto __phase_alignment =
- __atomic_phase_ref_t::required_alignment;
+ alignas(__phase_alignment) __tickets_t __tickets;
+ };
- using __tickets_t = std::array<__barrier_phase_t, 64>;
- struct alignas(64) /* naturally-align the heap state */ __state_t
- {
- alignas(__phase_alignment) __tickets_t __tickets;
- };
+ ptrdiff_t _M_expected;
+ __atomic_base<__state_t*> _M_state{nullptr};
+ __atomic_base<ptrdiff_t> _M_expected_adjustment{0};
+ alignas(__phase_alignment) __barrier_phase_t _M_phase{};
- ptrdiff_t _M_expected;
- unique_ptr<__state_t[]> _M_state;
- __atomic_base<ptrdiff_t> _M_expected_adjustment;
- _CompletionF _M_completion;
+ explicit constexpr
+ __tree_barrier_base(ptrdiff_t __expected)
+ : _M_expected(__expected)
+ {
+ __glibcxx_assert(__expected >= 0 && __expected <= max());
- alignas(__phase_alignment) __barrier_phase_t _M_phase;
+ if (!std::is_constant_evaluated())
+ _M_state.store(_M_alloc_state().release(), memory_order_release);
+ }
- bool
- _M_arrive(__barrier_phase_t __old_phase, size_t __current)
- {
- const auto __old_phase_val = static_cast<unsigned char>(__old_phase);
- const auto __half_step =
- static_cast<__barrier_phase_t>(__old_phase_val + 1);
- const auto __full_step =
- static_cast<__barrier_phase_t>(__old_phase_val + 2);
+ unique_ptr<__state_t[]>
+ _M_alloc_state()
+ {
+ size_t const __count = (_M_expected + 1) >> 1;
+ return std::make_unique<__state_t[]>(__count);
+ }
- size_t __current_expected = _M_expected;
- __current %= ((_M_expected + 1) >> 1);
+ bool
+ _M_arrive(__barrier_phase_t __old_phase, size_t __current)
+ {
+ const auto __old_phase_val = static_cast<unsigned char>(__old_phase);
+ const auto __half_step =
+ static_cast<__barrier_phase_t>(__old_phase_val + 1);
+ const auto __full_step =
+ static_cast<__barrier_phase_t>(__old_phase_val + 2);
+
+ size_t __current_expected = _M_expected;
+ __current %= ((_M_expected + 1) >> 1);
+
+ __state_t* const __state = _M_state.load(memory_order_relaxed);
+
+ for (int __round = 0; ; ++__round)
+ {
+ if (__current_expected <= 1)
+ return true;
+ size_t const __end_node = ((__current_expected + 1) >> 1),
+ __last_node = __end_node - 1;
+ for ( ; ; ++__current)
+ {
+ if (__current == __end_node)
+ __current = 0;
+ auto __expect = __old_phase;
+ __atomic_phase_ref_t __phase(__state[__current]
+ .__tickets[__round]);
+ if (__current == __last_node && (__current_expected & 1))
+ {
+ if (__phase.compare_exchange_strong(__expect, __full_step,
+ memory_order_acq_rel))
+ break; // I'm 1 in 1, go to next __round
+ }
+ else if (__phase.compare_exchange_strong(__expect, __half_step,
+ memory_order_acq_rel))
+ {
+ return false; // I'm 1 in 2, done with arrival
+ }
+ else if (__expect == __half_step)
+ {
+ if (__phase.compare_exchange_strong(__expect, __full_step,
+ memory_order_acq_rel))
+ break; // I'm 2 in 2, go to next __round
+ }
+ }
+ __current_expected = __last_node + 1;
+ __current >>= 1;
+ }
+ }
+ };
- for (int __round = 0; ; ++__round)
- {
- if (__current_expected <= 1)
- return true;
- size_t const __end_node = ((__current_expected + 1) >> 1),
- __last_node = __end_node - 1;
- for ( ; ; ++__current)
- {
- if (__current == __end_node)
- __current = 0;
- auto __expect = __old_phase;
- __atomic_phase_ref_t __phase(_M_state[__current]
- .__tickets[__round]);
- if (__current == __last_node && (__current_expected & 1))
- {
- if (__phase.compare_exchange_strong(__expect, __full_step,
- memory_order_acq_rel))
- break; // I'm 1 in 1, go to next __round
- }
- else if (__phase.compare_exchange_strong(__expect, __half_step,
- memory_order_acq_rel))
- {
- return false; // I'm 1 in 2, done with arrival
- }
- else if (__expect == __half_step)
- {
- if (__phase.compare_exchange_strong(__expect, __full_step,
- memory_order_acq_rel))
- break; // I'm 2 in 2, go to next __round
- }
- }
- __current_expected = __last_node + 1;
- __current >>= 1;
- }
- }
+ template<typename _CompletionF>
+ class __tree_barrier : public __tree_barrier_base
+ {
+ [[no_unique_address]] _CompletionF _M_completion;
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3898. Possibly unintended preconditions for completion functions
+ void _M_invoke_completion() noexcept { _M_completion(); }
public:
using arrival_token = __barrier_phase_t;
- static constexpr ptrdiff_t
- max() noexcept
- { return __PTRDIFF_MAX__; }
-
+ constexpr
__tree_barrier(ptrdiff_t __expected, _CompletionF __completion)
- : _M_expected(__expected), _M_expected_adjustment(0),
- _M_completion(move(__completion)),
- _M_phase(static_cast<__barrier_phase_t>(0))
- {
- size_t const __count = (_M_expected + 1) >> 1;
-
- _M_state = std::make_unique<__state_t[]>(__count);
- }
+ : __tree_barrier_base(__expected), _M_completion(std::move(__completion))
+ { }
[[nodiscard]] arrival_token
arrive(ptrdiff_t __update)
{
+ __glibcxx_assert(__update > 0);
+ // FIXME: Check that update is less than or equal to the expected count
+ // for the current barrier phase.
+
std::hash<std::thread::id> __hasher;
size_t __current = __hasher(std::this_thread::get_id());
__atomic_phase_ref_t __phase(_M_phase);
const auto __old_phase = __phase.load(memory_order_relaxed);
const auto __cur = static_cast<unsigned char>(__old_phase);
- for(; __update; --__update)
+
+ if (__cur == 0 && !_M_state.load(memory_order_relaxed)) [[unlikely]]
+ {
+ auto __p = _M_alloc_state();
+ __state_t* __val = nullptr;
+ if (_M_state.compare_exchange_strong(__val, __p.get(),
+ memory_order_seq_cst,
+ memory_order_acquire))
+ __p.release();
+ }
+
+ for (; __update; --__update)
{
- if(_M_arrive(__old_phase, __current))
+ if (_M_arrive(__old_phase, __current))
{
- _M_completion();
+ _M_invoke_completion();
_M_expected += _M_expected_adjustment.load(memory_order_relaxed);
_M_expected_adjustment.store(0, memory_order_relaxed);
auto __new_phase = static_cast<__barrier_phase_t>(__cur + 2);
@@ -194,11 +231,7 @@ It looks different from literature pseudocode for two main reasons:
wait(arrival_token&& __old_phase) const
{
__atomic_phase_const_ref_t __phase(_M_phase);
- auto const __test_fn = [=]
- {
- return __phase.load(memory_order_acquire) != __old_phase;
- };
- std::__atomic_wait_address(&_M_phase, __test_fn);
+ __phase.wait(__old_phase, memory_order_acquire);
}
void
@@ -212,6 +245,8 @@ It looks different from literature pseudocode for two main reasons:
template<typename _CompletionF = __empty_completion>
class barrier
{
+ static_assert(is_invocable_v<_CompletionF&>);
+
// Note, we may introduce a "central" barrier algorithm at some point
// for more space constrained targets
using __algorithm_t = __tree_barrier<_CompletionF>;
@@ -236,7 +271,7 @@ It looks different from literature pseudocode for two main reasons:
max() noexcept
{ return __algorithm_t::max(); }
- explicit
+ constexpr explicit
barrier(ptrdiff_t __count, _CompletionF __completion = _CompletionF())
: _M_b(__count, std::move(__completion))
{ }
diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit
index a481781..fd75edf 100644
--- a/libstdc++-v3/include/std/bit
+++ b/libstdc++-v3/include/std/bit
@@ -153,18 +153,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif // __cpp_lib_byteswap
/// @cond undocumented
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
template<typename _Tp>
constexpr _Tp
__rotl(_Tp __x, int __s) noexcept
{
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
- if _GLIBCXX17_CONSTEXPR ((_Nd & (_Nd - 1)) == 0)
+ if constexpr ((_Nd & (_Nd - 1)) == 0)
{
// Variant for power of two _Nd which the compiler can
// easily pattern match.
constexpr unsigned __uNd = _Nd;
- const unsigned __r = __s;
+ const auto __r = static_cast<unsigned>(__s);
return (__x << (__r % __uNd)) | (__x >> ((-__r) % __uNd));
}
const int __r = __s % _Nd;
@@ -181,12 +183,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__rotr(_Tp __x, int __s) noexcept
{
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
- if _GLIBCXX17_CONSTEXPR ((_Nd & (_Nd - 1)) == 0)
+ if constexpr ((_Nd & (_Nd - 1)) == 0)
{
// Variant for power of two _Nd which the compiler can
// easily pattern match.
constexpr unsigned __uNd = _Nd;
- const unsigned __r = __s;
+ const auto __r = static_cast<unsigned>(__s);
return (__x >> (__r % __uNd)) | (__x << ((-__r) % __uNd));
}
const int __r = __s % _Nd;
@@ -215,17 +217,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr auto _Nd_ul = __int_traits<unsigned long>::__digits;
constexpr auto _Nd_u = __int_traits<unsigned>::__digits;
- if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
+ if constexpr (_Nd <= _Nd_u)
{
constexpr int __diff = _Nd_u - _Nd;
return __builtin_clz(__x) - __diff;
}
- else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
+ else if constexpr (_Nd <= _Nd_ul)
{
constexpr int __diff = _Nd_ul - _Nd;
return __builtin_clzl(__x) - __diff;
}
- else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
+ else if constexpr (_Nd <= _Nd_ull)
{
constexpr int __diff = _Nd_ull - _Nd;
return __builtin_clzll(__x) - __diff;
@@ -272,11 +274,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr auto _Nd_ul = __int_traits<unsigned long>::__digits;
constexpr auto _Nd_u = __int_traits<unsigned>::__digits;
- if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
+ if constexpr (_Nd <= _Nd_u)
return __builtin_ctz(__x);
- else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
+ else if constexpr (_Nd <= _Nd_ul)
return __builtin_ctzl(__x);
- else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
+ else if constexpr (_Nd <= _Nd_ull)
return __builtin_ctzll(__x);
else // (_Nd > _Nd_ull)
{
@@ -314,11 +316,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr auto _Nd_ul = __int_traits<unsigned long>::__digits;
constexpr auto _Nd_u = __int_traits<unsigned>::__digits;
- if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
+ if constexpr (_Nd <= _Nd_u)
return __builtin_popcount(__x);
- else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
+ else if constexpr (_Nd <= _Nd_ul)
return __builtin_popcountl(__x);
- else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
+ else if constexpr (_Nd <= _Nd_ull)
return __builtin_popcountll(__x);
else // (_Nd > _Nd_ull)
{
@@ -357,7 +359,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
using __promoted_type = decltype(__x << 1);
- if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value)
+ if constexpr (!is_same<__promoted_type, _Tp>::value)
{
// If __x undergoes integral promotion then shifting by _Nd is
// not undefined. In order to make the shift undefined, so that
@@ -388,6 +390,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return _Nd - std::__countl_zero(__x);
}
+#pragma GCC diagnostic pop
/// @endcond
#ifdef __cpp_lib_bitops // C++ >= 20
diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset
index c07117a..8b5d270 100644
--- a/libstdc++-v3/include/std/bitset
+++ b/libstdc++-v3/include/std/bitset
@@ -1605,6 +1605,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef std::basic_istream<_CharT, _Traits> __istream_type;
typedef typename __istream_type::ios_base __ios_base;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
struct _Buffer
{
static _GLIBCXX_CONSTEXPR bool _S_use_alloca() { return _Nb <= 256; }
@@ -1613,18 +1615,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
~_Buffer()
{
- if _GLIBCXX17_CONSTEXPR (!_S_use_alloca())
+ if _GLIBCXX_CONSTEXPR (!_S_use_alloca())
delete[] _M_ptr;
}
_CharT* const _M_ptr;
};
_CharT* __ptr;
- if _GLIBCXX17_CONSTEXPR (_Buffer::_S_use_alloca())
+ if _GLIBCXX_CONSTEXPR (_Buffer::_S_use_alloca())
__ptr = (_CharT*)__builtin_alloca(_Nb);
else
__ptr = new _CharT[_Nb];
const _Buffer __buf(__ptr);
+#pragma GCC diagnostic pop
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 303. Bitset input operator underspecified
@@ -1673,7 +1676,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ __is._M_setstate(__ios_base::badbit); }
}
- if _GLIBCXX17_CONSTEXPR (_Nb)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ if _GLIBCXX_CONSTEXPR (_Nb)
{
if (size_t __len = __ptr - __buf._M_ptr)
__x.template _M_copy_from_ptr<_CharT, _Traits>(__buf._M_ptr, __len,
@@ -1682,6 +1687,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
else
__state |= __ios_base::failbit;
}
+#pragma GCC diagnostic pop
if (__state)
__is.setstate(__state);
return __is;
diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv
index 75fcb71..dda49ce 100644
--- a/libstdc++-v3/include/std/charconv
+++ b/libstdc++-v3/include/std/charconv
@@ -35,6 +35,7 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic" // __int128
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
#include <bits/requires_hosted.h> // for error codes
@@ -239,7 +240,7 @@ namespace __detail
to_chars_result __res;
unsigned __len = 0;
- if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Tp>::__digits <= 16)
+ if constexpr (__gnu_cxx::__int_traits<_Tp>::__digits <= 16)
{
__len = __val > 077777u ? 6u
: __val > 07777u ? 5u
@@ -336,7 +337,7 @@ namespace __detail
*__first = '0';
return { __first + 1, errc{} };
}
- else if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
+ else if constexpr (std::is_signed<_Tp>::value)
if (__value < 0)
{
*__first++ = '-';
@@ -452,7 +453,7 @@ namespace __detail
_GLIBCXX20_CONSTEXPR unsigned char
__from_chars_alnum_to_val(unsigned char __c)
{
- if _GLIBCXX17_CONSTEXPR (_DecOnly)
+ if constexpr (_DecOnly)
return static_cast<unsigned char>(__c - '0');
else
return __from_chars_alnum_to_val_table<_DecOnly>::value.__data[__c];
@@ -562,7 +563,7 @@ namespace __detail
from_chars_result __res{__first, {}};
int __sign = 1;
- if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
+ if constexpr (std::is_signed<_Tp>::value)
if (__first != __last && *__first == '-')
{
__sign = -1;
@@ -595,7 +596,7 @@ namespace __detail
__res.ec = errc::result_out_of_range;
else
{
- if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
+ if constexpr (std::is_signed<_Tp>::value)
{
_Tp __tmp;
if (__builtin_mul_overflow(__val, __sign, &__tmp))
@@ -605,8 +606,8 @@ namespace __detail
}
else
{
- if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Up>::__max
- > __gnu_cxx::__int_traits<_Tp>::__max)
+ if constexpr (__gnu_cxx::__int_traits<_Up>::__max
+ > __gnu_cxx::__int_traits<_Tp>::__max)
{
if (__val > __gnu_cxx::__int_traits<_Tp>::__max)
__res.ec = errc::result_out_of_range;
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index 8eb9fd9..cb8213e 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -2305,8 +2305,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__r *= 10;
return __r;
}
-
- template<typename _Duration> struct __utc_leap_second;
}
/// @endcond
@@ -2481,30 +2479,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__byte_duration<ratio<1>> _M_s{};
bool _M_is_neg{};
__subseconds<precision> _M_ss{};
-
- template<typename> friend struct __detail::__utc_leap_second;
};
- /// @cond undocumented
- namespace __detail
- {
- // Represents a time that is within a leap second insertion.
- template<typename _Duration>
- struct __utc_leap_second
- {
- explicit
- __utc_leap_second(const sys_time<_Duration>& __s)
- : _M_date(chrono::floor<days>(__s)), _M_time(__s - _M_date)
- {
- ++_M_time._M_s;
- }
-
- sys_days _M_date;
- hh_mm_ss<common_type_t<_Duration, days>> _M_time;
- };
- }
- /// @endcond
-
// 12/24 HOURS FUNCTIONS
constexpr bool
diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex
index 59ef905..d9d2d8a 100644
--- a/libstdc++-v3/include/std/complex
+++ b/libstdc++-v3/include/std/complex
@@ -969,7 +969,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
- // 26.2.7/4: arg(__z): Returns the phase angle of __z.
+ // C++11 26.4.7 [complex.value.ops]/4: arg(z): Returns the phase angle of z.
template<typename _Tp>
inline _Tp
__complex_arg(const complex<_Tp>& __z)
@@ -2123,8 +2123,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp> std::complex<_Tp> acosh(const std::complex<_Tp>&);
template<typename _Tp> std::complex<_Tp> asinh(const std::complex<_Tp>&);
template<typename _Tp> std::complex<_Tp> atanh(const std::complex<_Tp>&);
- // DR 595.
- template<typename _Tp> _Tp fabs(const std::complex<_Tp>&);
template<typename _Tp>
inline std::complex<_Tp>
@@ -2309,7 +2307,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
acos(const std::complex<_Tp>& __z)
{ return __complex_acos(__z.__rep()); }
#else
- /// acos(__z) [8.1.2].
+ /// acos(__z) C++11 26.4.8 [complex.transcendentals]
// Effects: Behaves the same as C99 function cacos, defined
// in subclause 7.3.5.1.
template<typename _Tp>
@@ -2345,7 +2343,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
asin(const std::complex<_Tp>& __z)
{ return __complex_asin(__z.__rep()); }
#else
- /// asin(__z) [8.1.3].
+ /// asin(__z) C++11 26.4.8 [complex.transcendentals]
// Effects: Behaves the same as C99 function casin, defined
// in subclause 7.3.5.2.
template<typename _Tp>
@@ -2389,7 +2387,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
atan(const std::complex<_Tp>& __z)
{ return __complex_atan(__z.__rep()); }
#else
- /// atan(__z) [8.1.4].
+ /// atan(__z) C++11 26.4.8 [complex.transcendentals]
// Effects: Behaves the same as C99 function catan, defined
// in subclause 7.3.5.3.
template<typename _Tp>
@@ -2425,7 +2423,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
acosh(const std::complex<_Tp>& __z)
{ return __complex_acosh(__z.__rep()); }
#else
- /// acosh(__z) [8.1.5].
+ /// acosh(__z) C++11 26.4.8 [complex.transcendentals]
// Effects: Behaves the same as C99 function cacosh, defined
// in subclause 7.3.6.1.
template<typename _Tp>
@@ -2464,7 +2462,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
asinh(const std::complex<_Tp>& __z)
{ return __complex_asinh(__z.__rep()); }
#else
- /// asinh(__z) [8.1.6].
+ /// asinh(__z) C++11 26.4.8 [complex.transcendentals]
// Effects: Behaves the same as C99 function casin, defined
// in subclause 7.3.6.2.
template<typename _Tp>
@@ -2508,7 +2506,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
atanh(const std::complex<_Tp>& __z)
{ return __complex_atanh(__z.__rep()); }
#else
- /// atanh(__z) [8.1.7].
+ /// atanh(__z) C++11 26.4.8 [complex.transcendentals]
// Effects: Behaves the same as C99 function catanh, defined
// in subclause 7.3.6.3.
template<typename _Tp>
@@ -2518,22 +2516,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
template<typename _Tp>
+ _GLIBCXX11_DEPRECATED_SUGGEST("std::abs")
inline _Tp
- /// fabs(__z) [8.1.8].
+ /// fabs(__z) TR1 8.1.8 [tr.c99.cmplx.fabs]
// Effects: Behaves the same as C99 function cabs, defined
// in subclause 7.3.8.1.
fabs(const std::complex<_Tp>& __z)
{ return std::abs(__z); }
- /// Additional overloads [8.1.9].
+ // Additional overloads C++11 26.4.9 [cmplx.over]
+
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
arg(_Tp __x)
{
typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
#if (_GLIBCXX11_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC)
- return std::signbit(__x) ? __type(3.1415926535897932384626433832795029L)
- : __type();
+ return __builtin_signbit(__type(__x))
+ ? __type(3.1415926535897932384626433832795029L) : __type();
#else
return std::arg(std::complex<__type>(__x));
#endif
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index 8fd7300..2badab8 100644
--- a/libstdc++-v3/include/std/deque
+++ b/libstdc++-v3/include/std/deque
@@ -72,6 +72,7 @@
#define __glibcxx_want_algorithm_default_value_type
#define __glibcxx_want_allocator_traits_is_always_equal
+#define __glibcxx_want_containers_ranges
#define __glibcxx_want_erase_if
#define __glibcxx_want_nonmember_container_access
#include <bits/version.h>
diff --git a/libstdc++-v3/include/std/expected b/libstdc++-v3/include/std/expected
index 5dc1dfb..60f1565 100644
--- a/libstdc++-v3/include/std/expected
+++ b/libstdc++-v3/include/std/expected
@@ -1169,13 +1169,13 @@ namespace __expected
return !__y.has_value() && bool(__x.error() == __y.error());
}
- template<typename _Up>
+ template<typename _Up, same_as<_Tp> _Vp>
requires (!__expected::__is_expected<_Up>)
&& requires (const _Tp& __t, const _Up& __u) {
{ __t == __u } -> convertible_to<bool>;
}
friend constexpr bool
- operator==(const expected& __x, const _Up& __v)
+ operator==(const expected<_Vp, _Er>& __x, const _Up& __v)
noexcept(noexcept(bool(*__x == __v)))
{ return __x.has_value() && bool(*__x == __v); }
diff --git a/libstdc++-v3/include/std/flat_map b/libstdc++-v3/include/std/flat_map
index 405caa8..de006ad 100644
--- a/libstdc++-v3/include/std/flat_map
+++ b/libstdc++-v3/include/std/flat_map
@@ -873,7 +873,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[nodiscard]]
friend bool
operator==(const _Derived& __x, const _Derived& __y)
- { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); }
+ {
+ return __x._M_cont.keys == __y._M_cont.keys
+ && __x._M_cont.values == __y._M_cont.values;
+ }
template<typename _Up = value_type>
[[nodiscard]]
@@ -890,14 +893,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __x.swap(__y); }
template<typename _Predicate>
- friend size_type
- erase_if(_Derived& __c, _Predicate __pred)
+ size_type
+ _M_erase_if(_Predicate __pred)
{
- auto __guard = __c._M_make_clear_guard();
- auto __zv = views::zip(__c._M_cont.keys, __c._M_cont.values);
- auto __sr = ranges::remove_if(__zv, __pred);
+ auto __guard = _M_make_clear_guard();
+ auto __zv = views::zip(_M_cont.keys, _M_cont.values);
+ auto __sr = ranges::remove_if(__zv, __pred,
+ [](const auto& __e) {
+ return const_reference(__e);
+ });
auto __erased = __sr.size();
- __c.erase(__c.end() - __erased, __c.end());
+ erase(end() - __erased, end());
__guard._M_disable();
return __erased;
}
@@ -1142,14 +1148,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// element access
mapped_type&
operator[](const key_type& __x)
- { return operator[]<const key_type>(__x); }
+ { return try_emplace(__x).first->second; }
mapped_type&
operator[](key_type&& __x)
- { return operator[]<key_type>(std::move(__x)); }
+ { return try_emplace(std::move(__x)).first->second; }
template<typename _Key2>
- requires same_as<remove_cvref_t<_Key2>, _Key> || __transparent_comparator<_Compare>
+ requires __transparent_comparator<_Compare>
mapped_type&
operator[](_Key2&& __x)
{ return try_emplace(std::forward<_Key2>(__x)).first->second; }
@@ -1329,6 +1335,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using _Impl::lower_bound;
using _Impl::upper_bound;
using _Impl::equal_range;
+
+ using _Impl::_M_erase_if;
};
template<typename _KeyContainer, typename _MappedContainer,
@@ -1412,6 +1420,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& uses_allocator_v<_MappedContainer, _Alloc>>
{ };
+ template<typename _Key, typename _Tp, typename _Compare,
+ typename _KeyContainer, typename _MappedContainer, typename _Predicate>
+ typename flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type
+ erase_if(flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __c,
+ _Predicate __pred)
+ { return __c._M_erase_if(std::move(__pred)); }
+
/* Class template flat_multimap - container adaptor
*
* @ingroup
@@ -1487,6 +1502,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using _Impl::lower_bound;
using _Impl::upper_bound;
using _Impl::equal_range;
+
+ using _Impl::_M_erase_if;
};
template<typename _KeyContainer, typename _MappedContainer,
@@ -1571,6 +1588,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& uses_allocator_v<_MappedContainer, _Alloc>>
{ };
+ template<typename _Key, typename _Tp, typename _Compare,
+ typename _KeyContainer, typename _MappedContainer, typename _Predicate>
+ typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type
+ erase_if(flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __c,
+ _Predicate __pred)
+ { return __c._M_erase_if(std::move(__pred)); }
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cpp_lib_flat_map
diff --git a/libstdc++-v3/include/std/flat_set b/libstdc++-v3/include/std/flat_set
index 3e15d1a..c48340d 100644
--- a/libstdc++-v3/include/std/flat_set
+++ b/libstdc++-v3/include/std/flat_set
@@ -745,15 +745,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __x.swap(__y); }
template<typename _Predicate>
- friend size_type
- erase_if(_Derived& __c, _Predicate __pred)
+ size_type
+ _M_erase_if(_Predicate __pred)
{
- auto __guard = __c._M_make_clear_guard();
- auto __first = __c._M_cont.begin();
- auto __last = __c._M_cont.end();
+ auto __guard = _M_make_clear_guard();
+ auto __first = _M_cont.begin();
+ auto __last = _M_cont.end();
__first = std::remove_if(__first, __last, __pred);
auto __n = __last - __first;
- __c.erase(__first, __last);
+ erase(__first, __last);
__guard._M_disable();
return __n;
}
@@ -860,6 +860,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using _Impl::lower_bound;
using _Impl::upper_bound;
using _Impl::equal_range;
+
+ using _Impl::_M_erase_if;
};
template<typename _KeyContainer,
@@ -930,6 +932,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: bool_constant<uses_allocator_v<_KeyContainer, _Alloc>>
{ };
+ template<typename _Key, typename _Compare, typename _KeyContainer,
+ typename _Predicate>
+ typename flat_set<_Key, _Compare, _KeyContainer>::size_type
+ erase_if(flat_set<_Key, _Compare, _KeyContainer>& __c, _Predicate __pred)
+ { return __c._M_erase_if(std::move(__pred)); }
+
/* Class template flat_multiset - container adaptor
*
* @ingroup
@@ -999,6 +1007,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using _Impl::lower_bound;
using _Impl::upper_bound;
using _Impl::equal_range;
+
+ using _Impl::_M_erase_if;
};
template<typename _KeyContainer,
@@ -1069,6 +1079,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: bool_constant<uses_allocator_v<_KeyContainer, _Alloc>>
{ };
+ template<typename _Key, typename _Compare, typename _KeyContainer,
+ typename _Predicate>
+ typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type
+ erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __c, _Predicate __pred)
+ { return __c._M_erase_if(std::move(__pred)); }
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cpp_lib_flat_set
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 2e9319c..46bd5d5 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -56,7 +56,7 @@
#include <bits/ranges_base.h> // input_range, range_reference_t
#include <bits/ranges_util.h> // subrange
#include <bits/ranges_algobase.h> // ranges::copy
-#include <bits/stl_iterator.h> // back_insert_iterator
+#include <bits/stl_iterator.h> // back_insert_iterator, counted_iterator
#include <bits/stl_pair.h> // __is_pair
#include <bits/unicode.h> // __is_scalar_value, _Utf_view, etc.
#include <bits/utility.h> // tuple_size_v
@@ -80,12 +80,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// @cond undocumented
namespace __format
{
- // Type-erased character sink.
+ // STATICALLY-WIDEN, see C++20 [time.general]
+ // It doesn't matter for format strings (which can only be char or wchar_t)
+ // but this returns the narrow string for anything that isn't wchar_t. This
+ // is done because const char* can be inserted into any ostream type, and
+ // will be widened at runtime if necessary.
+ template<typename _CharT>
+ consteval auto
+ _Widen(const char* __narrow, const wchar_t* __wide)
+ {
+ if constexpr (is_same_v<_CharT, wchar_t>)
+ return __wide;
+ else
+ return __narrow;
+ }
+#define _GLIBCXX_WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define _GLIBCXX_WIDEN(S) _GLIBCXX_WIDEN_(_CharT, S)
+
+ // Size for stack located buffer
+ template<typename _CharT>
+ constexpr size_t __stackbuf_size = 32 * sizeof(void*) / sizeof(_CharT);
+
+ // Type-erased character sinks.
template<typename _CharT> class _Sink;
+ template<typename _CharT> class _Fixedbuf_sink;
+ template<typename _Out, typename _CharT> class _Padding_sink;
+
// Output iterator that writes to a type-erase character sink.
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>;
@@ -104,6 +133,7 @@ namespace __format
template<typename, typename...> friend struct std::basic_format_string;
};
+
} // namespace __format
/// @endcond
@@ -442,36 +472,33 @@ namespace __format
return {0, nullptr};
}
- enum _Pres_type {
+ enum class _Pres_type : unsigned char {
_Pres_none = 0, // Default type (not valid for integer presentation types).
+ _Pres_s = 1, // For strings, bool, ranges
// Presentation types for integral types (including bool and charT).
- _Pres_d = 1, _Pres_b, _Pres_B, _Pres_o, _Pres_x, _Pres_X, _Pres_c,
- // Presentation types for floating-point types.
- _Pres_a = 1, _Pres_A, _Pres_e, _Pres_E, _Pres_f, _Pres_F, _Pres_g, _Pres_G,
- _Pres_p = 0, _Pres_P, // For pointers.
- _Pres_s = 0, // For strings and bool.
- _Pres_esc = 0xf, // For strings and charT.
- };
-
- enum _Align {
- _Align_default,
- _Align_left,
- _Align_right,
- _Align_centre,
+ _Pres_c = 2, _Pres_x, _Pres_X, _Pres_d, _Pres_o, _Pres_b, _Pres_B,
+ // Presentation types for floating-point types
+ _Pres_g = 1, _Pres_G, _Pres_a, _Pres_A, _Pres_e, _Pres_E, _Pres_f, _Pres_F,
+ // For pointers, the value are same as hexadecimal presentations for integers
+ _Pres_p = _Pres_x, _Pres_P = _Pres_X,
+ _Pres_max = 0xf,
};
+ using enum _Pres_type;
- enum _Sign {
+ enum class _Sign : unsigned char {
_Sign_default,
_Sign_plus,
_Sign_minus, // XXX does this need to be distinct from _Sign_default?
_Sign_space,
};
+ using enum _Sign;
- enum _WidthPrec {
+ enum _WidthPrec : unsigned char {
_WP_none, // No width/prec specified.
_WP_value, // Fixed width/prec specified.
_WP_from_arg // Use a formatting argument for width/prec.
};
+ using enum _WidthPrec;
template<typename _Context>
size_t
@@ -483,9 +510,17 @@ namespace __format
constexpr bool __is_xdigit(char __c)
{ return std::__detail::__from_chars_alnum_to_val(__c) < 16; }
+ // Used to make _Spec a non-C++98 POD, so the tail-padding is used.
+ // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#pod
+ struct _SpecBase
+ { };
+
template<typename _CharT>
- struct _Spec
+ struct _Spec : _SpecBase
{
+ unsigned short _M_width;
+ unsigned short _M_prec;
+ char32_t _M_fill = ' ';
_Align _M_align : 2;
_Sign _M_sign : 2;
unsigned _M_alt : 1;
@@ -493,12 +528,11 @@ namespace __format
unsigned _M_zero_fill : 1;
_WidthPrec _M_width_kind : 2;
_WidthPrec _M_prec_kind : 2;
+ unsigned _M_debug : 1;
_Pres_type _M_type : 4;
- unsigned _M_reserved : 1;
- unsigned _M_reserved2 : 16;
- unsigned short _M_width;
- unsigned short _M_prec;
- char32_t _M_fill = ' ';
+ unsigned _M_reserved : 8;
+ // This class has 8 bits of tail padding, that can be used by
+ // derived classes.
using iterator = typename basic_string_view<_CharT>::iterator;
@@ -517,42 +551,48 @@ namespace __format
// pre: __first != __last
constexpr iterator
_M_parse_fill_and_align(iterator __first, iterator __last) noexcept
+ { return _M_parse_fill_and_align(__first, __last, "{"); }
+
+ // pre: __first != __last
+ constexpr iterator
+ _M_parse_fill_and_align(iterator __first, iterator __last, string_view __not_fill) noexcept
{
- if (*__first != '{')
+ for (char __c : __not_fill)
+ if (*__first == static_cast<_CharT>(__c))
+ return __first;
+
+ using namespace __unicode;
+ if constexpr (__literal_encoding_is_unicode<_CharT>())
{
- using namespace __unicode;
- if constexpr (__literal_encoding_is_unicode<_CharT>())
- {
- // Accept any UCS scalar value as fill character.
- _Utf32_view<ranges::subrange<iterator>> __uv({__first, __last});
- if (!__uv.empty())
- {
- auto __beg = __uv.begin();
- char32_t __c = *__beg++;
- if (__is_scalar_value(__c))
- if (auto __next = __beg.base(); __next != __last)
- if (_Align __align = _S_align(*__next))
- {
- _M_fill = __c;
- _M_align = __align;
- return ++__next;
- }
- }
- }
- else if (__last - __first >= 2)
- if (_Align __align = _S_align(__first[1]))
- {
- _M_fill = *__first;
- _M_align = __align;
- return __first + 2;
- }
+ // Accept any UCS scalar value as fill character.
+ _Utf32_view<ranges::subrange<iterator>> __uv({__first, __last});
+ if (!__uv.empty())
+ {
+ auto __beg = __uv.begin();
+ char32_t __c = *__beg++;
+ if (__is_scalar_value(__c))
+ if (auto __next = __beg.base(); __next != __last)
+ if (_Align __align = _S_align(*__next); __align != _Align_default)
+ {
+ _M_fill = __c;
+ _M_align = __align;
+ return ++__next;
+ }
+ }
+ }
+ else if (__last - __first >= 2)
+ if (_Align __align = _S_align(__first[1]); __align != _Align_default)
+ {
+ _M_fill = *__first;
+ _M_align = __align;
+ return __first + 2;
+ }
- if (_Align __align = _S_align(__first[0]))
- {
- _M_fill = ' ';
- _M_align = __align;
- return __first + 1;
- }
+ if (_Align __align = _S_align(__first[0]); __align != _Align_default)
+ {
+ _M_fill = ' ';
+ _M_align = __align;
+ return __first + 1;
}
return __first;
}
@@ -573,7 +613,7 @@ namespace __format
constexpr iterator
_M_parse_sign(iterator __first, iterator) noexcept
{
- if (_Sign __sign = _S_sign(*__first))
+ if (_Sign __sign = _S_sign(*__first); __sign != _Sign_default)
{
_M_sign = __sign;
return __first + 1;
@@ -841,13 +881,336 @@ namespace __format
const size_t __nfill = __width - __estimated_width;
- if (__spec._M_align)
+ if (__spec._M_align != _Align_default)
__align = __spec._M_align;
return __format::__write_padded(__fc.out(), __str, __align, __nfill,
__spec._M_fill);
}
+ template<typename _CharT>
+ size_t
+ __truncate(basic_string_view<_CharT>& __s, size_t __prec)
+ {
+ if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
+ {
+ if (__prec != (size_t)-1)
+ return __unicode::__truncate(__s, __prec);
+ else
+ return __unicode::__field_width(__s);
+ }
+ else
+ {
+ __s = __s.substr(0, __prec);
+ return __s.size();
+ }
+ }
+
+ enum class _Term_char : unsigned char {
+ _Term_none,
+ _Term_quote,
+ _Term_apos,
+ };
+ using enum _Term_char;
+
+ template<typename _CharT>
+ struct _Escapes
+ {
+ using _Str_view = basic_string_view<_CharT>;
+
+ static consteval
+ _Str_view _S_all()
+ { return _GLIBCXX_WIDEN("\t\\t\n\\n\r\\r\\\\\\\"\\\"'\\'\\u\\x"); }
+
+ static consteval
+ _Str_view _S_tab()
+ { return _S_all().substr(0, 3); }
+
+ static consteval
+ _Str_view _S_newline()
+ { return _S_all().substr(3, 3); }
+
+ static consteval
+ _Str_view _S_return()
+ { return _S_all().substr(6, 3); }
+
+ static consteval
+ _Str_view _S_bslash()
+ { return _S_all().substr(9, 3); }
+
+ static consteval
+ _Str_view _S_quote()
+ { return _S_all().substr(12, 3); }
+
+ static consteval
+ _Str_view _S_apos()
+ { return _S_all().substr(15, 3); }
+
+ static consteval
+ _Str_view _S_u()
+ { return _S_all().substr(18, 2); }
+
+ static consteval
+ _Str_view _S_x()
+ { return _S_all().substr(20, 2); }
+
+ static constexpr
+ _Str_view _S_term(_Term_char __term)
+ {
+ switch (__term)
+ {
+ case _Term_none:
+ return _Str_view();
+ case _Term_quote:
+ return _S_quote().substr(0, 1);
+ case _Term_apos:
+ return _S_apos().substr(0, 1);
+ }
+ __builtin_unreachable();
+ }
+ };
+
+ template<typename _CharT>
+ struct _Separators
+ {
+ using _Str_view = basic_string_view<_CharT>;
+
+ static consteval
+ _Str_view _S_all()
+ { return _GLIBCXX_WIDEN("[]{}(), : "); }
+
+ static consteval
+ _Str_view _S_squares()
+ { return _S_all().substr(0, 2); }
+
+ static consteval
+ _Str_view _S_braces()
+ { return _S_all().substr(2, 2); }
+
+ static consteval
+ _Str_view _S_parens()
+ { return _S_all().substr(4, 2); }
+
+ static consteval
+ _Str_view _S_comma()
+ { return _S_all().substr(6, 2); }
+
+ static consteval
+ _Str_view _S_colon()
+ { return _S_all().substr(8, 2); }
+ };
+
+ template<typename _CharT>
+ constexpr bool __should_escape_ascii(_CharT __c, _Term_char __term)
+ {
+ using _Esc = _Escapes<_CharT>;
+ switch (__c)
+ {
+ case _Esc::_S_tab()[0]:
+ case _Esc::_S_newline()[0]:
+ case _Esc::_S_return()[0]:
+ case _Esc::_S_bslash()[0]:
+ return true;
+ case _Esc::_S_quote()[0]:
+ return __term == _Term_quote;
+ case _Esc::_S_apos()[0]:
+ return __term == _Term_apos;
+ default:
+ return (__c >= 0 && __c < 0x20) || __c == 0x7f;
+ };
+ }
+
+ // @pre __c <= 0x10FFFF
+ constexpr bool __should_escape_unicode(char32_t __c, bool __prev_esc)
+ {
+ if (__unicode::__should_escape_category(__c))
+ return __c != U' ';
+ if (!__prev_esc)
+ return false;
+ return __unicode::__grapheme_cluster_break_property(__c)
+ == __unicode::_Gcb_property::_Gcb_Extend;
+ }
+
+ using uint_least32_t = __UINT_LEAST32_TYPE__;
+ template<typename _Out, typename _CharT>
+ _Out
+ __write_escape_seq(_Out __out, uint_least32_t __val,
+ basic_string_view<_CharT> __prefix)
+ {
+ using _Str_view = basic_string_view<_CharT>;
+ constexpr size_t __max = 8;
+ char __buf[__max];
+ const string_view __narrow(
+ __buf,
+ std::__to_chars_i<uint_least32_t>(__buf, __buf + __max, __val, 16).ptr);
+
+ __out = __format::__write(__out, __prefix);
+ *__out = _Separators<_CharT>::_S_braces()[0];
+ ++__out;
+ if constexpr (is_same_v<char, _CharT>)
+ __out = __format::__write(__out, __narrow);
+#ifdef _GLIBCXX_USE_WCHAR_T
+ else
+ {
+ _CharT __wbuf[__max];
+ const size_t __n = __narrow.size();
+ std::__to_wstring_numeric(__narrow.data(), __n, __wbuf);
+ __out = __format::__write(__out, _Str_view(__wbuf, __n));
+ }
+#endif
+ *__out = _Separators<_CharT>::_S_braces()[1];
+ return ++__out;
+ }
+
+ template<typename _Out, typename _CharT>
+ _Out
+ __write_escaped_char(_Out __out, _CharT __c)
+ {
+ using _UChar = make_unsigned_t<_CharT>;
+ using _Esc = _Escapes<_CharT>;
+ switch (__c)
+ {
+ case _Esc::_S_tab()[0]:
+ return __format::__write(__out, _Esc::_S_tab().substr(1, 2));
+ case _Esc::_S_newline()[0]:
+ return __format::__write(__out, _Esc::_S_newline().substr(1, 2));
+ case _Esc::_S_return()[0]:
+ return __format::__write(__out, _Esc::_S_return().substr(1, 2));
+ case _Esc::_S_bslash()[0]:
+ return __format::__write(__out, _Esc::_S_bslash().substr(1, 2));
+ case _Esc::_S_quote()[0]:
+ return __format::__write(__out, _Esc::_S_quote().substr(1, 2));
+ case _Esc::_S_apos()[0]:
+ return __format::__write(__out, _Esc::_S_apos().substr(1, 2));
+ default:
+ return __format::__write_escape_seq(
+ __out, static_cast<_UChar>(__c), _Esc::_S_u());
+ }
+ }
+
+ template<typename _CharT, typename _Out>
+ _Out
+ __write_escaped_ascii(_Out __out,
+ basic_string_view<_CharT> __str,
+ _Term_char __term)
+ {
+ using _Str_view = basic_string_view<_CharT>;
+ auto __first = __str.begin();
+ auto const __last = __str.end();
+ while (__first != __last)
+ {
+ auto __print = __first;
+ // assume anything outside ASCII is printable
+ while (__print != __last
+ && !__format::__should_escape_ascii(*__print, __term))
+ ++__print;
+
+ if (__print != __first)
+ __out = __format::__write(__out, _Str_view(__first, __print));
+
+ if (__print == __last)
+ return __out;
+
+ __first = __print;
+ __out = __format::__write_escaped_char(__out, *__first);
+ ++__first;
+ }
+ return __out;
+ }
+
+ template<typename _CharT, typename _Out>
+ _Out
+ __write_escaped_unicode(_Out __out,
+ basic_string_view<_CharT> __str,
+ _Term_char __term)
+ {
+ using _Str_view = basic_string_view<_CharT>;
+ using _UChar = make_unsigned_t<_CharT>;
+ using _Esc = _Escapes<_CharT>;
+
+ static constexpr char32_t __replace = U'\uFFFD';
+ static constexpr _Str_view __replace_rep = []
+ {
+ // N.B. "\uFFFD" is ill-formed if encoding is not unicode.
+ if constexpr (is_same_v<char, _CharT>)
+ return "\xEF\xBF\xBD";
+ else
+ return L"\xFFFD";
+ }();
+
+ __unicode::_Utf_view<char32_t, _Str_view> __v(std::move(__str));
+ auto __first = __v.begin();
+ auto const __last = __v.end();
+
+ bool __prev_esc = true;
+ while (__first != __last)
+ {
+ bool __esc_ascii = false;
+ bool __esc_unicode = false;
+ bool __esc_replace = false;
+ auto __should_escape = [&](auto const& __it)
+ {
+ if (*__it <= 0x7f)
+ return __esc_ascii
+ = __format::__should_escape_ascii(*__it.base(), __term);
+ if (__format::__should_escape_unicode(*__it, __prev_esc))
+ return __esc_unicode = true;
+ if (*__it == __replace)
+ {
+ _Str_view __units(__it.base(), __it._M_units());
+ return __esc_replace = (__units != __replace_rep);
+ }
+ return false;
+ };
+
+ auto __print = __first;
+ while (__print != __last && !__should_escape(__print))
+ {
+ __prev_esc = false;
+ ++__print;
+ }
+
+ if (__print != __first)
+ __out = __format::__write(__out, _Str_view(__first.base(), __print.base()));
+
+ if (__print == __last)
+ return __out;
+
+ __first = __print;
+ if (__esc_ascii)
+ __out = __format::__write_escaped_char(__out, *__first.base());
+ else if (__esc_unicode)
+ __out = __format::__write_escape_seq(__out, *__first, _Esc::_S_u());
+ else // __esc_replace
+ for (_CharT __c : _Str_view(__first.base(), __first._M_units()))
+ __out = __format::__write_escape_seq(__out,
+ static_cast<_UChar>(__c),
+ _Esc::_S_x());
+ __prev_esc = true;
+ ++__first;
+
+ }
+ return __out;
+ }
+
+ template<typename _CharT, typename _Out>
+ _Out
+ __write_escaped(_Out __out, basic_string_view<_CharT> __str, _Term_char __term)
+ {
+ __out = __format::__write(__out, _Escapes<_CharT>::_S_term(__term));
+
+ if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
+ __out = __format::__write_escaped_unicode(__out, __str, __term);
+ else if constexpr (is_same_v<char, _CharT>
+ && __unicode::__literal_encoding_is_extended_ascii())
+ __out = __format::__write_escaped_ascii(__out, __str, __term);
+ else
+ // TODO Handle non-ascii extended encoding
+ __out = __format::__write_escaped_ascii(__out, __str, __term);
+
+ return __format::__write(__out, _Escapes<_CharT>::_S_term(__term));
+ }
+
// A lightweight optional<locale>.
struct _Optional_locale
{
@@ -924,6 +1287,13 @@ namespace __format
template<__char _CharT>
struct __formatter_str
{
+ __formatter_str() = default;
+
+ constexpr
+ __formatter_str(_Spec<_CharT> __spec) noexcept
+ : _M_spec(__spec)
+ { }
+
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
{
@@ -960,11 +1330,14 @@ namespace __format
return __first;
if (*__first == 's')
- ++__first;
-#if __cpp_lib_format_ranges
+ {
+ __spec._M_type = _Pres_s;
+ ++__first;
+ }
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
else if (*__first == '?')
{
- __spec._M_type = _Pres_esc;
+ __spec._M_debug = true;
++__first;
}
#endif
@@ -980,40 +1353,115 @@ namespace __format
format(basic_string_view<_CharT> __s,
basic_format_context<_Out, _CharT>& __fc) const
{
- if (_M_spec._M_type == _Pres_esc)
- {
- // TODO: C++23 escaped string presentation
- }
+ if (_M_spec._M_debug)
+ return _M_format_escaped(__s, __fc);
if (_M_spec._M_width_kind == _WP_none
&& _M_spec._M_prec_kind == _WP_none)
return __format::__write(__fc.out(), __s);
- size_t __estimated_width;
- if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
+ const size_t __maxwidth = _M_spec._M_get_precision(__fc);
+ const size_t __width = __format::__truncate(__s, __maxwidth);
+ return __format::__write_padded_as_spec(__s, __width, __fc, _M_spec);
+ }
+
+ template<typename _Out>
+ _Out
+ _M_format_escaped(basic_string_view<_CharT> __s,
+ basic_format_context<_Out, _CharT>& __fc) const
+ {
+ const size_t __padwidth = _M_spec._M_get_width(__fc);
+ if (__padwidth == 0 && _M_spec._M_prec_kind == _WP_none)
+ return __format::__write_escaped(__fc.out(), __s, _Term_quote);
+
+ const size_t __maxwidth = _M_spec._M_get_precision(__fc);
+ const size_t __width = __truncate(__s, __maxwidth);
+ // N.B. Escaping only increases width
+ if (__padwidth <= __width && _M_spec._M_prec_kind == _WP_none)
+ return __format::__write_escaped(__fc.out(), __s, _Term_quote);
+
+ // N.B. [tab:format.type.string] defines '?' as
+ // Copies the escaped string ([format.string.escaped]) to the output,
+ // so precision seem to appy to escaped string.
+ _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth, __maxwidth);
+ __format::__write_escaped(__sink.out(), __s, _Term_quote);
+ return __sink._M_finish(_M_spec._M_align, _M_spec._M_fill);
+ }
+
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
+ template<ranges::input_range _Rg, typename _Out>
+ requires same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, _CharT>
+ _Out
+ _M_format_range(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const
+ {
+ using _Range = remove_reference_t<_Rg>;
+ using _String = basic_string<_CharT>;
+ using _String_view = basic_string_view<_CharT>;
+ if constexpr (!is_lvalue_reference_v<_Rg>)
+ return _M_format_range<_Range&>(__rg, __fc);
+ else if constexpr (!is_const_v<_Range>
+ && __simply_formattable_range<_Range, _CharT>)
+ return _M_format_range<const _Range&>(__rg, __fc);
+ else if constexpr (ranges::contiguous_range<_Rg>)
+ {
+ _String_view __str(ranges::data(__rg),
+ size_t(ranges::distance(__rg)));
+ return format(__str, __fc);
+ }
+ else if (!_M_spec._M_debug)
+ {
+ const size_t __padwidth = _M_spec._M_get_width(__fc);
+ if (__padwidth == 0 && _M_spec._M_prec_kind == _WP_none)
+ return ranges::copy(__rg, __fc.out()).out;
+
+ _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth,
+ _M_spec._M_get_precision(__fc));
+ ranges::copy(__rg, __sink.out());
+ return __sink._M_finish(_M_spec._M_align, _M_spec._M_fill);
+ }
+ else if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
{
- if (_M_spec._M_prec_kind != _WP_none)
+ const size_t __n(ranges::distance(__rg));
+ size_t __w = __n;
+ if constexpr (!__unicode::__literal_encoding_is_unicode<_CharT>())
+ if (size_t __max = _M_spec._M_get_precision(__fc); __n > __max)
+ __w == __max;
+
+ if (__w <= __format::__stackbuf_size<_CharT>)
{
- size_t __prec = _M_spec._M_get_precision(__fc);
- __estimated_width = __unicode::__truncate(__s, __prec);
+ _CharT __buf[__format::__stackbuf_size<_CharT>];
+ ranges::copy_n(ranges::begin(__rg), __w, __buf);
+ return _M_format_escaped(_String_view(__buf, __n), __fc);
}
+ else if constexpr (ranges::random_access_range<_Rg>)
+ {
+ ranges::iterator_t<_Rg> __first = ranges::begin(__rg);
+ ranges::subrange __sub(__first, __first + __w);
+ return _M_format_escaped(_String(from_range, __sub), __fc);
+ }
+ else if (__w <= __n)
+ {
+ ranges::subrange __sub(
+ counted_iterator(ranges::begin(__rg), __w),
+ default_sentinel);
+ return _M_format_escaped(_String(from_range, __sub), __fc);
+ }
+ else if constexpr (ranges::sized_range<_Rg>)
+ return _M_format_escaped(_String(from_range, __rg), __fc);
else
- __estimated_width = __unicode::__field_width(__s);
+ {
+ // N.B. preserve the computed size
+ ranges::subrange __sub(__rg, __n);
+ return _M_format_escaped(_String(from_range, __sub), __fc);
+ }
}
else
- {
- __s = __s.substr(0, _M_spec._M_get_precision(__fc));
- __estimated_width = __s.size();
- }
-
- return __format::__write_padded_as_spec(__s, __estimated_width,
- __fc, _M_spec);
+ return _M_format_escaped(_String(from_range, __rg), __fc);
}
-#if __cpp_lib_format_ranges
constexpr void
set_debug_format() noexcept
- { _M_spec._M_type = _Pres_esc; }
+ { _M_spec._M_debug = true; }
#endif
private:
@@ -1029,6 +1477,16 @@ 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)
+ {
+ if (_M_spec._M_type == _Pres_none)
+ _M_spec._M_type = _Pres_d;
+ }
+
constexpr typename basic_format_parse_context<_CharT>::iterator
_M_do_parse(basic_format_parse_context<_CharT>& __pc, _Pres_type __type)
{
@@ -1116,15 +1574,15 @@ namespace __format
case 's':
if (__type == _AsBool)
{
- __spec._M_type = _Pres_s; // same value (and meaning) as "none"
+ __spec._M_type = _Pres_s; // same meaning as "none" for bool
++__first;
}
break;
-#if __cpp_lib_format_ranges
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
case '?':
if (__type == _AsChar)
{
- __spec._M_type = _Pres_esc;
+ __spec._M_debug = true;
++__first;
}
#endif
@@ -1145,7 +1603,8 @@ namespace __format
{
auto __end = _M_do_parse(__pc, _AsBool);
if (_M_spec._M_type == _Pres_s)
- if (_M_spec._M_sign || _M_spec._M_alt || _M_spec._M_zero_fill)
+ if (_M_spec._M_sign != _Sign_default || _M_spec._M_alt
+ || _M_spec._M_zero_fill)
__throw_format_error("format error: format-spec contains "
"invalid formatting options for "
"'bool'");
@@ -1154,8 +1613,9 @@ namespace __format
else if constexpr (__char<_Tp>)
{
auto __end = _M_do_parse(__pc, _AsChar);
- if (_M_spec._M_type == _Pres_c || _M_spec._M_type == _Pres_esc)
- if (_M_spec._M_sign || _M_spec._M_alt || _M_spec._M_zero_fill
+ if (_M_spec._M_type == _Pres_c)
+ if (_M_spec._M_sign != _Sign_default || _M_spec._M_alt
+ || _M_spec._M_zero_fill
/* XXX should be invalid? || _M_spec._M_localized */)
__throw_format_error("format error: format-spec contains "
"invalid formatting options for "
@@ -1267,26 +1727,35 @@ namespace __format
_M_spec);
}
- [[__gnu__::__always_inline__]]
- static size_t
- _S_character_width(_CharT __c)
- {
- // N.B. single byte cannot encode charcter of width greater than 1
- if constexpr (sizeof(_CharT) > 1u &&
- __unicode::__literal_encoding_is_unicode<_CharT>())
- return __unicode::__field_width(__c);
- else
- return 1u;
- }
-
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
_M_format_character(_CharT __c,
- basic_format_context<_Out, _CharT>& __fc) const
+ basic_format_context<_Out, _CharT>& __fc) const
{
- return __format::__write_padded_as_spec({&__c, 1u},
- _S_character_width(__c),
- __fc, _M_spec);
+ basic_string_view<_CharT> __in(&__c, 1u);
+ size_t __width = 1u;
+ // N.B. single byte cannot encode character of width greater than 1
+ if constexpr (sizeof(_CharT) > 1u &&
+ __unicode::__literal_encoding_is_unicode<_CharT>())
+ __width = __unicode::__field_width(__c);
+
+ if (!_M_spec._M_debug)
+ return __format::__write_padded_as_spec(__in, __width,
+ __fc, _M_spec);
+
+ __width += 2;
+ if (_M_spec._M_get_width(__fc) <= __width)
+ return __format::__write_escaped(__fc.out(), __in, _Term_apos);
+
+ _CharT __buf[12];
+ _Fixedbuf_sink<_CharT> __sink(__buf);
+ __format::__write_escaped(__sink.out(), __in, _Term_apos);
+
+ __in = __sink.view();
+ if (__in[1] == _Escapes<_CharT>::_S_bslash()[0]) // escape sequence
+ __width = __in.size();
+ return __format::__write_padded_as_spec(__in, __width,
+ __fc, _M_spec);
}
template<typename _Int>
@@ -1402,20 +1871,24 @@ namespace __format
_Spec<_CharT> _M_spec{};
};
+#ifdef __BFLT16_DIG__
+ using __bflt16_t = decltype(0.0bf16);
+#endif
+
// Decide how 128-bit floating-point types should be formatted (or not).
- // When supported, the typedef __format::__float128_t is the type that
- // format arguments should be converted to for storage in basic_format_arg.
+ // When supported, the typedef __format::__flt128_t is the type that format
+ // arguments should be converted to before passing them to __formatter_fp.
// Define the macro _GLIBCXX_FORMAT_F128 to say they're supported.
- // _GLIBCXX_FORMAT_F128=1 means __float128, _Float128 etc. will be formatted
- // by converting them to long double (or __ieee128 for powerpc64le).
- // _GLIBCXX_FORMAT_F128=2 means basic_format_arg needs to enable explicit
- // support for _Float128, rather than formatting it as another type.
+ // The __float128, _Float128 will be formatted by converting them to:
+ // __ieee128 (same as __float128) when _GLIBCXX_FORMAT_F128=1,
+ // long double when _GLIBCXX_FORMAT_F128=2,
+ // _Float128 when _GLIBCXX_FORMAT_F128=3.
#undef _GLIBCXX_FORMAT_F128
#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
// Format 128-bit floating-point types using __ieee128.
- using __float128_t = __ieee128;
+ using __flt128_t = __ieee128;
# define _GLIBCXX_FORMAT_F128 1
#ifdef __LONG_DOUBLE_IEEE128__
@@ -1449,14 +1922,14 @@ namespace __format
#elif defined _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128
// Format 128-bit floating-point types using long double.
- using __float128_t = long double;
-# define _GLIBCXX_FORMAT_F128 1
+ using __flt128_t = long double;
+# define _GLIBCXX_FORMAT_F128 2
#elif __FLT128_DIG__ && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
// Format 128-bit floating-point types using _Float128.
- using __float128_t = _Float128;
-# define _GLIBCXX_FORMAT_F128 2
+ using __flt128_t = _Float128;
+# define _GLIBCXX_FORMAT_F128 3
# if __cplusplus == 202002L
// These overloads exist in the library, but are not declared for C++20.
@@ -1925,9 +2398,16 @@ namespace __format
const size_t __r = __str.size() - __e; // Length of remainder.
auto __overwrite = [&](_CharT* __p, size_t) {
// Apply grouping to the digits before the radix or exponent.
- auto __end = std::__add_grouping(__p, __np.thousands_sep(),
+ int __off = 0;
+ if (auto __c = __str.front(); __c == '-' || __c == '+' || __c == ' ')
+ {
+ *__p = __c;
+ __off = 1;
+ }
+ auto __end = std::__add_grouping(__p + __off, __np.thousands_sep(),
__grp.data(), __grp.size(),
- __str.data(), __str.data() + __e);
+ __str.data() + __off,
+ __str.data() + __e);
if (__r) // If there's a fractional part or exponent
{
if (__d != __str.npos)
@@ -1950,6 +2430,150 @@ 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)
+ { _M_set_default(_Pres_p); }
+
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc, _Pres_type __type = _Pres_p)
+ {
+ __format::_Spec<_CharT> __spec{};
+ const auto __last = __pc.end();
+ auto __first = __pc.begin();
+
+ auto __finalize = [this, &__spec, __type] {
+ _M_spec = __spec;
+ _M_set_default(__type);
+ };
+
+ 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 (__finished())
+ return __first;
+
+ if (*__first == 'p')
+ {
+ __spec._M_type = _Pres_p;
+ _M_spec._M_alt = !_M_spec._M_alt;
+ ++__first;
+ }
+#if __glibcxx_format >= 202304L
+ else if (*__first == 'P')
+ {
+ __spec._M_type = _Pres_P;
+ _M_spec._M_alt = !_M_spec._M_alt;
+ ++__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:
+ [[__gnu__::__always_inline__]]
+ constexpr void
+ _M_set_default(_Pres_type __type)
+ {
+ if (_M_spec._M_type == _Pres_none && __type != _Pres_none)
+ {
+ _M_spec._M_type = __type;
+ _M_spec._M_alt = !_M_spec._M_alt;
+ }
+ }
+
+ __format::_Spec<_CharT> _M_spec{};
+ };
+
} // namespace __format
/// @endcond
@@ -1969,22 +2593,16 @@ namespace __format
typename basic_format_context<_Out, _CharT>::iterator
format(_CharT __u, basic_format_context<_Out, _CharT>& __fc) const
{
- if (_M_f._M_spec._M_type == __format::_Pres_none
- || _M_f._M_spec._M_type == __format::_Pres_c)
+ if (_M_f._M_spec._M_type == __format::_Pres_c)
return _M_f._M_format_character(__u, __fc);
- else if (_M_f._M_spec._M_type == __format::_Pres_esc)
- {
- // TODO
- return __fc.out();
- }
else
return _M_f.format(static_cast<make_unsigned_t<_CharT>>(__u), __fc);
}
-#if __cpp_lib_format_ranges
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
constexpr void
set_debug_format() noexcept
- { _M_f._M_spec._M_type = __format::_Pres_esc; }
+ { _M_f._M_spec._M_debug = true; }
#endif
private:
@@ -2008,22 +2626,16 @@ namespace __format
typename basic_format_context<_Out, wchar_t>::iterator
format(char __u, basic_format_context<_Out, wchar_t>& __fc) const
{
- if (_M_f._M_spec._M_type == __format::_Pres_none
- || _M_f._M_spec._M_type == __format::_Pres_c)
+ if (_M_f._M_spec._M_type == __format::_Pres_c)
return _M_f._M_format_character(__u, __fc);
- else if (_M_f._M_spec._M_type == __format::_Pres_esc)
- {
- // TODO
- return __fc.out();
- }
else
return _M_f.format(static_cast<unsigned char>(__u), __fc);
}
-#if __cpp_lib_format_ranges
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
constexpr void
set_debug_format() noexcept
- { _M_f._M_spec._M_type = __format::_Pres_esc; }
+ { _M_f._M_spec._M_debug = true; }
#endif
private:
@@ -2050,7 +2662,7 @@ namespace __format
format(_CharT* __u, basic_format_context<_Out, _CharT>& __fc) const
{ return _M_f.format(__u, __fc); }
-#if __cpp_lib_format_ranges
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
#endif
@@ -2075,7 +2687,7 @@ namespace __format
basic_format_context<_Out, _CharT>& __fc) const
{ return _M_f.format(__u, __fc); }
-#if __cpp_lib_format_ranges
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
#endif
@@ -2099,7 +2711,7 @@ namespace __format
basic_format_context<_Out, _CharT>& __fc) const
{ return _M_f.format({__u, _Nm}, __fc); }
-#if __cpp_lib_format_ranges
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
#endif
@@ -2123,7 +2735,7 @@ namespace __format
basic_format_context<_Out, char>& __fc) const
{ return _M_f.format(__u, __fc); }
-#if __cpp_lib_format_ranges
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
#endif
@@ -2148,7 +2760,7 @@ namespace __format
basic_format_context<_Out, wchar_t>& __fc) const
{ return _M_f.format(__u, __fc); }
-#if __cpp_lib_format_ranges
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
#endif
@@ -2173,7 +2785,7 @@ namespace __format
basic_format_context<_Out, char>& __fc) const
{ return _M_f.format(__u, __fc); }
-#if __cpp_lib_format_ranges
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
#endif
@@ -2198,7 +2810,7 @@ namespace __format
basic_format_context<_Out, wchar_t>& __fc) const
{ return _M_f.format(__u, __fc); }
-#if __cpp_lib_format_ranges
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
#endif
@@ -2364,8 +2976,8 @@ namespace __format
};
#endif
-#if defined(__FLT128_DIG__) && _GLIBCXX_FORMAT_F128 == 1
- // Reuse __formatter_fp<C>::format<__float128_t, Out> for _Float128.
+#if defined(__FLT128_DIG__) && _GLIBCXX_FORMAT_F128
+ // Use __formatter_fp<C>::format<__format::__flt128_t, Out> for _Float128.
template<__format::__char _CharT>
struct formatter<_Float128, _CharT>
{
@@ -2379,17 +2991,45 @@ namespace __format
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(_Float128 __u, basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f.format((__format::__float128_t)__u, __fc); }
+ { return _M_f.format((__format::__flt128_t)__u, __fc); }
private:
__format::__formatter_fp<_CharT> _M_f;
};
#endif
+#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128 > 1
+ // Reuse __formatter_fp<C>::format<__format::__flt128_t, Out> for __float128.
+ // This formatter is not declared if _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT is true,
+ // as __float128 when present is same type as __ieee128, which may be same as
+ // long double.
+ template<__format::__char _CharT>
+ struct formatter<__float128, _CharT>
+ {
+ formatter() = default;
+
+ [[__gnu__::__always_inline__]]
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ { return _M_f.parse(__pc); }
+
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(__float128 __u, basic_format_context<_Out, _CharT>& __fc) const
+ { return _M_f.format((__format::__flt128_t)__u, __fc); }
+
+ private:
+ __format::__formatter_fp<_CharT> _M_f;
+
+ static_assert( !is_same_v<__float128, long double>,
+ "This specialization should not be used for long double" );
+ };
+#endif
+
#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
// Reuse __formatter_fp<C>::format<float, Out> for bfloat16_t.
template<__format::__char _CharT>
- struct formatter<__gnu_cxx::__bfloat16_t, _CharT>
+ struct formatter<__format::__bflt16_t, _CharT>
{
formatter() = default;
@@ -2420,120 +3060,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>
@@ -2552,7 +3087,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>
@@ -2571,98 +3106,38 @@ namespace __format
{ return _M_f.format(nullptr, __fc); }
private:
- formatter<const void*, _CharT> _M_f;
+ __format::__formatter_ptr<_CharT> _M_f;
};
/// @}
-#if defined _GLIBCXX_USE_WCHAR_T && __cpp_lib_format_ranges
+#if defined _GLIBCXX_USE_WCHAR_T && __glibcxx_format_ranges
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3944. Formatters converting sequences of char to sequences of wchar_t
- namespace __format { struct __disabled; }
+ struct __formatter_disabled
+ {
+ __formatter_disabled() = delete; // Cannot format char sequence to wchar_t
+ __formatter_disabled(const __formatter_disabled&) = delete;
+ __formatter_disabled& operator=(const __formatter_disabled&) = delete;
+ };
- // std::formatter<__disabled, C> uses the primary template, which is disabled.
template<>
struct formatter<char*, wchar_t>
- : private formatter<__format::__disabled, wchar_t> { };
+ : private __formatter_disabled { };
template<>
struct formatter<const char*, wchar_t>
- : private formatter<__format::__disabled, wchar_t> { };
+ : private __formatter_disabled { };
template<size_t _Nm>
struct formatter<char[_Nm], wchar_t>
- : private formatter<__format::__disabled, wchar_t> { };
+ : private __formatter_disabled { };
template<class _Traits, class _Allocator>
struct formatter<basic_string<char, _Traits, _Allocator>, wchar_t>
- : private formatter<__format::__disabled, wchar_t> { };
+ : private __formatter_disabled { };
template<class _Traits>
struct formatter<basic_string_view<char, _Traits>, wchar_t>
- : 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>;
-
-} // namespace __format
-/// @endcond
-
-// Concept std::formattable was introduced by P2286R8 "Formatting Ranges",
-// but we can't guard it with __cpp_lib_format_ranges until we define that!
-#if __cplusplus > 202002L
- // [format.formattable], concept formattable
- template<typename _Tp, typename _CharT>
- concept formattable
- = __format::__formattable_impl<remove_reference_t<_Tp>, _CharT>;
+ : private __formatter_disabled { };
#endif
-#if __cpp_lib_format_ranges
- /// @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>;
-} // namespace __format
- /// @endcond
-#endif // format_ranges
-
/// An iterator after the last character written, and the number of
/// characters that would have been written.
template<typename _Out>
@@ -2730,6 +3205,10 @@ namespace __format
auto
_M_reserve(size_t __n) const
{ return _M_sink->_M_reserve(__n); }
+
+ bool
+ _M_discarding() const
+ { return _M_sink->_M_discarding(); }
};
// Abstract base class for type-erased character sinks.
@@ -2849,6 +3328,11 @@ namespace __format
_M_bump(size_t __n)
{ _M_next += __n; }
+ // Returns true if the _Sink is discarding incoming characters.
+ virtual bool
+ _M_discarding() const
+ { return false; }
+
public:
_Sink(const _Sink&) = delete;
_Sink& operator=(const _Sink&) = delete;
@@ -2859,12 +3343,38 @@ namespace __format
{ return _Sink_iter<_CharT>(*this); }
};
+
+ template<typename _CharT>
+ class _Fixedbuf_sink final : public _Sink<_CharT>
+ {
+ void
+ _M_overflow() override
+ {
+ __glibcxx_assert(false);
+ this->_M_rewind();
+ }
+
+ public:
+ [[__gnu__::__always_inline__]]
+ constexpr explicit
+ _Fixedbuf_sink(span<_CharT> __buf)
+ : _Sink<_CharT>(__buf)
+ { }
+
+ constexpr basic_string_view<_CharT>
+ view() const
+ {
+ auto __s = this->_M_used();
+ return basic_string_view<_CharT>(__s.data(), __s.size());
+ }
+ };
+
// A sink with an internal buffer. This is used to implement concrete sinks.
template<typename _CharT>
class _Buf_sink : public _Sink<_CharT>
{
protected:
- _CharT _M_buf[32 * sizeof(void*) / sizeof(_CharT)];
+ _CharT _M_buf[__stackbuf_size<_CharT>];
[[__gnu__::__always_inline__]]
constexpr
@@ -2878,12 +3388,12 @@ namespace __format
// A sink that fills a sequence (e.g. std::string, std::vector, std::deque).
// Writes to a buffer then appends that to the sequence when it fills up.
template<typename _Seq>
- class _Seq_sink final : public _Buf_sink<typename _Seq::value_type>
+ class _Seq_sink : public _Buf_sink<typename _Seq::value_type>
{
using _CharT = typename _Seq::value_type;
_Seq _M_seq;
-
+ protected:
// Transfer buffer contents to the sequence, so buffer can be refilled.
void
_M_overflow() override
@@ -2955,6 +3465,17 @@ namespace __format
}
}
+ void _M_trim(span<const _CharT> __s)
+ requires __is_specialization_of<_Seq, basic_string>
+ {
+ _GLIBCXX_DEBUG_ASSERT(__s.data() == this->_M_buf
+ || __s.data() == _M_seq.data());
+ if (__s.data() == _M_seq.data())
+ _M_seq.resize(__s.size());
+ else
+ this->_M_reset(this->_M_buf, __s.size());
+ }
+
public:
// TODO: for SSO string, use SSO buffer as initial span, then switch
// to _M_buf if it overflows? Or even do that for all unused capacity?
@@ -2980,7 +3501,7 @@ namespace __format
// A writable span that views everything written to the sink.
// Will be either a view over _M_seq or the used part of _M_buf.
span<_CharT>
- view()
+ _M_span()
{
auto __s = this->_M_used();
if (_M_seq.size())
@@ -2991,6 +3512,13 @@ namespace __format
}
return __s;
}
+
+ basic_string_view<_CharT>
+ view()
+ {
+ auto __span = _M_span();
+ return basic_string_view<_CharT>(__span.data(), __span.size());
+ }
};
template<typename _CharT, typename _Alloc = allocator<_CharT>>
@@ -2998,9 +3526,7 @@ namespace __format
= _Seq_sink<basic_string<_CharT, char_traits<_CharT>, _Alloc>>;
// template<typename _CharT, typename _Alloc = allocator<_CharT>>
- // using _Vec_sink = _Seq_sink<vector<_CharT, _Alloc>>;
-
- // A sink that writes to an output iterator.
+ // using _Vec_sink = _Seq_sink<vector<_CharTthis-> sink that writes to an output iterator.
// Writes to a fixed-size buffer and then flushes to the output iterator
// when the buffer fills up.
template<typename _CharT, typename _OutIter>
@@ -3032,6 +3558,14 @@ namespace __format
_M_count += __s.size();
}
+ bool
+ _M_discarding() const override
+ {
+ // format_to_n return total number of characters, that would be written,
+ // see C++20 [format.functions] p20
+ return false;
+ }
+
public:
[[__gnu__::__always_inline__]]
explicit
@@ -3094,6 +3628,14 @@ namespace __format
}
}
+ bool
+ _M_discarding() const override
+ {
+ // format_to_n return total number of characters, that would be written,
+ // see C++20 [format.functions] p20
+ return false;
+ }
+
typename _Sink<_CharT>::_Reservation
_M_reserve(size_t __n) final
{
@@ -3168,20 +3710,202 @@ namespace __format
}
};
- enum _Arg_t : unsigned char {
+ // A sink for handling the padded outputs (_M_padwidth) or truncated
+ // (_M_maxwidth). The handling is done by writting to buffer (_Str_strink)
+ // until sufficient number of characters is written. After that if sequence
+ // is longer than _M_padwidth it's written to _M_out, and further writes are
+ // either:
+ // * buffered and forwarded to _M_out, if below _M_maxwidth,
+ // * ignored otherwise
+ // If field width of written sequence is no greater than _M_padwidth, the
+ // sequence is written during _M_finish call.
+ template<typename _Out, typename _CharT>
+ class _Padding_sink : public _Str_sink<_CharT>
+ {
+ size_t _M_padwidth;
+ size_t _M_maxwidth;
+ _Out _M_out;
+ size_t _M_printwidth;
+
+ [[__gnu__::__always_inline__]]
+ bool
+ _M_ignoring() const
+ { return _M_printwidth >= _M_maxwidth; }
+
+ [[__gnu__::__always_inline__]]
+ bool
+ _M_buffering() const
+ {
+ if (_M_printwidth < _M_padwidth)
+ return true;
+ if (_M_maxwidth != (size_t)-1)
+ return _M_printwidth < _M_maxwidth;
+ return false;
+ }
+
+ void
+ _M_sync_discarding()
+ {
+ if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
+ if (_M_out._M_discarding())
+ _M_maxwidth = _M_printwidth;
+ }
+
+ void
+ _M_flush()
+ {
+ span<_CharT> __new = this->_M_used();
+ basic_string_view<_CharT> __str(__new.data(), __new.size());
+ _M_out = __format::__write(std::move(_M_out), __str);
+ _M_sync_discarding();
+ this->_M_rewind();
+ }
+
+ bool
+ _M_force_update()
+ {
+ auto __str = this->view();
+ // Compute actual field width, possibly truncated.
+ _M_printwidth = __format::__truncate(__str, _M_maxwidth);
+ if (_M_ignoring())
+ this->_M_trim(__str);
+ if (_M_buffering())
+ return true;
+
+ // We have more characters than padidng, no padding is needed,
+ // write direclty to _M_out.
+ if (_M_printwidth >= _M_padwidth)
+ {
+ _M_out = __format::__write(std::move(_M_out), __str);
+ _M_sync_discarding();
+ }
+ // We reached _M_maxwidth that is smaller than _M_padwidth.
+ // Store the prefix sequence in _M_seq, and free _M_buf.
+ else
+ _Str_sink<_CharT>::_M_overflow();
+
+ // Use internal buffer for writes to _M_out.
+ this->_M_reset(this->_M_buf);
+ return false;
+ }
+
+ bool
+ _M_update(size_t __new)
+ {
+ _M_printwidth += __new;
+ // Compute estimated width, to see if is not reduced.
+ if (_M_printwidth >= _M_padwidth || _M_printwidth >= _M_maxwidth)
+ return _M_force_update();
+ return true;
+ }
+
+ void
+ _M_overflow() override
+ {
+ // Ignore characters in buffer, and override it.
+ if (_M_ignoring())
+ this->_M_rewind();
+ // Write buffer to _M_out, and override it.
+ else if (!_M_buffering())
+ _M_flush();
+ // Update written count, and if input still should be buffered,
+ // flush the to _M_seq.
+ else if (_M_update(this->_M_used().size()))
+ _Str_sink<_CharT>::_M_overflow();
+ }
+
+ bool
+ _M_discarding() const override
+ { return _M_ignoring(); }
+
+ typename _Sink<_CharT>::_Reservation
+ _M_reserve(size_t __n) override
+ {
+ // Ignore characters in buffer, if any.
+ if (_M_ignoring())
+ this->_M_rewind();
+ else if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
+ if (!_M_buffering())
+ {
+ // Write pending characters if any
+ if (!this->_M_used().empty())
+ _M_flush();
+ // Try to reserve from _M_out sink.
+ if (auto __reserved = _M_out._M_reserve(__n))
+ return __reserved;
+ }
+ return _Sink<_CharT>::_M_reserve(__n);
+ }
+
+ void
+ _M_bump(size_t __n) override
+ {
+ // Ignore the written characters.
+ if (_M_ignoring())
+ return;
+ // If reservation was made directy sink associated _M_out,
+ // _M_bump will be called on that sink.
+ _Sink<_CharT>::_M_bump(__n);
+ if (_M_buffering())
+ _M_update(__n);
+ }
+
+ public:
+ [[__gnu__::__always_inline__]]
+ explicit
+ _Padding_sink(_Out __out, size_t __padwidth, size_t __maxwidth)
+ : _M_padwidth(__padwidth), _M_maxwidth(__maxwidth),
+ _M_out(std::move(__out)), _M_printwidth(0)
+ { _M_sync_discarding(); }
+
+ [[__gnu__::__always_inline__]]
+ explicit
+ _Padding_sink(_Out __out, size_t __padwidth)
+ : _Padding_sink(std::move(__out), __padwidth, (size_t)-1)
+ { }
+
+ _Out
+ _M_finish(_Align __align, char32_t __fill_char)
+ {
+ // Handle any characters in the buffer.
+ if (auto __rem = this->_M_used().size())
+ {
+ if (_M_ignoring())
+ this->_M_rewind();
+ else if (!_M_buffering())
+ _M_flush();
+ else
+ _M_update(__rem);
+ }
+
+ if (!_M_buffering() || !_M_force_update())
+ // Characters were already written to _M_out.
+ if (_M_printwidth >= _M_padwidth)
+ return std::move(_M_out);
+
+ const auto __str = this->view();
+ if (_M_printwidth >= _M_padwidth)
+ return __format::__write(std::move(_M_out), __str);
+
+ const size_t __nfill = _M_padwidth - _M_printwidth;
+ return __format::__write_padded(std::move(_M_out), __str,
+ __align, __nfill, __fill_char);
+ }
+ };
+
+ enum class _Arg_t : unsigned char {
_Arg_none, _Arg_bool, _Arg_c, _Arg_i, _Arg_u, _Arg_ll, _Arg_ull,
_Arg_flt, _Arg_dbl, _Arg_ldbl, _Arg_str, _Arg_sv, _Arg_ptr, _Arg_handle,
- _Arg_i128, _Arg_u128,
- _Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f64, // These are unused.
+ _Arg_i128, _Arg_u128, _Arg_float128,
+ _Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f64,
+ _Arg_max_,
+
#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
- _Arg_next_value_,
- _Arg_f128 = _Arg_ldbl,
- _Arg_ibm128 = _Arg_next_value_,
-#else
- _Arg_f128,
+ _Arg_ibm128 = _Arg_ldbl,
+ _Arg_ieee128 = _Arg_float128,
#endif
- _Arg_max_
};
+ using enum _Arg_t;
template<typename _Context>
struct _Arg_value
@@ -3207,6 +3931,12 @@ namespace __format
double _M_dbl;
#ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT // No long double if it's ambiguous.
long double _M_ldbl;
+#else
+ __ibm128 _M_ibm128;
+ __ieee128 _M_ieee128;
+#endif
+#ifdef __SIZEOF_FLOAT128__
+ __float128 _M_float128;
#endif
const _CharT* _M_str;
basic_string_view<_CharT> _M_sv;
@@ -3216,11 +3946,17 @@ namespace __format
__int128 _M_i128;
unsigned __int128 _M_u128;
#endif
-#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
- __ieee128 _M_f128;
- __ibm128 _M_ibm128;
-#elif _GLIBCXX_FORMAT_F128 == 2
- __float128_t _M_f128;
+#ifdef __BFLT16_DIG__
+ __bflt16_t _M_bf16;
+#endif
+#ifdef __FLT16_DIG__
+ _Float16 _M_f16;
+#endif
+#ifdef __FLT32_DIG__
+ _Float32 _M_f32;
+#endif
+#ifdef __FLT64_DIG__
+ _Float64 _M_f64;
#endif
};
@@ -3258,10 +3994,14 @@ namespace __format
else if constexpr (is_same_v<_Tp, long double>)
return __u._M_ldbl;
#else
- else if constexpr (is_same_v<_Tp, __ieee128>)
- return __u._M_f128;
else if constexpr (is_same_v<_Tp, __ibm128>)
return __u._M_ibm128;
+ else if constexpr (is_same_v<_Tp, __ieee128>)
+ return __u._M_ieee128;
+#endif
+#ifdef __SIZEOF_FLOAT128__
+ else if constexpr (is_same_v<_Tp, __float128>)
+ return __u._M_float128;
#endif
else if constexpr (is_same_v<_Tp, const _CharT*>)
return __u._M_str;
@@ -3275,9 +4015,21 @@ namespace __format
else if constexpr (is_same_v<_Tp, unsigned __int128>)
return __u._M_u128;
#endif
-#if _GLIBCXX_FORMAT_F128 == 2
- else if constexpr (is_same_v<_Tp, __float128_t>)
- return __u._M_f128;
+#ifdef __BFLT16_DIG__
+ else if constexpr (is_same_v<_Tp, __bflt16_t>)
+ return __u._M_bf16;
+#endif
+#ifdef __FLT16_DIG__
+ else if constexpr (is_same_v<_Tp, _Float16>)
+ return __u._M_f16;
+#endif
+#ifdef __FLT32_DIG__
+ else if constexpr (is_same_v<_Tp, _Float32>)
+ return __u._M_f32;
+#endif
+#ifdef __FLT64_DIG__
+ else if constexpr (is_same_v<_Tp, _Float64>)
+ return __u._M_f64;
#endif
else if constexpr (derived_from<_Tp, _HandleBase>)
return static_cast<_Tp&>(__u._M_handle);
@@ -3456,36 +4208,25 @@ namespace __format
else if constexpr (is_same_v<_Td, __ieee128>)
return type_identity<__ieee128>();
#endif
-
-#if defined(__FLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
- else if constexpr (is_same_v<_Td, _Float16>)
- return type_identity<float>();
+#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128
+ else if constexpr (is_same_v<_Td, __float128>)
+ return type_identity<__float128>();
#endif
-
-#if defined(__BFLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
- else if constexpr (is_same_v<_Td, decltype(0.0bf16)>)
- return type_identity<float>();
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ else if constexpr (is_same_v<_Td, __format::__bflt16_t>)
+ return type_identity<__format::__bflt16_t>();
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ else if constexpr (is_same_v<_Td, _Float16>)
+ return type_identity<_Float16>();
#endif
-
#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
else if constexpr (is_same_v<_Td, _Float32>)
- return type_identity<float>();
+ return type_identity<_Float32>();
#endif
-
#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
else if constexpr (is_same_v<_Td, _Float64>)
- return type_identity<double>();
-#endif
-
-#if _GLIBCXX_FORMAT_F128
-# if __FLT128_DIG__
- else if constexpr (is_same_v<_Td, _Float128>)
- return type_identity<__format::__float128_t>();
-# endif
-# if __SIZEOF_FLOAT128__
- else if constexpr (is_same_v<_Td, __float128>)
- return type_identity<__format::__float128_t>();
-# endif
+ return type_identity<_Float64>();
#endif
else if constexpr (__is_specialization_of<_Td, basic_string_view>
|| __is_specialization_of<_Td, basic_string>)
@@ -3541,7 +4282,27 @@ namespace __format
else if constexpr (is_same_v<_Tp, __ibm128>)
return _Arg_ibm128;
else if constexpr (is_same_v<_Tp, __ieee128>)
- return _Arg_f128;
+ return _Arg_ieee128;
+#endif
+#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128
+ else if constexpr (is_same_v<_Tp, __float128>)
+ return _Arg_float128;
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ else if constexpr (is_same_v<_Tp, __format::__bflt16_t>)
+ return _Arg_bf16;
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ else if constexpr (is_same_v<_Tp, _Float16>)
+ return _Arg_f16;
+#endif
+#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ else if constexpr (is_same_v<_Tp, _Float32>)
+ return _Arg_f32;
+#endif
+#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+ else if constexpr (is_same_v<_Tp, _Float64>)
+ return _Arg_f64;
#endif
else if constexpr (is_same_v<_Tp, const _CharT*>)
return _Arg_str;
@@ -3555,11 +4316,6 @@ namespace __format
else if constexpr (is_same_v<_Tp, unsigned __int128>)
return _Arg_u128;
#endif
-
-#if _GLIBCXX_FORMAT_F128 == 2
- else if constexpr (is_same_v<_Tp, __format::__float128_t>)
- return _Arg_f128;
-#endif
else if constexpr (is_same_v<_Tp, handle>)
return _Arg_handle;
}
@@ -3632,13 +4388,33 @@ namespace __format
#ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
case _Arg_ldbl:
return std::forward<_Visitor>(__vis)(_M_val._M_ldbl);
+#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128
+ case _Arg_float128:
+ return std::forward<_Visitor>(__vis)(_M_val._M_float128);
+#endif
#else
- case _Arg_f128:
- return std::forward<_Visitor>(__vis)(_M_val._M_f128);
case _Arg_ibm128:
return std::forward<_Visitor>(__vis)(_M_val._M_ibm128);
+ case _Arg_ieee128:
+ return std::forward<_Visitor>(__vis)(_M_val._M_ieee128);
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ case _Arg_bf16:
+ return std::forward<_Visitor>(__vis)(_M_val._M_bf16);
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ case _Arg_f16:
+ return std::forward<_Visitor>(__vis)(_M_val._M_f16);
+#endif
+#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ case _Arg_f32:
+ return std::forward<_Visitor>(__vis)(_M_val._M_f32);
#endif
+#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+ case _Arg_f64:
+ return std::forward<_Visitor>(__vis)(_M_val._M_f64);
#endif
+#endif // __glibcxx_to_chars
case _Arg_str:
return std::forward<_Visitor>(__vis)(_M_val._M_str);
case _Arg_sv:
@@ -3656,14 +4432,7 @@ namespace __format
case _Arg_u128:
return std::forward<_Visitor>(__vis)(_M_val._M_u128);
#endif
-
-#if _GLIBCXX_FORMAT_F128 == 2
- case _Arg_f128:
- return std::forward<_Visitor>(__vis)(_M_val._M_f128);
-#endif
-
default:
- // _Arg_f16 etc.
__builtin_unreachable();
}
}
@@ -3675,17 +4444,17 @@ namespace __format
return _M_visit([&__vis]<typename _Tp>(_Tp& __val) -> decltype(auto)
{
constexpr bool __user_facing = __is_one_of<_Tp,
- monostate, bool, _CharT,
- int, unsigned int, long long int, unsigned long long int,
- float, double, long double,
- const _CharT*, basic_string_view<_CharT>,
- const void*, handle>::value;
+ monostate, bool, _CharT,
+ int, unsigned int, long long int, unsigned long long int,
+ float, double, long double,
+ const _CharT*, basic_string_view<_CharT>,
+ const void*, handle>::value;
if constexpr (__user_facing)
return std::forward<_Visitor>(__vis)(__val);
else
{
- handle __h(__val);
- return std::forward<_Visitor>(__vis)(__h);
+ handle __h(__val);
+ return std::forward<_Visitor>(__vis)(__h);
}
}, __type);
}
@@ -3749,7 +4518,7 @@ namespace __format
{
__UINT64_TYPE__ __packed_types = 0;
for (auto __i = __types.rbegin(); __i != __types.rend(); ++__i)
- __packed_types = (__packed_types << _Bits) | *__i;
+ __packed_types = (__packed_types << _Bits) | (unsigned)*__i;
return __packed_types;
}
} // namespace __format
@@ -3762,7 +4531,7 @@ namespace __format
static constexpr int _S_packed_type_mask = 0b11111;
static constexpr int _S_max_packed_args = 12;
- static_assert( __format::_Arg_max_ <= (1 << _S_packed_type_bits) );
+ static_assert( (unsigned)__format::_Arg_max_ <= (1u << _S_packed_type_bits) );
template<typename... _Args>
using _Store = __format::_Arg_store<_Context, _Args...>;
@@ -4713,22 +5482,8 @@ namespace __format
}
#endif
-#if __cpp_lib_format_ranges
- // [format.range], formatting of ranges
- // [format.range.fmtkind], variable template format_kind
- enum class range_format {
- disabled,
- map,
- set,
- sequence,
- string,
- debug_string
- };
-
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
/// @cond undocumented
- template<typename _Rg>
- constexpr auto format_kind = not defined(format_kind<_Rg>);
-
template<typename _Tp>
consteval range_format
__fmt_kind()
@@ -4758,29 +5513,570 @@ namespace __format
template<ranges::input_range _Rg> requires same_as<_Rg, remove_cvref_t<_Rg>>
constexpr range_format format_kind<_Rg> = __fmt_kind<_Rg>();
- // [format.range.formatter], class template range_formatter
- template<typename _Tp, typename _CharT = char>
- requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT>
- class range_formatter; // TODO
-
/// @cond undocumented
namespace __format
{
- // [format.range.fmtdef], class template range-default-formatter
- template<range_format _Kind, ranges::input_range _Rg, typename _CharT>
- struct __range_default_formatter; // TODO
+ template<typename _CharT, typename _Out, typename _Callback>
+ typename basic_format_context<_Out, _CharT>::iterator
+ __format_padded(basic_format_context<_Out, _CharT>& __fc,
+ const _Spec<_CharT>& __spec,
+ _Callback&& __call)
+ {
+ // This is required to implement formatting with padding,
+ // as we need to format to temporary buffer, using the same iterator.
+ static_assert(is_same_v<_Out, __format::_Sink_iter<_CharT>>);
+
+ const size_t __padwidth = __spec._M_get_width(__fc);
+ if (__padwidth == 0)
+ return __call(__fc);
+
+ struct _Restore_out
+ {
+ _Restore_out(basic_format_context<_Sink_iter<_CharT>, _CharT>& __fc)
+ : _M_ctx(std::addressof(__fc)), _M_out(__fc.out())
+ { }
+
+ void
+ _M_disarm()
+ { _M_ctx = nullptr; }
+
+ ~_Restore_out()
+ {
+ if (_M_ctx)
+ _M_ctx->advance_to(_M_out);
+ }
+
+ private:
+ basic_format_context<_Sink_iter<_CharT>, _CharT>* _M_ctx;
+ _Sink_iter<_CharT> _M_out;
+ };
+
+ _Restore_out __restore(__fc);
+ _Padding_sink<_Sink_iter<_CharT>, _CharT> __sink(__fc.out(), __padwidth);
+ __fc.advance_to(__sink.out());
+ __call(__fc);
+ __fc.advance_to(__sink._M_finish(__spec._M_align, __spec._M_fill));
+ __restore._M_disarm();
+ return __fc.out();
+ }
+
+ template<size_t _Pos, typename _Tp, typename _CharT>
+ struct __indexed_formatter_storage
+ {
+ constexpr void
+ _M_parse()
+ {
+ basic_format_parse_context<_CharT> __pc({});
+ if (_M_formatter.parse(__pc) != __pc.end())
+ __format::__failed_to_parse_format_spec();
+ }
+
+ template<typename _Out>
+ void
+ _M_format(__maybe_const<_Tp, _CharT>& __elem,
+ basic_format_context<_Out, _CharT>& __fc,
+ basic_string_view<_CharT> __sep) const
+ {
+ if constexpr (_Pos != 0)
+ __fc.advance_to(__format::__write(__fc.out(), __sep));
+ __fc.advance_to(_M_formatter.format(__elem, __fc));
+ }
+
+ [[__gnu__::__always_inline__]]
+ constexpr void
+ set_debug_format()
+ {
+ if constexpr (__has_debug_format<formatter<_Tp, _CharT>>)
+ _M_formatter.set_debug_format();
+ }
+
+ private:
+ formatter<_Tp, _CharT> _M_formatter;
+ };
+
+ template<typename _CharT, typename... _Tps>
+ class __tuple_formatter
+ {
+ using _String_view = basic_string_view<_CharT>;
+ using _Seps = __format::_Separators<_CharT>;
+
+ public:
+ constexpr void
+ set_separator(basic_string_view<_CharT> __sep) noexcept
+ { _M_sep = __sep; }
+
+ constexpr void
+ set_brackets(basic_string_view<_CharT> __open,
+ basic_string_view<_CharT> __close) noexcept
+ {
+ _M_open = __open;
+ _M_close = __close;
+ }
+
+ // We deviate from standard, that declares this as template accepting
+ // unconstrained ParseContext type, which seems unimplementable.
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ {
+ auto __first = __pc.begin();
+ const auto __last = __pc.end();
+ __format::_Spec<_CharT> __spec{};
+
+ auto __finished = [&]
+ {
+ if (__first != __last && *__first != '}')
+ return false;
+
+ _M_spec = __spec;
+ _M_felems._M_parse();
+ _M_felems.set_debug_format();
+ return true;
+ };
+
+ if (__finished())
+ return __first;
+
+ __first = __spec._M_parse_fill_and_align(__first, __last, "{:");
+ if (__finished())
+ return __first;
+
+ __first = __spec._M_parse_width(__first, __last, __pc);
+ if (__finished())
+ return __first;
+
+ if (*__first == 'n')
+ {
+ ++__first;
+ _M_open = _M_close = _String_view();
+ }
+ else if (*__first == 'm')
+ {
+ ++__first;
+ if constexpr (sizeof...(_Tps) == 2)
+ {
+ _M_sep = _Seps::_S_colon();
+ _M_open = _M_close = _String_view();
+ }
+ else
+ __throw_format_error("format error: 'm' specifier requires range"
+ " of pair or tuple of two elements");
+ }
+
+ if (__finished())
+ return __first;
+
+ __format::__failed_to_parse_format_spec();
+ }
+
+ protected:
+ template<typename _Tuple, typename _Out, size_t... _Ids>
+ typename basic_format_context<_Out, _CharT>::iterator
+ _M_format(_Tuple& __tuple, index_sequence<_Ids...>,
+ basic_format_context<_Out, _CharT>& __fc) const
+ { return _M_format_elems(std::get<_Ids>(__tuple)..., __fc); }
+
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ _M_format_elems(__maybe_const<_Tps, _CharT>&... __elems,
+ basic_format_context<_Out, _CharT>& __fc) const
+ {
+ return __format::__format_padded(
+ __fc, _M_spec,
+ [this, &__elems...](basic_format_context<_Out, _CharT>& __nfc)
+ {
+ __nfc.advance_to(__format::__write(__nfc.out(), _M_open));
+ _M_felems._M_format(__elems..., __nfc, _M_sep);
+ return __format::__write(__nfc.out(), _M_close);
+ });
+ }
+
+ private:
+ template<size_t... _Ids>
+ struct __formatters_storage
+ : __indexed_formatter_storage<_Ids, _Tps, _CharT>...
+ {
+ template<size_t _Id, typename _Up>
+ using _Base = __indexed_formatter_storage<_Id, _Up, _CharT>;
+
+ constexpr void
+ _M_parse()
+ {
+ (_Base<_Ids, _Tps>::_M_parse(), ...);
+ }
+
+ template<typename _Out>
+ void
+ _M_format(__maybe_const<_Tps, _CharT>&... __elems,
+ basic_format_context<_Out, _CharT>& __fc,
+ _String_view __sep) const
+ {
+ (_Base<_Ids, _Tps>::_M_format(__elems, __fc, __sep), ...);
+ }
+
+ constexpr void
+ set_debug_format()
+ {
+ (_Base<_Ids, _Tps>::set_debug_format(), ...);
+ }
+ };
+
+ template<size_t... _Ids>
+ static auto
+ _S_create_storage(index_sequence<_Ids...>)
+ -> __formatters_storage<_Ids...>;
+ using _Formatters
+ = decltype(_S_create_storage(index_sequence_for<_Tps...>()));
+
+ _Spec<_CharT> _M_spec{};
+ _String_view _M_open = _Seps::_S_parens().substr(0, 1);
+ _String_view _M_close = _Seps::_S_parens().substr(1, 1);
+ _String_view _M_sep = _Seps::_S_comma();
+ _Formatters _M_felems;
+ };
+
+ template<typename _Tp>
+ concept __is_map_formattable
+ = __is_pair<_Tp> || (__is_tuple_v<_Tp> && tuple_size_v<_Tp> == 2);
+
} // namespace __format
/// @endcond
+ // [format.tuple] Tuple formatter
+ template<__format::__char _CharT, formattable<_CharT> _Fp,
+ formattable<_CharT> _Sp>
+ struct formatter<pair<_Fp, _Sp>, _CharT>
+ : __format::__tuple_formatter<_CharT, remove_cvref_t<_Fp>,
+ remove_cvref_t<_Sp>>
+ {
+ private:
+ using __maybe_const_pair
+ = __conditional_t<formattable<const _Fp, _CharT>
+ && formattable<const _Sp, _CharT>,
+ const pair<_Fp, _Sp>, pair<_Fp, _Sp>>;
+ public:
+ // We deviate from standard, that declares this as template accepting
+ // unconstrained FormatContext type, which seems unimplementable.
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(__maybe_const_pair& __p,
+ basic_format_context<_Out, _CharT>& __fc) const
+ { return this->_M_format_elems(__p.first, __p.second, __fc); }
+ };
+
+ template<__format::__char _CharT, formattable<_CharT>... _Tps>
+ struct formatter<tuple<_Tps...>, _CharT>
+ : __format::__tuple_formatter<_CharT, remove_cvref_t<_Tps>...>
+ {
+ private:
+ using __maybe_const_tuple
+ = __conditional_t<(formattable<const _Tps, _CharT> && ...),
+ const tuple<_Tps...>, tuple<_Tps...>>;
+ public:
+ // We deviate from standard, that declares this as template accepting
+ // unconstrained FormatContext type, which seems unimplementable.
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(__maybe_const_tuple& __t,
+ basic_format_context<_Out, _CharT>& __fc) const
+ { return this->_M_format(__t, index_sequence_for<_Tps...>(), __fc); }
+ };
+
+ // [format.range.formatter], class template range_formatter
+ template<typename _Tp, __format::__char _CharT>
+ requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT>
+ class range_formatter
+ {
+ using _String_view = basic_string_view<_CharT>;
+ using _Seps = __format::_Separators<_CharT>;
+
+ public:
+ constexpr void
+ set_separator(basic_string_view<_CharT> __sep) noexcept
+ { _M_sep = __sep; }
+
+ constexpr void
+ set_brackets(basic_string_view<_CharT> __open,
+ basic_string_view<_CharT> __close) noexcept
+ {
+ _M_open = __open;
+ _M_close = __close;
+ }
+
+ constexpr formatter<_Tp, _CharT>&
+ underlying() noexcept
+ { return _M_fval; }
+
+ constexpr const formatter<_Tp, _CharT>&
+ underlying() const noexcept
+ { return _M_fval; }
+
+ // We deviate from standard, that declares this as template accepting
+ // unconstrained ParseContext type, which seems unimplementable.
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ {
+ auto __first = __pc.begin();
+ const auto __last = __pc.end();
+ __format::_Spec<_CharT> __spec{};
+ bool __no_brace = false;
+
+ auto __finished = [&]
+ { return __first == __last || *__first == '}'; };
+
+ auto __finalize = [&]
+ {
+ _M_spec = __spec;
+ return __first;
+ };
+
+ auto __parse_val = [&](_String_view __nfs = _String_view())
+ {
+ basic_format_parse_context<_CharT> __npc(__nfs);
+ if (_M_fval.parse(__npc) != __npc.end())
+ __format::__failed_to_parse_format_spec();
+ if constexpr (__format::__has_debug_format<formatter<_Tp, _CharT>>)
+ _M_fval.set_debug_format();
+ return __finalize();
+ };
+
+ if (__finished())
+ return __parse_val();
+
+ __first = __spec._M_parse_fill_and_align(__first, __last, "{:");
+ if (__finished())
+ return __parse_val();
+
+ __first = __spec._M_parse_width(__first, __last, __pc);
+ if (__finished())
+ return __parse_val();
+
+ if (*__first == '?')
+ {
+ ++__first;
+ __spec._M_debug = true;
+ if (__finished() || *__first != 's')
+ __throw_format_error("format error: '?' is allowed only in"
+ " combination with 's'");
+ }
+
+ if (*__first == 's')
+ {
+ ++__first;
+ if constexpr (same_as<_Tp, _CharT>)
+ {
+ __spec._M_type = __format::_Pres_s;
+ if (__finished())
+ return __finalize();
+ __throw_format_error("format error: element format specifier"
+ " cannot be provided when 's' specifier is used");
+ }
+ else
+ __throw_format_error("format error: 's' specifier requires"
+ " range of character types");
+ }
+
+ if (__finished())
+ return __parse_val();
+
+ if (*__first == 'n')
+ {
+ ++__first;
+ _M_open = _M_close = _String_view();
+ __no_brace = true;
+ }
+
+ if (__finished())
+ return __parse_val();
+
+ if (*__first == 'm')
+ {
+ _String_view __m(__first, 1);
+ ++__first;
+ if constexpr (__format::__is_map_formattable<_Tp>)
+ {
+ _M_sep = _Seps::_S_comma();
+ if (!__no_brace)
+ {
+ _M_open = _Seps::_S_braces().substr(0, 1);
+ _M_close = _Seps::_S_braces().substr(1, 1);
+ }
+ if (__finished())
+ return __parse_val(__m);
+ __throw_format_error("format error: element format specifier"
+ " cannot be provided when 'm' specifier is used");
+ }
+ else
+ __throw_format_error("format error: 'm' specifier requires"
+ " range of pairs or tuples of two elements");
+ }
+
+ if (__finished())
+ return __parse_val();
+
+ if (*__first == ':')
+ {
+ __pc.advance_to(++__first);
+ __first = _M_fval.parse(__pc);
+ }
+
+ if (__finished())
+ return __finalize();
+
+ __format::__failed_to_parse_format_spec();
+ }
+
+ // We deviate from standard, that declares this as template accepting
+ // unconstrained FormatContext type, which seems unimplementable.
+ template<ranges::input_range _Rg, typename _Out>
+ requires formattable<ranges::range_reference_t<_Rg>, _CharT> &&
+ same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, _Tp>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const
+ {
+ using _Range = remove_reference_t<_Rg>;
+ if constexpr (__format::__simply_formattable_range<_Range, _CharT>)
+ return _M_format<const _Range>(__rg, __fc);
+ else
+ return _M_format(__rg, __fc);
+ }
+
+ private:
+ template<ranges::input_range _Rg, typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ _M_format(_Rg& __rg, basic_format_context<_Out, _CharT>& __fc) const
+ {
+ if constexpr (same_as<_Tp, _CharT>)
+ if (_M_spec._M_type == __format::_Pres_s)
+ {
+ __format::__formatter_str __fstr(_M_spec);
+ return __fstr._M_format_range(__rg, __fc);
+ }
+ return __format::__format_padded(
+ __fc, _M_spec,
+ [this, &__rg](basic_format_context<_Out, _CharT>& __nfc)
+ { return _M_format_elems(__rg, __nfc); });
+ }
+
+
+ template<ranges::input_range _Rg, typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ _M_format_elems(_Rg& __rg,
+ basic_format_context<_Out, _CharT>& __fc) const
+ {
+ auto __out = __format::__write(__fc.out(), _M_open);
+
+ auto __first = ranges::begin(__rg);
+ auto const __last = ranges::end(__rg);
+ if (__first == __last)
+ return __format::__write(__out, _M_close);
+
+ __fc.advance_to(__out);
+ __out = _M_fval.format(*__first, __fc);
+ for (++__first; __first != __last; ++__first)
+ {
+ __out = __format::__write(__out, _M_sep);
+ __fc.advance_to(__out);
+ __out = _M_fval.format(*__first, __fc);
+ }
+
+ return __format::__write(__out, _M_close);
+ }
+
+ __format::_Spec<_CharT> _M_spec{};
+ _String_view _M_open = _Seps::_S_squares().substr(0, 1);
+ _String_view _M_close = _Seps::_S_squares().substr(1, 1);
+ _String_view _M_sep = _Seps::_S_comma();
+ formatter<_Tp, _CharT> _M_fval;
+ };
+
+ // In standard this is shown as inheriting from specialization of
+ // exposition only specialization for range-default-formatter for
+ // each range_format. We opt for simpler implementation.
// [format.range.fmtmap], [format.range.fmtset], [format.range.fmtstr],
// specializations for maps, sets, and strings
- template<ranges::input_range _Rg, typename _CharT>
+ template<ranges::input_range _Rg, __format::__char _CharT>
requires (format_kind<_Rg> != range_format::disabled)
&& formattable<ranges::range_reference_t<_Rg>, _CharT>
struct formatter<_Rg, _CharT>
- : __format::__range_default_formatter<format_kind<_Rg>, _Rg, _CharT>
- { };
+ {
+ private:
+ static const bool _S_range_format_is_string =
+ (format_kind<_Rg> == range_format::string)
+ || (format_kind<_Rg> == range_format::debug_string);
+ using _Vt = remove_cvref_t<
+ ranges::range_reference_t<
+ __format::__maybe_const_range<_Rg, _CharT>>>;
+
+ static consteval bool _S_is_correct()
+ {
+ if constexpr (_S_range_format_is_string)
+ static_assert(same_as<_Vt, _CharT>);
+ return true;
+ }
+
+ static_assert(_S_is_correct());
+
+ public:
+ constexpr formatter() noexcept
+ {
+ using _Seps = __format::_Separators<_CharT>;
+ if constexpr (format_kind<_Rg> == range_format::map)
+ {
+ static_assert(__format::__is_map_formattable<_Vt>);
+ _M_under.set_brackets(_Seps::_S_braces().substr(0, 1),
+ _Seps::_S_braces().substr(1, 1));
+ _M_under.underlying().set_brackets({}, {});
+ _M_under.underlying().set_separator(_Seps::_S_colon());
+ }
+ else if constexpr (format_kind<_Rg> == range_format::set)
+ _M_under.set_brackets(_Seps::_S_braces().substr(0, 1),
+ _Seps::_S_braces().substr(1, 1));
+ }
+
+ constexpr void
+ set_separator(basic_string_view<_CharT> __sep) noexcept
+ requires (!_S_range_format_is_string)
+ { _M_under.set_separator(__sep); }
+
+ constexpr void
+ set_brackets(basic_string_view<_CharT> __open,
+ basic_string_view<_CharT> __close) noexcept
+ requires (!_S_range_format_is_string)
+ { _M_under.set_brackets(__open, __close); }
+
+ // We deviate from standard, that declares this as template accepting
+ // unconstrained ParseContext type, which seems unimplementable.
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ {
+ auto __res = _M_under.parse(__pc);
+ if constexpr (format_kind<_Rg> == range_format::debug_string)
+ _M_under.set_debug_format();
+ return __res;
+ }
+
+ // We deviate from standard, that declares this as template accepting
+ // unconstrained FormatContext type, which seems unimplementable.
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(__format::__maybe_const_range<_Rg, _CharT>& __rg,
+ basic_format_context<_Out, _CharT>& __fc) const
+ {
+ if constexpr (_S_range_format_is_string)
+ return _M_under._M_format_range(__rg, __fc);
+ else
+ return _M_under.format(__rg, __fc);
+ }
+
+ private:
+ using _Formatter_under
+ = __conditional_t<_S_range_format_is_string,
+ __format::__formatter_str<_CharT>,
+ range_formatter<_Vt, _CharT>>;
+ _Formatter_under _M_under;
+ };
#endif // C++23 formatting ranges
+#undef _GLIBCXX_WIDEN
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/std/forward_list b/libstdc++-v3/include/std/forward_list
index 166fdb0..d478851 100644
--- a/libstdc++-v3/include/std/forward_list
+++ b/libstdc++-v3/include/std/forward_list
@@ -49,6 +49,7 @@
#define __glibcxx_want_algorithm_default_value_type
#define __glibcxx_want_allocator_traits_is_always_equal
+#define __glibcxx_want_containers_ranges
#define __glibcxx_want_erase_if
#define __glibcxx_want_incomplete_container_elements
#define __glibcxx_want_list_remove_return_type
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 1077e96..307bcb9 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -52,6 +52,21 @@
#if __cplusplus >= 201103L
+#define __glibcxx_want_boyer_moore_searcher
+#define __glibcxx_want_bind_front
+#define __glibcxx_want_bind_back
+#define __glibcxx_want_constexpr_functional
+#define __glibcxx_want_copyable_function
+#define __glibcxx_want_function_ref
+#define __glibcxx_want_invoke
+#define __glibcxx_want_invoke_r
+#define __glibcxx_want_move_only_function
+#define __glibcxx_want_not_fn
+#define __glibcxx_want_ranges
+#define __glibcxx_want_reference_wrapper
+#define __glibcxx_want_transparent_operators
+#include <bits/version.h>
+
#include <tuple>
#include <type_traits>
#include <bits/functional_hash.h>
@@ -72,23 +87,10 @@
# include <bits/ranges_cmp.h> // std::identity, ranges::equal_to etc.
# include <compare>
#endif
-#if __cplusplus > 202002L && _GLIBCXX_HOSTED
-# include <bits/move_only_function.h>
+#if __glibcxx_move_only_function || __glibcxx_copyable_function || __glibcxx_function_ref
+# include <bits/funcwrap.h>
#endif
-#define __glibcxx_want_boyer_moore_searcher
-#define __glibcxx_want_bind_front
-#define __glibcxx_want_bind_back
-#define __glibcxx_want_constexpr_functional
-#define __glibcxx_want_invoke
-#define __glibcxx_want_invoke_r
-#define __glibcxx_want_move_only_function
-#define __glibcxx_want_not_fn
-#define __glibcxx_want_ranges
-#define __glibcxx_want_reference_wrapper
-#define __glibcxx_want_transparent_operators
-#include <bits/version.h>
-
#endif // C++11
namespace std _GLIBCXX_VISIBILITY(default)
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/generator b/libstdc++-v3/include/std/generator
index 3f781f1..7ab2c9e 100644
--- a/libstdc++-v3/include/std/generator
+++ b/libstdc++-v3/include/std/generator
@@ -153,6 +153,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept
{ return _Recursive_awaiter { std::move(__r.range) }; }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3899. co_yielding elements of an lvalue generator is
+ // unnecessarily inefficient
+ template<typename _R2, typename _V2, typename _A2, typename _U2>
+ requires std::same_as<_Yield2_t<_R2, _V2>, _Yielded>
+ auto
+ yield_value(ranges::elements_of<generator<_R2, _V2, _A2>&, _U2> __r)
+ noexcept
+ { return _Recursive_awaiter { std::move(__r.range) }; }
+
template<ranges::input_range _R, typename _Alloc>
requires convertible_to<ranges::range_reference_t<_R>, _Yielded>
auto
diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch
index cf64854..9504df0 100644
--- a/libstdc++-v3/include/std/latch
+++ b/libstdc++-v3/include/std/latch
@@ -62,7 +62,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr explicit
latch(ptrdiff_t __expected) noexcept
- : _M_a(__expected)
+ : _M_counter(__expected)
{ __glibcxx_assert(__expected >= 0 && __expected <= max()); }
~latch() = default;
@@ -74,35 +74,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
count_down(ptrdiff_t __update = 1)
{
__glibcxx_assert(__update >= 0 && __update <= max());
- auto const __old = __atomic_impl::fetch_sub(&_M_a, __update,
+ auto const __old = __atomic_impl::fetch_sub(&_M_counter, __update,
memory_order::release);
if (std::cmp_equal(__old, __update))
- __atomic_impl::notify_all(&_M_a);
+ __atomic_impl::notify_all(&_M_counter);
else
__glibcxx_assert(std::cmp_less(__update, __old));
}
_GLIBCXX_ALWAYS_INLINE bool
try_wait() const noexcept
- { return __atomic_impl::load(&_M_a, memory_order::acquire) == 0; }
+ { return __atomic_impl::load(&_M_counter, memory_order::acquire) == 0; }
_GLIBCXX_ALWAYS_INLINE void
wait() const noexcept
{
- auto const __pred = [this] { return this->try_wait(); };
- std::__atomic_wait_address(&_M_a, __pred);
+ auto const __vfn = [this] {
+ return __atomic_impl::load(&_M_counter, memory_order::acquire);
+ };
+ auto const __pred = [](__detail::__platform_wait_t __v) {
+ return __v == 0;
+ };
+ std::__atomic_wait_address(&_M_counter, __pred, __vfn);
}
_GLIBCXX_ALWAYS_INLINE void
arrive_and_wait(ptrdiff_t __update = 1) noexcept
{
- count_down(__update);
- wait();
+ // The standard specifies this functions as count_down(update); wait();
+ // but we combine those two calls into one and avoid the wait() if we
+ // know the counter reached zero.
+
+ __glibcxx_assert(__update >= 0 && __update <= max());
+ // Use acq_rel here because an omitted wait() would have used acquire:
+ auto const __old = __atomic_impl::fetch_sub(&_M_counter, __update,
+ memory_order::acq_rel);
+ if (std::cmp_equal(__old, __update))
+ __atomic_impl::notify_all(&_M_counter);
+ else
+ {
+ __glibcxx_assert(std::cmp_less(__update, __old));
+ wait();
+ }
}
private:
alignas(__detail::__platform_wait_alignment)
- __detail::__platform_wait_t _M_a;
+ __detail::__platform_wait_t _M_counter;
};
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/std/list b/libstdc++-v3/include/std/list
index 170499d..2ba0599 100644
--- a/libstdc++-v3/include/std/list
+++ b/libstdc++-v3/include/std/list
@@ -73,6 +73,7 @@
#define __glibcxx_want_algorithm_default_value_type
#define __glibcxx_want_allocator_traits_is_always_equal
+#define __glibcxx_want_containers_ranges
#define __glibcxx_want_erase_if
#define __glibcxx_want_incomplete_container_elements
#define __glibcxx_want_list_remove_return_type
diff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map
index 16a397f..6bfb538 100644
--- a/libstdc++-v3/include/std/map
+++ b/libstdc++-v3/include/std/map
@@ -72,6 +72,7 @@
#endif
#define __glibcxx_want_allocator_traits_is_always_equal
+#define __glibcxx_want_containers_ranges
#define __glibcxx_want_erase_if
#define __glibcxx_want_generic_associative_lookup
#define __glibcxx_want_map_try_emplace
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
new file mode 100644
index 0000000..c72a640
--- /dev/null
+++ b/libstdc++-v3/include/std/mdspan
@@ -0,0 +1,1041 @@
+// <mdspan> -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file mdspan
+ * This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_MDSPAN
+#define _GLIBCXX_MDSPAN 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <span>
+#include <array>
+#include <type_traits>
+#include <limits>
+#include <utility>
+
+#define __glibcxx_want_mdspan
+#include <bits/version.h>
+
+#ifdef __glibcxx_mdspan
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ namespace __mdspan
+ {
+ template<typename _IndexType, array _Extents>
+ class _ExtentsStorage
+ {
+ public:
+ static consteval bool
+ _S_is_dyn(size_t __ext) noexcept
+ { return __ext == dynamic_extent; }
+
+ template<typename _OIndexType>
+ static constexpr _IndexType
+ _S_int_cast(const _OIndexType& __other) noexcept
+ { return _IndexType(__other); }
+
+ static constexpr size_t _S_rank = _Extents.size();
+
+ // For __r in [0, _S_rank], _S_dynamic_index[__r] is the number
+ // of dynamic extents up to (and not including) __r.
+ //
+ // If __r is the index of a dynamic extent, then
+ // _S_dynamic_index[__r] is the index of that extent in
+ // _M_dyn_exts.
+ static constexpr auto _S_dynamic_index = [] consteval
+ {
+ array<size_t, _S_rank+1> __ret;
+ size_t __dyn = 0;
+ for (size_t __i = 0; __i < _S_rank; ++__i)
+ {
+ __ret[__i] = __dyn;
+ __dyn += _S_is_dyn(_Extents[__i]);
+ }
+ __ret[_S_rank] = __dyn;
+ return __ret;
+ }();
+
+ static constexpr size_t _S_rank_dynamic = _S_dynamic_index[_S_rank];
+
+ // For __r in [0, _S_rank_dynamic), _S_dynamic_index_inv[__r] is the
+ // index of the __r-th dynamic extent in _Extents.
+ static constexpr auto _S_dynamic_index_inv = [] consteval
+ {
+ array<size_t, _S_rank_dynamic> __ret;
+ for (size_t __i = 0, __r = 0; __i < _S_rank; ++__i)
+ if (_S_is_dyn(_Extents[__i]))
+ __ret[__r++] = __i;
+ return __ret;
+ }();
+
+ static constexpr size_t
+ _S_static_extent(size_t __r) noexcept
+ { return _Extents[__r]; }
+
+ constexpr _IndexType
+ _M_extent(size_t __r) const noexcept
+ {
+ auto __se = _Extents[__r];
+ if (__se == dynamic_extent)
+ return _M_dyn_exts[_S_dynamic_index[__r]];
+ else
+ return __se;
+ }
+
+ template<size_t _OtherRank, typename _GetOtherExtent>
+ constexpr void
+ _M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept
+ {
+ for (size_t __i = 0; __i < _S_rank_dynamic; ++__i)
+ {
+ size_t __di = __i;
+ if constexpr (_OtherRank != _S_rank_dynamic)
+ __di = _S_dynamic_index_inv[__i];
+ _M_dyn_exts[__i] = _S_int_cast(__get_extent(__di));
+ }
+ }
+
+ constexpr
+ _ExtentsStorage() noexcept = default;
+
+ template<typename _OIndexType, array _OExtents>
+ constexpr
+ _ExtentsStorage(const _ExtentsStorage<_OIndexType, _OExtents>&
+ __other) noexcept
+ {
+ _M_init_dynamic_extents<_S_rank>([&__other](size_t __i)
+ { return __other._M_extent(__i); });
+ }
+
+ template<typename _OIndexType, size_t _Nm>
+ constexpr
+ _ExtentsStorage(span<const _OIndexType, _Nm> __exts) noexcept
+ {
+ _M_init_dynamic_extents<_Nm>(
+ [&__exts](size_t __i) -> const _OIndexType&
+ { return __exts[__i]; });
+ }
+
+ static constexpr span<const size_t>
+ _S_static_extents(size_t __begin, size_t __end) noexcept
+ {
+ return {_Extents.data() + __begin, _Extents.data() + __end};
+ }
+
+ constexpr span<const _IndexType>
+ _M_dynamic_extents(size_t __begin, size_t __end) const noexcept
+ requires (_Extents.size() > 0)
+ {
+ return {_M_dyn_exts + _S_dynamic_index[__begin],
+ _M_dyn_exts + _S_dynamic_index[__end]};
+ }
+
+ private:
+ using _S_storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type;
+ [[no_unique_address]] _S_storage _M_dyn_exts{};
+ };
+
+ template<typename _OIndexType, typename _SIndexType>
+ concept __valid_index_type =
+ is_convertible_v<_OIndexType, _SIndexType> &&
+ is_nothrow_constructible_v<_SIndexType, _OIndexType>;
+
+ template<size_t _Extent, typename _IndexType>
+ concept
+ __valid_static_extent = _Extent == dynamic_extent
+ || _Extent <= numeric_limits<_IndexType>::max();
+ }
+
+ namespace __mdspan
+ {
+ template<typename _Extents>
+ constexpr span<const size_t>
+ __static_extents(size_t __begin = 0, size_t __end = _Extents::rank())
+ noexcept
+ { return _Extents::_S_storage::_S_static_extents(__begin, __end); }
+
+ template<typename _Extents>
+ constexpr span<const typename _Extents::index_type>
+ __dynamic_extents(const _Extents& __exts, size_t __begin = 0,
+ size_t __end = _Extents::rank()) noexcept
+ {
+ return __exts._M_exts._M_dynamic_extents(__begin, __end);
+ }
+ }
+
+ template<typename _IndexType, size_t... _Extents>
+ class extents
+ {
+ static_assert(__is_standard_integer<_IndexType>::value,
+ "IndexType must be a signed or unsigned integer type");
+ static_assert(
+ (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
+ "Extents must either be dynamic or representable as IndexType");
+
+ public:
+ using index_type = _IndexType;
+ using size_type = make_unsigned_t<index_type>;
+ using rank_type = size_t;
+
+ static constexpr rank_type
+ rank() noexcept { return _S_storage::_S_rank; }
+
+ static constexpr rank_type
+ rank_dynamic() noexcept { return _S_storage::_S_rank_dynamic; }
+
+ static constexpr size_t
+ static_extent(rank_type __r) noexcept
+ {
+ __glibcxx_assert(__r < rank());
+ if constexpr (rank() == 0)
+ __builtin_trap();
+ else
+ return _S_storage::_S_static_extent(__r);
+ }
+
+ constexpr index_type
+ extent(rank_type __r) const noexcept
+ {
+ __glibcxx_assert(__r < rank());
+ if constexpr (rank() == 0)
+ __builtin_trap();
+ else
+ return _M_exts._M_extent(__r);
+ }
+
+ constexpr
+ extents() noexcept = default;
+
+ private:
+ static consteval bool
+ _S_is_less_dynamic(size_t __ext, size_t __oext)
+ { return (__ext != dynamic_extent) && (__oext == dynamic_extent); }
+
+ template<typename _OIndexType, size_t... _OExtents>
+ static consteval bool
+ _S_ctor_explicit()
+ {
+ return (_S_is_less_dynamic(_Extents, _OExtents) || ...)
+ || (numeric_limits<index_type>::max()
+ < numeric_limits<_OIndexType>::max());
+ }
+
+ template<size_t... _OExtents>
+ static consteval bool
+ _S_is_compatible_extents()
+ {
+ if constexpr (sizeof...(_OExtents) != rank())
+ return false;
+ else
+ return ((_OExtents == dynamic_extent || _Extents == dynamic_extent
+ || _OExtents == _Extents) && ...);
+ }
+
+ public:
+ template<typename _OIndexType, size_t... _OExtents>
+ requires (_S_is_compatible_extents<_OExtents...>())
+ constexpr explicit(_S_ctor_explicit<_OIndexType, _OExtents...>())
+ extents(const extents<_OIndexType, _OExtents...>& __other) noexcept
+ : _M_exts(__other._M_exts)
+ { }
+
+ template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
+ requires (sizeof...(_OIndexTypes) == rank()
+ || sizeof...(_OIndexTypes) == rank_dynamic())
+ constexpr explicit extents(_OIndexTypes... __exts) noexcept
+ : _M_exts(span<const _IndexType, sizeof...(_OIndexTypes)>(
+ initializer_list{_S_storage::_S_int_cast(__exts)...}))
+ { }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType, size_t _Nm>
+ requires (_Nm == rank() || _Nm == rank_dynamic())
+ constexpr explicit(_Nm != rank_dynamic())
+ extents(span<_OIndexType, _Nm> __exts) noexcept
+ : _M_exts(span<const _OIndexType, _Nm>(__exts))
+ { }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType, size_t _Nm>
+ requires (_Nm == rank() || _Nm == rank_dynamic())
+ constexpr explicit(_Nm != rank_dynamic())
+ extents(const array<_OIndexType, _Nm>& __exts) noexcept
+ : _M_exts(span<const _OIndexType, _Nm>(__exts))
+ { }
+
+ template<typename _OIndexType, size_t... _OExtents>
+ friend constexpr bool
+ operator==(const extents& __self,
+ const extents<_OIndexType, _OExtents...>& __other) noexcept
+ {
+ if constexpr (!_S_is_compatible_extents<_OExtents...>())
+ return false;
+ else
+ {
+ for (size_t __i = 0; __i < __self.rank(); ++__i)
+ if (!cmp_equal(__self.extent(__i), __other.extent(__i)))
+ return false;
+ return true;
+ }
+ }
+
+ private:
+ friend span<const size_t>
+ __mdspan::__static_extents<extents>(size_t, size_t);
+
+ friend span<const index_type>
+ __mdspan::__dynamic_extents<extents>(const extents&, size_t, size_t);
+
+ using _S_storage = __mdspan::_ExtentsStorage<
+ _IndexType, array<size_t, sizeof...(_Extents)>{_Extents...}>;
+ [[no_unique_address]] _S_storage _M_exts;
+
+ template<typename _OIndexType, size_t... _OExtents>
+ friend class extents;
+ };
+
+ namespace __mdspan
+ {
+ template<typename _Tp, size_t _Nm>
+ constexpr bool
+ __contains_zero(span<_Tp, _Nm> __exts) noexcept
+ {
+ for (size_t __i = 0; __i < __exts.size(); ++__i)
+ if (__exts[__i] == 0)
+ return true;
+ return false;
+ }
+
+ template<typename _Extents>
+ constexpr bool
+ __empty(const _Extents& __exts) noexcept
+ {
+ if constexpr (__contains_zero(__static_extents<_Extents>()))
+ return true;
+ else if constexpr (_Extents::rank_dynamic() > 0)
+ return __contains_zero(__dynamic_extents(__exts));
+ else
+ return false;
+ }
+
+ constexpr size_t
+ __static_extents_prod(const auto& __sta_exts) noexcept
+ {
+ size_t __ret = 1;
+ for (auto __factor : __sta_exts)
+ if (__factor != dynamic_extent)
+ __ret *= __factor;
+ return __ret;
+ }
+
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __exts_prod(const _Extents& __exts, size_t __begin, size_t __end) noexcept
+ {
+ using _IndexType = typename _Extents::index_type;
+
+ size_t __ret = 1;
+ if constexpr (_Extents::rank_dynamic() != _Extents::rank())
+ {
+ auto __sta_exts = __static_extents<_Extents>(__begin, __end);
+ __ret = __static_extents_prod(__sta_exts);
+ if (__ret == 0)
+ return 0;
+ }
+
+ if constexpr (_Extents::rank_dynamic() > 0)
+ for (auto __factor : __dynamic_extents(__exts, __begin, __end))
+ __ret *= size_t(__factor);
+ return _IndexType(__ret);
+ }
+
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __fwd_prod(const _Extents& __exts, size_t __r) noexcept
+ { return __exts_prod(__exts, 0, __r); }
+
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __rev_prod(const _Extents& __exts, size_t __r) noexcept
+ { return __exts_prod(__exts, __r + 1, __exts.rank()); }
+
+ template<typename _IndexType, size_t... _Counts>
+ auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
+ -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
+
+ template<typename _Tp>
+ consteval size_t
+ __dynamic_extent() { return dynamic_extent; }
+ }
+
+ template<typename _IndexType, size_t _Rank>
+ using dextents = decltype(__mdspan::__build_dextents_type<_IndexType>(
+ make_index_sequence<_Rank>()));
+
+ template<typename... _Integrals>
+ requires (is_convertible_v<_Integrals, size_t> && ...)
+ explicit extents(_Integrals...) ->
+ extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>;
+
+ struct layout_left
+ {
+ template<typename _Extents>
+ class mapping;
+ };
+
+ struct layout_right
+ {
+ template<typename _Extents>
+ class mapping;
+ };
+
+ struct layout_stride
+ {
+ template<typename _Extents>
+ class mapping;
+ };
+
+ namespace __mdspan
+ {
+ template<typename _Tp>
+ constexpr bool __is_extents = false;
+
+ template<typename _IndexType, size_t... _Extents>
+ constexpr bool __is_extents<extents<_IndexType, _Extents...>> = true;
+
+ template<typename _Extents, typename... _Indices>
+ constexpr typename _Extents::index_type
+ __linear_index_left(const _Extents& __exts, _Indices... __indices)
+ noexcept
+ {
+ using _IndexType = typename _Extents::index_type;
+ _IndexType __res = 0;
+ if constexpr (sizeof...(__indices) > 0)
+ {
+ _IndexType __mult = 1;
+ auto __update = [&, __pos = 0u](_IndexType __idx) mutable
+ {
+ __res += __idx * __mult;
+ __mult *= __exts.extent(__pos);
+ ++__pos;
+ };
+ (__update(__indices), ...);
+ }
+ return __res;
+ }
+
+ template<typename _Extents,
+ typename _IndexType = typename _Extents::index_type>
+ consteval _IndexType
+ __static_quotient(_IndexType __nom = numeric_limits<_IndexType>::max())
+ {
+ auto __sta_exts = __static_extents<_Extents>();
+ for (auto __factor : __sta_exts)
+ {
+ if (__factor != dynamic_extent)
+ __nom /= _IndexType(__factor);
+ if (__nom == 0)
+ break;
+ }
+ return __nom;
+ }
+
+ template<typename _Extents>
+ constexpr bool
+ __is_representable_extents(const _Extents& __exts) noexcept
+ {
+ using _IndexType = _Extents::index_type;
+
+ if constexpr (__contains_zero(__static_extents<_Extents>()))
+ return true;
+ else
+ {
+ constexpr auto __sta_quo = __static_quotient<_Extents>();
+ if constexpr (_Extents::rank_dynamic() == 0)
+ return __sta_quo != 0;
+ else
+ {
+ auto __dyn_exts = __dynamic_extents(__exts);
+ if (__contains_zero(__dyn_exts))
+ return true;
+
+ if constexpr (__sta_quo == 0)
+ return false;
+ else
+ {
+ auto __dyn_quo = _IndexType(__sta_quo);
+ for (auto __factor : __dyn_exts)
+ {
+ __dyn_quo /= __factor;
+ if (__dyn_quo == 0)
+ return false;
+ }
+ return true;
+ }
+ }
+ }
+ }
+
+ template<typename _Extents, typename _IndexType>
+ concept __representable_size = _Extents::rank_dynamic() != 0
+ || __contains_zero(__static_extents<_Extents>())
+ || (__static_quotient<_Extents, _IndexType>() != 0);
+
+ template<typename _Layout, typename _Mapping>
+ concept __mapping_of =
+ is_same_v<typename _Layout::mapping<typename _Mapping::extents_type>,
+ _Mapping>;
+
+ template<typename _Mapping>
+ concept __standardized_mapping = __mapping_of<layout_left, _Mapping>
+ || __mapping_of<layout_right, _Mapping>
+ || __mapping_of<layout_stride, _Mapping>;
+
+ // A tag type to create internal ctors.
+ class __internal_ctor
+ { };
+ }
+
+ template<typename _Extents>
+ class layout_left::mapping
+ {
+ public:
+ using extents_type = _Extents;
+ using index_type = typename extents_type::index_type;
+ using size_type = typename extents_type::size_type;
+ using rank_type = typename extents_type::rank_type;
+ using layout_type = layout_left;
+
+ static_assert(__mdspan::__representable_size<extents_type, index_type>,
+ "The size of extents_type must be representable as index_type");
+
+ constexpr
+ mapping() noexcept = default;
+
+ constexpr
+ mapping(const mapping&) noexcept = default;
+
+ constexpr
+ mapping(const extents_type& __extents) noexcept
+ : _M_extents(__extents)
+ { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
+
+ template<typename _OExtents>
+ requires is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+ mapping(const mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { }
+
+ template<typename _OExtents>
+ requires (extents_type::rank() <= 1)
+ && is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+ mapping(const layout_right::mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { }
+
+ // noexcept for consistency with other layouts.
+ template<typename _OExtents>
+ requires is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(extents_type::rank() > 0)
+ mapping(const layout_stride::mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { __glibcxx_assert(*this == __other); }
+
+ constexpr mapping&
+ operator=(const mapping&) noexcept = default;
+
+ constexpr const extents_type&
+ extents() const noexcept { return _M_extents; }
+
+ constexpr index_type
+ required_span_size() const noexcept
+ { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); }
+
+ template<__mdspan::__valid_index_type<index_type>... _Indices>
+ requires (sizeof...(_Indices) == extents_type::rank())
+ constexpr index_type
+ operator()(_Indices... __indices) const noexcept
+ {
+ return __mdspan::__linear_index_left(_M_extents,
+ static_cast<index_type>(__indices)...);
+ }
+
+ static constexpr bool
+ is_always_unique() noexcept { return true; }
+
+ static constexpr bool
+ is_always_exhaustive() noexcept { return true; }
+
+ static constexpr bool
+ is_always_strided() noexcept { return true; }
+
+ static constexpr bool
+ is_unique() noexcept { return true; }
+
+ static constexpr bool
+ is_exhaustive() noexcept { return true; }
+
+ static constexpr bool
+ is_strided() noexcept { return true; }
+
+ constexpr index_type
+ stride(rank_type __i) const noexcept
+ requires (extents_type::rank() > 0)
+ {
+ __glibcxx_assert(__i < extents_type::rank());
+ return __mdspan::__fwd_prod(_M_extents, __i);
+ }
+
+ template<typename _OExtents>
+ requires (extents_type::rank() == _OExtents::rank())
+ friend constexpr bool
+ operator==(const mapping& __self, const mapping<_OExtents>& __other)
+ noexcept
+ { return __self.extents() == __other.extents(); }
+
+ private:
+ template<typename _OExtents>
+ constexpr explicit
+ mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
+ : _M_extents(__oexts)
+ {
+ static_assert(__mdspan::__representable_size<_OExtents, index_type>,
+ "The size of OtherExtents must be representable as index_type");
+ __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
+ }
+
+ [[no_unique_address]] extents_type _M_extents{};
+ };
+
+ namespace __mdspan
+ {
+ template<typename _Extents, typename... _Indices>
+ constexpr typename _Extents::index_type
+ __linear_index_right(const _Extents& __exts, _Indices... __indices)
+ noexcept
+ {
+ using _IndexType = typename _Extents::index_type;
+ array<_IndexType, sizeof...(__indices)> __ind_arr{__indices...};
+ _IndexType __res = 0;
+ if constexpr (sizeof...(__indices) > 0)
+ {
+ _IndexType __mult = 1;
+ auto __update = [&, __pos = __exts.rank()](_IndexType) mutable
+ {
+ --__pos;
+ __res += __ind_arr[__pos] * __mult;
+ __mult *= __exts.extent(__pos);
+ };
+ (__update(__indices), ...);
+ }
+ return __res;
+ }
+ }
+
+ template<typename _Extents>
+ class layout_right::mapping
+ {
+ public:
+ using extents_type = _Extents;
+ using index_type = typename extents_type::index_type;
+ using size_type = typename extents_type::size_type;
+ using rank_type = typename extents_type::rank_type;
+ using layout_type = layout_right;
+
+ static_assert(__mdspan::__representable_size<extents_type, index_type>,
+ "The size of extents_type must be representable as index_type");
+
+ constexpr
+ mapping() noexcept = default;
+
+ constexpr
+ mapping(const mapping&) noexcept = default;
+
+ constexpr
+ mapping(const extents_type& __extents) noexcept
+ : _M_extents(__extents)
+ { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
+
+ template<typename _OExtents>
+ requires is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+ mapping(const mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { }
+
+ template<typename _OExtents>
+ requires (extents_type::rank() <= 1)
+ && is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+ mapping(const layout_left::mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { }
+
+ template<typename _OExtents>
+ requires is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(extents_type::rank() > 0)
+ mapping(const layout_stride::mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { __glibcxx_assert(*this == __other); }
+
+ constexpr mapping&
+ operator=(const mapping&) noexcept = default;
+
+ constexpr const extents_type&
+ extents() const noexcept { return _M_extents; }
+
+ constexpr index_type
+ required_span_size() const noexcept
+ { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); }
+
+ template<__mdspan::__valid_index_type<index_type>... _Indices>
+ requires (sizeof...(_Indices) == extents_type::rank())
+ constexpr index_type
+ operator()(_Indices... __indices) const noexcept
+ {
+ return __mdspan::__linear_index_right(
+ _M_extents, static_cast<index_type>(__indices)...);
+ }
+
+ static constexpr bool
+ is_always_unique() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_always_exhaustive() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_always_strided() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_unique() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_exhaustive() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_strided() noexcept
+ { return true; }
+
+ constexpr index_type
+ stride(rank_type __i) const noexcept
+ requires (extents_type::rank() > 0)
+ {
+ __glibcxx_assert(__i < extents_type::rank());
+ return __mdspan::__rev_prod(_M_extents, __i);
+ }
+
+ template<typename _OExtents>
+ requires (extents_type::rank() == _OExtents::rank())
+ friend constexpr bool
+ operator==(const mapping& __self, const mapping<_OExtents>& __other)
+ noexcept
+ { return __self.extents() == __other.extents(); }
+
+ private:
+ template<typename _OExtents>
+ constexpr explicit
+ mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
+ : _M_extents(__oexts)
+ {
+ static_assert(__mdspan::__representable_size<_OExtents, index_type>,
+ "The size of OtherExtents must be representable as index_type");
+ __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
+ }
+
+ [[no_unique_address]] extents_type _M_extents{};
+ };
+
+ namespace __mdspan
+ {
+ template<typename _Mp>
+ concept __mapping_alike = requires
+ {
+ requires __is_extents<typename _Mp::extents_type>;
+ { _Mp::is_always_strided() } -> same_as<bool>;
+ { _Mp::is_always_exhaustive() } -> same_as<bool>;
+ { _Mp::is_always_unique() } -> same_as<bool>;
+ bool_constant<_Mp::is_always_strided()>::value;
+ bool_constant<_Mp::is_always_exhaustive()>::value;
+ bool_constant<_Mp::is_always_unique()>::value;
+ };
+
+ template<typename _Mapping>
+ constexpr typename _Mapping::index_type
+ __offset(const _Mapping& __m) noexcept
+ {
+ using _IndexType = typename _Mapping::index_type;
+ constexpr auto __rank = _Mapping::extents_type::rank();
+
+ if constexpr (__standardized_mapping<_Mapping>)
+ return 0;
+ else if (__empty(__m.extents()))
+ return 0;
+ else
+ {
+ auto __impl = [&__m]<size_t... _Counts>(index_sequence<_Counts...>)
+ { return __m(((void) _Counts, _IndexType(0))...); };
+ return __impl(make_index_sequence<__rank>());
+ }
+ }
+
+ template<typename _Mapping, typename... _Indices>
+ constexpr typename _Mapping::index_type
+ __linear_index_strides(const _Mapping& __m, _Indices... __indices)
+ noexcept
+ {
+ using _IndexType = typename _Mapping::index_type;
+ _IndexType __res = 0;
+ if constexpr (sizeof...(__indices) > 0)
+ {
+ auto __update = [&, __pos = 0u](_IndexType __idx) mutable
+ {
+ __res += __idx * __m.stride(__pos++);
+ };
+ (__update(__indices), ...);
+ }
+ return __res;
+ }
+ }
+
+ template<typename _Extents>
+ class layout_stride::mapping
+ {
+ public:
+ using extents_type = _Extents;
+ using index_type = typename extents_type::index_type;
+ using size_type = typename extents_type::size_type;
+ using rank_type = typename extents_type::rank_type;
+ using layout_type = layout_stride;
+
+ static_assert(__mdspan::__representable_size<extents_type, index_type>,
+ "The size of extents_type must be representable as index_type");
+
+ constexpr
+ mapping() noexcept
+ {
+ // The precondition is either statically asserted, or automatically
+ // satisfied because dynamic extents are zero-initialized.
+ size_t __stride = 1;
+ for (size_t __i = extents_type::rank(); __i > 0; --__i)
+ {
+ _M_strides[__i - 1] = index_type(__stride);
+ __stride *= size_t(_M_extents.extent(__i - 1));
+ }
+ }
+
+ constexpr
+ mapping(const mapping&) noexcept = default;
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType>
+ constexpr
+ mapping(const extents_type& __exts,
+ span<_OIndexType, extents_type::rank()> __strides) noexcept
+ : _M_extents(__exts)
+ {
+ for (size_t __i = 0; __i < extents_type::rank(); ++__i)
+ _M_strides[__i] = index_type(as_const(__strides[__i]));
+ }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType>
+ constexpr
+ mapping(const extents_type& __exts,
+ const array<_OIndexType, extents_type::rank()>& __strides)
+ noexcept
+ : mapping(__exts,
+ span<const _OIndexType, extents_type::rank()>(__strides))
+ { }
+
+ template<__mdspan::__mapping_alike _StridedMapping>
+ requires (is_constructible_v<extents_type,
+ typename _StridedMapping::extents_type>
+ && _StridedMapping::is_always_unique()
+ && _StridedMapping::is_always_strided())
+ constexpr explicit(!(
+ is_convertible_v<typename _StridedMapping::extents_type, extents_type>
+ && __mdspan::__standardized_mapping<_StridedMapping>))
+ mapping(const _StridedMapping& __other) noexcept
+ : _M_extents(__other.extents())
+ {
+ using _OIndexType = _StridedMapping::index_type;
+ using _OExtents = _StridedMapping::extents_type;
+
+ __glibcxx_assert(__mdspan::__offset(__other) == 0);
+ static_assert(__mdspan::__representable_size<_OExtents, index_type>,
+ "The size of StridedMapping::extents_type must be representable as"
+ " index_type");
+ if constexpr (cmp_greater(numeric_limits<_OIndexType>::max(),
+ numeric_limits<index_type>::max()))
+ __glibcxx_assert(!cmp_less(numeric_limits<index_type>::max(),
+ __other.required_span_size())
+ && "other.required_span_size() must be representable"
+ " as index_type");
+ if constexpr (extents_type::rank() > 0)
+ for (size_t __i = 0; __i < extents_type::rank(); ++__i)
+ _M_strides[__i] = index_type(__other.stride(__i));
+ }
+
+ constexpr mapping&
+ operator=(const mapping&) noexcept = default;
+
+ constexpr const extents_type&
+ extents() const noexcept { return _M_extents; }
+
+ constexpr array<index_type, extents_type::rank()>
+ strides() const noexcept
+ {
+ array<index_type, extents_type::rank()> __ret;
+ for (size_t __i = 0; __i < extents_type::rank(); ++__i)
+ __ret[__i] = _M_strides[__i];
+ return __ret;
+ }
+
+ constexpr index_type
+ required_span_size() const noexcept
+ {
+ if (__mdspan::__empty(_M_extents))
+ return 0;
+
+ index_type __ret = 1;
+ for (size_t __i = 0; __i < extents_type::rank(); ++__i)
+ __ret += (_M_extents.extent(__i) - 1) * _M_strides[__i];
+ return __ret;
+ }
+
+ template<__mdspan::__valid_index_type<index_type>... _Indices>
+ requires (sizeof...(_Indices) == extents_type::rank())
+ constexpr index_type
+ operator()(_Indices... __indices) const noexcept
+ {
+ return __mdspan::__linear_index_strides(*this,
+ static_cast<index_type>(__indices)...);
+ }
+
+ static constexpr bool
+ is_always_unique() noexcept { return true; }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4266. layout_stride::mapping should treat empty mappings as exhaustive
+ static constexpr bool
+ is_always_exhaustive() noexcept
+ {
+ return (_Extents::rank() == 0) || __mdspan::__contains_zero(
+ __mdspan::__static_extents<extents_type>());
+ }
+
+ static constexpr bool
+ is_always_strided() noexcept { return true; }
+
+ static constexpr bool
+ is_unique() noexcept { return true; }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4266. layout_stride::mapping should treat empty mappings as exhaustive
+ constexpr bool
+ is_exhaustive() const noexcept
+ {
+ if constexpr (!is_always_exhaustive())
+ {
+ constexpr auto __rank = extents_type::rank();
+ auto __size = __mdspan::__fwd_prod(_M_extents, __rank);
+ if(__size > 0)
+ return __size == required_span_size();
+ }
+ return true;
+ }
+
+ static constexpr bool
+ is_strided() noexcept { return true; }
+
+ constexpr index_type
+ stride(rank_type __r) const noexcept { return _M_strides[__r]; }
+
+ template<__mdspan::__mapping_alike _OMapping>
+ requires ((extents_type::rank() == _OMapping::extents_type::rank())
+ && _OMapping::is_always_strided())
+ friend constexpr bool
+ operator==(const mapping& __self, const _OMapping& __other) noexcept
+ {
+ if (__self.extents() != __other.extents())
+ return false;
+ if constexpr (extents_type::rank() > 0)
+ for (size_t __i = 0; __i < extents_type::rank(); ++__i)
+ if (!cmp_equal(__self.stride(__i), __other.stride(__i)))
+ return false;
+ return __mdspan::__offset(__other) == 0;
+ }
+
+ private:
+ using _S_strides_t = typename __array_traits<index_type,
+ extents_type::rank()>::_Type;
+ [[no_unique_address]] extents_type _M_extents;
+ [[no_unique_address]] _S_strides_t _M_strides;
+ };
+
+ template<typename _ElementType>
+ struct default_accessor
+ {
+ static_assert(!is_array_v<_ElementType>,
+ "ElementType must not be an array type");
+ static_assert(!is_abstract_v<_ElementType>,
+ "ElementType must not be an abstract class type");
+
+ using offset_policy = default_accessor;
+ using element_type = _ElementType;
+ using reference = element_type&;
+ using data_handle_type = element_type*;
+
+ constexpr
+ default_accessor() noexcept = default;
+
+ template<typename _OElementType>
+ requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
+ constexpr
+ default_accessor(default_accessor<_OElementType>) noexcept
+ { }
+
+ constexpr reference
+ access(data_handle_type __p, size_t __i) const noexcept
+ { return __p[__i]; }
+
+ constexpr data_handle_type
+ offset(data_handle_type __p, size_t __i) const noexcept
+ { return __p + __i; }
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+#endif
+#endif
diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory
index 99f542d..1da03b3 100644
--- a/libstdc++-v3/include/std/memory
+++ b/libstdc++-v3/include/std/memory
@@ -97,6 +97,11 @@
# include <bits/out_ptr.h>
#endif
+#if __cplusplus > 202302L
+# include <bits/indirect.h>
+#endif
+
+#define __glibcxx_want_addressof_constexpr
#define __glibcxx_want_allocator_traits_is_always_equal
#define __glibcxx_want_assume_aligned
#define __glibcxx_want_atomic_shared_ptr
@@ -104,9 +109,11 @@
#define __glibcxx_want_constexpr_dynamic_alloc
#define __glibcxx_want_constexpr_memory
#define __glibcxx_want_enable_shared_from_this
+#define __glibcxx_want_indirect
#define __glibcxx_want_make_unique
#define __glibcxx_want_out_ptr
#define __glibcxx_want_parallel_algorithm
+#define __glibcxx_want_polymorphic
#define __glibcxx_want_ranges
#define __glibcxx_want_raw_memory_algorithms
#define __glibcxx_want_shared_ptr_arrays
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index b3f89c0..e575a81 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -733,7 +733,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
-#ifdef __cpp_lib_scoped_lock // C++ >= 17 && hosted && gthread
+#ifdef __cpp_lib_scoped_lock // C++ >= 17
/** @brief A scoped lock type for multiple lockable objects.
*
* A scoped_lock controls mutex ownership within a scope, releasing
diff --git a/libstdc++-v3/include/std/numeric b/libstdc++-v3/include/std/numeric
index 4d36fcd..cbabf031 100644
--- a/libstdc++-v3/include/std/numeric
+++ b/libstdc++-v3/include/std/numeric
@@ -582,7 +582,7 @@ namespace __detail
{
if (__first != __last)
{
- auto __init = *__first;
+ auto __init = std::move(*__first);
*__result++ = __init;
++__first;
if (__first != __last)
@@ -645,8 +645,8 @@ namespace __detail
{
while (__first != __last)
{
- auto __v = __init;
- __init = __binary_op(__init, __unary_op(*__first));
+ auto __v = std::move(__init);
+ __init = __binary_op(__v, __unary_op(*__first));
++__first;
*__result++ = std::move(__v);
}
@@ -732,12 +732,11 @@ namespace __detail
/// @} group numeric_ops
#endif // C++17
+#if __glibcxx_ranges_iota >= 202202L // C++ >= 23
namespace ranges
{
-#if __glibcxx_ranges_iota >= 202202L // C++ >= 23
-
template<typename _Out, typename _Tp>
- using iota_result = out_value_result<_Out, _Tp>;
+ using iota_result = out_value_result<_Out, _Tp>;
struct __iota_fn
{
@@ -762,9 +761,8 @@ namespace ranges
};
inline constexpr __iota_fn iota{};
-
-#endif // __glibcxx_ranges_iota
} // namespace ranges
+#endif // __glibcxx_ranges_iota
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional
index a616dc0..cc7af5b 100644
--- a/libstdc++-v3/include/std/optional
+++ b/libstdc++-v3/include/std/optional
@@ -36,6 +36,7 @@
#define __glibcxx_want_freestanding_optional
#define __glibcxx_want_optional
+#define __glibcxx_want_optional_range_support
#define __glibcxx_want_constrained_equality
#include <bits/version.h>
@@ -57,6 +58,11 @@
#if __cplusplus > 202002L
# include <concepts>
#endif
+#ifdef __cpp_lib_optional_range_support // C++ >= 26
+# include <bits/formatfwd.h>
+# include <bits/ranges_base.h>
+# include <bits/stl_iterator.h>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -858,6 +864,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
using value_type = _Tp;
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional>;
+ using const_iterator = __gnu_cxx::__normal_iterator<const _Tp*, optional>;
+#endif
constexpr optional() noexcept { }
@@ -1158,6 +1168,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ // Iterator support.
+ constexpr iterator begin() noexcept
+ {
+ return iterator(
+ this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr
+ );
+ }
+
+ constexpr const_iterator begin() const noexcept
+ {
+ return const_iterator(
+ this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr
+ );
+ }
+
+ constexpr iterator end() noexcept
+ {
+ return begin() + has_value();
+ }
+
+ constexpr const_iterator end() const noexcept
+ {
+ return begin() + has_value();
+ }
+#endif // __cpp_lib_optional_range_support
+
// Observers.
constexpr const _Tp*
operator->() const noexcept
@@ -1772,6 +1809,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _Tp> optional(_Tp) -> optional<_Tp>;
#endif
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ template<typename _Tp>
+ inline constexpr bool
+ ranges::enable_view<optional<_Tp>> = true;
+
+ template<typename _Tp>
+ inline constexpr range_format
+ format_kind<optional<_Tp>> = range_format::disabled;
+#endif // __cpp_lib_optional_range_support
+
#undef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream
index 644e568..3a0a0d3 100644
--- a/libstdc++-v3/include/std/ostream
+++ b/libstdc++-v3/include/std/ostream
@@ -193,7 +193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
__format::_Str_sink<char> __buf;
std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
- auto __out = __buf.view();
+ auto __out = __buf._M_span();
void* __open_terminal(streambuf*);
error_code __write_to_terminal(void*, span<char>);
diff --git a/libstdc++-v3/include/std/print b/libstdc++-v3/include/std/print
index ea1aaac..92dbe11 100644
--- a/libstdc++-v3/include/std/print
+++ b/libstdc++-v3/include/std/print
@@ -73,7 +73,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#else
__format::_Str_sink<char> __buf;
std::vformat_to(__buf.out(), __fmt, __args);
- auto __out = __buf.view();
+ auto __out = __buf._M_span();
void* __open_terminal(FILE*);
error_code __write_to_terminal(void*, span<char>);
diff --git a/libstdc++-v3/include/std/queue b/libstdc++-v3/include/std/queue
index c06a4c3..9052589 100644
--- a/libstdc++-v3/include/std/queue
+++ b/libstdc++-v3/include/std/queue
@@ -61,13 +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
-#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/ranges b/libstdc++-v3/include/std/ranges
index 7a339c5..210ac82 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -64,7 +64,6 @@
#define __glibcxx_want_ranges_chunk
#define __glibcxx_want_ranges_chunk_by
#define __glibcxx_want_ranges_enumerate
-#define __glibcxx_want_ranges_iota
#define __glibcxx_want_ranges_join_with
#define __glibcxx_want_ranges_repeat
#define __glibcxx_want_ranges_slide
@@ -5337,7 +5336,7 @@ namespace views::__adaptor
requires move_constructible<decay_t<_Fp>> && regular_invocable<decay_t<_Fp>&>
&& is_object_v<decay_t<invoke_result_t<decay_t<_Fp>&>>>
constexpr auto
- operator() [[nodiscard]] (_Fp&& __f) const
+ operator() [[nodiscard]] (_Fp&&) const
{
return views::empty<decay_t<invoke_result_t<decay_t<_Fp>&>>>;
}
@@ -6599,7 +6598,7 @@ namespace views::__adaptor
}
friend constexpr difference_type
- operator-(default_sentinel_t __y, const _Iterator& __x)
+ operator-(default_sentinel_t, const _Iterator& __x)
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
{ return __detail::__div_ceil(__x._M_end - __x._M_current, __x._M_n); }
@@ -7288,8 +7287,8 @@ namespace views::__adaptor
using iterator_category = decltype(_S_iter_cat());
};
- template<bool> struct _Iterator;
- template<bool> struct _Sentinel;
+ template<bool> class _Iterator;
+ template<bool> class _Sentinel;
public:
join_with_view() requires (default_initializable<_Vp>
@@ -7744,7 +7743,7 @@ namespace views::__adaptor
__detail::__box<_Tp> _M_value;
[[no_unique_address]] _Bound _M_bound = _Bound();
- struct _Iterator;
+ class _Iterator;
template<typename _Range>
friend constexpr auto
@@ -8304,7 +8303,7 @@ namespace views::__adaptor
}
friend constexpr difference_type
- operator-(default_sentinel_t __y, const _Iterator& __x)
+ operator-(default_sentinel_t, const _Iterator& __x)
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
{ return __detail::__div_ceil(__x._M_end - __x._M_current, __x._M_stride); }
diff --git a/libstdc++-v3/include/std/semaphore b/libstdc++-v3/include/std/semaphore
index bec5ac3..18d0407 100644
--- a/libstdc++-v3/include/std/semaphore
+++ b/libstdc++-v3/include/std/semaphore
@@ -35,29 +35,28 @@
#include <bits/requires_hosted.h> // concurrency
-#if __cplusplus > 201703L
-#include <bits/semaphore_base.h>
-
#define __glibcxx_want_semaphore
#include <bits/version.h>
-#ifdef __cpp_lib_semaphore // C++ >= 20 && hosted && (atomic_wait || posix_sem)
+#ifdef __cpp_lib_semaphore // C++ >= 20 && hosted && atomic_wait
+#include <bits/semaphore_base.h>
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
- template<ptrdiff_t __least_max_value = __semaphore_impl::_S_max>
+ template<ptrdiff_t __least_max_value = _Semaphore_impl<2>::_S_max>
class counting_semaphore
{
static_assert(__least_max_value >= 0);
- static_assert(__least_max_value <= __semaphore_impl::_S_max);
- __semaphore_impl _M_sem;
+ _Semaphore_impl<__least_max_value> _M_sem;
public:
- explicit counting_semaphore(ptrdiff_t __desired) noexcept
- : _M_sem(__desired)
- { }
+ constexpr explicit
+ counting_semaphore(ptrdiff_t __desired) noexcept
+ : _M_sem(__desired)
+ { __glibcxx_assert(__desired >= 0 && __desired <= max()); }
~counting_semaphore() = default;
@@ -69,8 +68,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __least_max_value; }
void
- release(ptrdiff_t __update = 1) noexcept(noexcept(_M_sem._M_release(1)))
- { _M_sem._M_release(__update); }
+ release(ptrdiff_t __update = 1) noexcept
+ {
+ [[maybe_unused]] ptrdiff_t __old = _M_sem._M_release(__update);
+ __glibcxx_assert(__update >= 0 && __update <= max() - __old);
+ }
void
acquire() noexcept(noexcept(_M_sem._M_acquire()))
@@ -91,10 +93,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return _M_sem._M_try_acquire_until(__atime); }
};
+ /** @brief A binary semaphore
+ *
+ * @since C++20
+ */
using binary_semaphore = std::counting_semaphore<1>;
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
-#endif // cpp_lib_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE
#endif // __cpp_lib_semaphore
#endif // _GLIBCXX_SEMAPHORE
diff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set
index 2ebf485..cf7057a 100644
--- a/libstdc++-v3/include/std/set
+++ b/libstdc++-v3/include/std/set
@@ -72,6 +72,7 @@
#endif
#define __glibcxx_want_allocator_traits_is_always_equal
+#define __glibcxx_want_containers_ranges
#define __glibcxx_want_erase_if
#define __glibcxx_want_generic_associative_lookup
#define __glibcxx_want_node_extract
diff --git a/libstdc++-v3/include/std/sstream b/libstdc++-v3/include/std/sstream
index ad0c16a..b1b4126 100644
--- a/libstdc++-v3/include/std/sstream
+++ b/libstdc++-v3/include/std/sstream
@@ -41,8 +41,16 @@
#include <istream>
#include <ostream>
+
#include <bits/alloc_traits.h> // allocator_traits, __allocator_like
+#define __glibcxx_want_sstream_from_string_view
+#include <bits/version.h>
+
+#ifdef __cpp_lib_sstream_from_string_view
+# include <string_view>
+#endif
+
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
# define _GLIBCXX_LVAL_REF_QUAL &
# define _GLIBCXX_SSTREAM_ALWAYS_INLINE
@@ -52,8 +60,6 @@
# define _GLIBCXX_SSTREAM_ALWAYS_INLINE [[__gnu__::__always_inline__]]
#endif
-
-
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -159,6 +165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); }
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+ // P0408 Efficient access to basic_stringbuf buffer
explicit
basic_stringbuf(const allocator_type& __a)
: basic_stringbuf(ios_base::in | std::ios_base::out, __a)
@@ -197,7 +204,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
| ios_base::out)
: basic_stringbuf(__s, __mode, allocator_type{})
{ }
+#endif
+#ifdef __cpp_lib_sstream_from_string_view
+ template<typename _Tp>
+ explicit
+ basic_stringbuf(const _Tp& __t,
+ ios_base::openmode __mode = ios_base::in | ios_base::out)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : basic_stringbuf(__t, __mode, allocator_type{})
+ { }
+
+ template<typename _Tp>
+ basic_stringbuf(const _Tp& __t, const allocator_type& __a)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : basic_stringbuf(__t, ios_base::in | ios_base::out, __a)
+ { }
+
+ template<typename _Tp>
+ basic_stringbuf(const _Tp& __t, ios_base::openmode __mode,
+ const allocator_type& __a)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : _M_string(__t, __a)
+ { _M_stringbuf_init(__mode); }
+#endif // C++26
+
+#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+ // P0408 Efficient access to basic_stringbuf buffer
basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& __a)
: basic_stringbuf(std::move(__rhs), __a, __xfer_bufptrs(__rhs, this))
{ __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); }
@@ -262,6 +298,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus > 201703L
#if _GLIBCXX_USE_CXX11_ABI
#if __cpp_concepts
+ // P0407 Allocator-aware basic_streambuf
template<__allocator_like _SAlloc>
_GLIBCXX_NODISCARD
basic_string<_CharT, _Traits, _SAlloc>
@@ -317,6 +354,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
#if __cpp_concepts
+ // P0407 Allocator-aware basic_streambuf
template<__allocator_like _SAlloc>
requires (!is_same_v<_SAlloc, _Alloc>)
void
@@ -335,6 +373,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
}
#endif
+#ifdef __cpp_lib_sstream_from_string_view
+ template <typename _Tp>
+ void
+ str(const _Tp& __t)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ {
+ basic_string_view<_CharT, _Traits> __sv{__t};
+ _M_string = __sv;
+ _M_stringbuf_init(_M_mode);
+ }
+#endif // C++26
+
protected:
// Common initialization code goes here.
void
@@ -521,6 +572,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ }
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+ // P0408 Efficient access to basic_stringbuf buffer
+
// The move constructor initializes an __xfer_bufptrs temporary then
// delegates to this constructor to performs moves during its lifetime.
basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& __a,
@@ -584,7 +637,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/
basic_istringstream()
: __istream_type(), _M_stringbuf(ios_base::in)
- { this->init(&_M_stringbuf); }
+ { this->init(std::__addressof(_M_stringbuf)); }
/**
* @brief Starts with an empty string buffer.
@@ -601,7 +654,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
explicit
basic_istringstream(ios_base::openmode __mode)
: __istream_type(), _M_stringbuf(__mode | ios_base::in)
- { this->init(&_M_stringbuf); }
+ { this->init(std::__addressof(_M_stringbuf)); }
/**
* @brief Starts with an existing string buffer.
@@ -620,7 +673,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_istringstream(const __string_type& __str,
ios_base::openmode __mode = ios_base::in)
: __istream_type(), _M_stringbuf(__str, __mode | ios_base::in)
- { this->init(&_M_stringbuf); }
+ { this->init(std::__addressof(_M_stringbuf)); }
/**
* @brief The destructor does nothing.
@@ -637,9 +690,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_istringstream(basic_istringstream&& __rhs)
: __istream_type(std::move(__rhs)),
_M_stringbuf(std::move(__rhs._M_stringbuf))
- { __istream_type::set_rdbuf(&_M_stringbuf); }
+ { __istream_type::set_rdbuf(std::__addressof(_M_stringbuf)); }
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+ // P0408 Efficient access to basic_stringbuf buffer
basic_istringstream(ios_base::openmode __mode, const allocator_type& __a)
: __istream_type(), _M_stringbuf(__mode | ios_base::in, __a)
{ this->init(std::__addressof(_M_stringbuf)); }
@@ -671,6 +725,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ }
#endif // C++20
+#ifdef __cpp_lib_sstream_from_string_view
+ template <typename _Tp>
+ explicit
+ basic_istringstream(const _Tp& __t,
+ ios_base::openmode __mode = ios_base::in)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : basic_istringstream(__t, __mode, allocator_type{})
+ { }
+
+ template <typename _Tp>
+ basic_istringstream(const _Tp& __t, const allocator_type& __a)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : basic_istringstream(__t, ios_base::in, __a)
+ { }
+
+ template <typename _Tp>
+ basic_istringstream(const _Tp& __t, ios_base::openmode __mode,
+ const allocator_type& __a)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : __istream_type(), _M_stringbuf(__t, __mode | ios_base::in, __a)
+ { this->init(std::__addressof(_M_stringbuf)); }
+#endif // C++26
+
// 27.8.3.2 Assign and swap:
basic_istringstream&
@@ -702,7 +782,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_NODISCARD
__stringbuf_type*
rdbuf() const
- { return const_cast<__stringbuf_type*>(&_M_stringbuf); }
+ { return const_cast<__stringbuf_type*>(std::__addressof(_M_stringbuf)); }
/**
* @brief Copying out the string buffer.
@@ -716,6 +796,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus > 201703L
#if _GLIBCXX_USE_CXX11_ABI
#if __cpp_concepts
+ // P0407 Allocator-aware basic_streambuf
template<__allocator_like _SAlloc>
_GLIBCXX_NODISCARD
basic_string<_CharT, _Traits, _SAlloc>
@@ -747,6 +828,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
#if __cpp_concepts
+ // P0407 Allocator-aware basic_streambuf
template<__allocator_like _SAlloc>
requires (!is_same_v<_SAlloc, _Alloc>)
void
@@ -758,6 +840,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
str(__string_type&& __s)
{ _M_stringbuf.str(std::move(__s)); }
#endif
+
+#ifdef __cpp_lib_sstream_from_string_view
+ template<typename _Tp>
+ void
+ str(const _Tp& __t)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ { _M_stringbuf.str(__t); }
+#endif // C++26
};
@@ -812,7 +903,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/
basic_ostringstream()
: __ostream_type(), _M_stringbuf(ios_base::out)
- { this->init(&_M_stringbuf); }
+ { this->init(std::__addressof(_M_stringbuf)); }
/**
* @brief Starts with an empty string buffer.
@@ -829,7 +920,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
explicit
basic_ostringstream(ios_base::openmode __mode)
: __ostream_type(), _M_stringbuf(__mode | ios_base::out)
- { this->init(&_M_stringbuf); }
+ { this->init(std::__addressof(_M_stringbuf)); }
/**
* @brief Starts with an existing string buffer.
@@ -848,7 +939,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_ostringstream(const __string_type& __str,
ios_base::openmode __mode = ios_base::out)
: __ostream_type(), _M_stringbuf(__str, __mode | ios_base::out)
- { this->init(&_M_stringbuf); }
+ { this->init(std::__addressof(_M_stringbuf)); }
/**
* @brief The destructor does nothing.
@@ -865,9 +956,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_ostringstream(basic_ostringstream&& __rhs)
: __ostream_type(std::move(__rhs)),
_M_stringbuf(std::move(__rhs._M_stringbuf))
- { __ostream_type::set_rdbuf(&_M_stringbuf); }
+ { __ostream_type::set_rdbuf(std::__addressof(_M_stringbuf)); }
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+ // P0408 Efficient access to basic_stringbuf buffer
basic_ostringstream(ios_base::openmode __mode, const allocator_type& __a)
: __ostream_type(), _M_stringbuf(__mode | ios_base::out, __a)
{ this->init(std::__addressof(_M_stringbuf)); }
@@ -899,6 +991,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ }
#endif // C++20
+#ifdef __cpp_lib_sstream_from_string_view
+ template <typename _Tp>
+ explicit
+ basic_ostringstream(
+ const _Tp& __t, ios_base::openmode __mode = ios_base::out)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : basic_ostringstream(__t, __mode, allocator_type{})
+ { }
+
+ template <typename _Tp>
+ basic_ostringstream(const _Tp& __t, const allocator_type& __a)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : basic_ostringstream(__t, ios_base::out, __a)
+ { }
+
+ template <typename _Tp>
+ basic_ostringstream(const _Tp& __t, ios_base::openmode __mode,
+ const allocator_type& __a)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : __ostream_type(), _M_stringbuf(__t, __mode | ios_base::out, __a)
+ { this->init(std::__addressof(_M_stringbuf)); }
+#endif // C++26
+
// 27.8.3.2 Assign and swap:
basic_ostringstream&
@@ -930,7 +1048,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_NODISCARD
__stringbuf_type*
rdbuf() const
- { return const_cast<__stringbuf_type*>(&_M_stringbuf); }
+ { return const_cast<__stringbuf_type*>(std::__addressof(_M_stringbuf)); }
/**
* @brief Copying out the string buffer.
@@ -944,6 +1062,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus > 201703L
#if _GLIBCXX_USE_CXX11_ABI
#if __cpp_concepts
+ // P0407 Allocator-aware basic_streambuf
template<__allocator_like _SAlloc>
_GLIBCXX_NODISCARD
basic_string<_CharT, _Traits, _SAlloc>
@@ -975,6 +1094,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
#if __cpp_concepts
+ // P0407 Allocator-aware basic_streambuf
template<__allocator_like _SAlloc>
requires (!is_same_v<_SAlloc, _Alloc>)
void
@@ -986,6 +1106,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
str(__string_type&& __s)
{ _M_stringbuf.str(std::move(__s)); }
#endif
+
+#ifdef __cpp_lib_sstream_from_string_view
+ template<typename _Tp>
+ void
+ str(const _Tp& __t)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ { _M_stringbuf.str(__t); }
+#endif // C++26
};
@@ -1040,7 +1169,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/
basic_stringstream()
: __iostream_type(), _M_stringbuf(ios_base::out | ios_base::in)
- { this->init(&_M_stringbuf); }
+ { this->init(std::__addressof(_M_stringbuf)); }
/**
* @brief Starts with an empty string buffer.
@@ -1055,7 +1184,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
explicit
basic_stringstream(ios_base::openmode __m)
: __iostream_type(), _M_stringbuf(__m)
- { this->init(&_M_stringbuf); }
+ { this->init(std::__addressof(_M_stringbuf)); }
/**
* @brief Starts with an existing string buffer.
@@ -1072,7 +1201,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_stringstream(const __string_type& __str,
ios_base::openmode __m = ios_base::out | ios_base::in)
: __iostream_type(), _M_stringbuf(__str, __m)
- { this->init(&_M_stringbuf); }
+ { this->init(std::__addressof(_M_stringbuf)); }
/**
* @brief The destructor does nothing.
@@ -1089,12 +1218,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_stringstream(basic_stringstream&& __rhs)
: __iostream_type(std::move(__rhs)),
_M_stringbuf(std::move(__rhs._M_stringbuf))
- { __iostream_type::set_rdbuf(&_M_stringbuf); }
+ { __iostream_type::set_rdbuf(std::__addressof(_M_stringbuf)); }
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+ // P0408 Efficient access to basic_stringbuf buffer
basic_stringstream(ios_base::openmode __mode, const allocator_type& __a)
: __iostream_type(), _M_stringbuf(__mode, __a)
- { this->init(&_M_stringbuf); }
+ { this->init(std::__addressof(_M_stringbuf)); }
explicit
basic_stringstream(__string_type&& __str,
@@ -1125,6 +1255,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ }
#endif // C++20
+#ifdef __cpp_lib_sstream_from_string_view
+ template <typename _Tp>
+ explicit
+ basic_stringstream(const _Tp& __t,
+ ios_base::openmode __mode = ios_base::in | ios_base::out)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : basic_stringstream(__t, __mode, allocator_type{})
+ { }
+
+ template <typename _Tp>
+ basic_stringstream(const _Tp& __t, const allocator_type& __a)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ : basic_stringstream(__t, ios_base::in | ios_base::out, __a)
+ { }
+
+ template <typename _Tp>
+ basic_stringstream(const _Tp& __t, ios_base::openmode __mode,
+ const allocator_type& __a)
+ requires (is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>)
+ : __iostream_type(), _M_stringbuf(__t, __mode, __a)
+ { this->init(std::__addressof(_M_stringbuf)); }
+#endif // C++26
+
// 27.8.3.2 Assign and swap:
basic_stringstream&
@@ -1156,7 +1311,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_NODISCARD
__stringbuf_type*
rdbuf() const
- { return const_cast<__stringbuf_type*>(&_M_stringbuf); }
+ { return const_cast<__stringbuf_type*>(std::__addressof(_M_stringbuf)); }
/**
* @brief Copying out the string buffer.
@@ -1170,6 +1325,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus > 201703L
#if _GLIBCXX_USE_CXX11_ABI
#if __cpp_concepts
+ // P0407 Allocator-aware basic_streambuf
template<__allocator_like _SAlloc>
_GLIBCXX_NODISCARD
basic_string<_CharT, _Traits, _SAlloc>
@@ -1201,6 +1357,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
#if __cpp_concepts
+ // P0407 Allocator-aware basic_streambuf
template<__allocator_like _SAlloc>
requires (!is_same_v<_SAlloc, _Alloc>)
void
@@ -1212,6 +1369,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
str(__string_type&& __s)
{ _M_stringbuf.str(std::move(__s)); }
#endif
+
+#ifdef __cpp_lib_sstream_from_string_view
+ template<typename _Tp>
+ void
+ str(const _Tp& __t)
+ requires (is_convertible_v<const _Tp&,
+ basic_string_view<_CharT, _Traits>>)
+ { _M_stringbuf.str(__t); }
+#endif // C++26
};
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/std/stack b/libstdc++-v3/include/std/stack
index 2f7951a..a57a5a0 100644
--- a/libstdc++-v3/include/std/stack
+++ b/libstdc++-v3/include/std/stack
@@ -61,10 +61,53 @@
#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 <bits/stl_stack.h>
-#define __glibcxx_want_adaptor_iterator_pair_constructor
-#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<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/stop_token b/libstdc++-v3/include/std/stop_token
index 1225b3a..775ec6a 100644
--- a/libstdc++-v3/include/std/stop_token
+++ b/libstdc++-v3/include/std/stop_token
@@ -34,8 +34,7 @@
#define __glibcxx_want_jthread
#include <bits/version.h>
-#if __cplusplus > 201703L
-
+#ifdef __glibcxx_jthread // C++ >= 20
#include <atomic>
#include <bits/std_thread.h>
@@ -650,6 +649,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
stop_callback(stop_token, _Callback) -> stop_callback<_Callback>;
_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-#endif // __cplusplus > 201703L
+} // namespace std
+#endif // __glibcxx_jthread
#endif // _GLIBCXX_STOP_TOKEN
diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string
index 6211da9..7186471 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -60,6 +60,7 @@
#define __glibcxx_want_allocator_traits_is_always_equal
#define __glibcxx_want_constexpr_char_traits
#define __glibcxx_want_constexpr_string
+#define __glibcxx_want_containers_ranges
#define __glibcxx_want_erase_if
#define __glibcxx_want_nonmember_container_access
#define __glibcxx_want_string_resize_and_overwrite
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:
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 2e69af1..b39ce71 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -2939,19 +2939,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
#ifdef __cpp_lib_make_from_tuple // C++ >= 17
+ template <typename _Tp, typename _Tuple, typename _Seq
+ = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>>
+ constexpr bool __can_make_from_tuple = false;
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3528. make_from_tuple can perform (the equivalent of) a C-style cast
+ template <typename _Tp, typename _Tuple, size_t... _Idx>
+ constexpr bool __can_make_from_tuple<_Tp, _Tuple, index_sequence<_Idx...>>
+ = is_constructible_v<_Tp,
+ decltype(std::get<_Idx>(std::declval<_Tuple>()))...>;
+
template <typename _Tp, typename _Tuple, size_t... _Idx>
constexpr _Tp
__make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
- { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
+ {
+ static_assert(__can_make_from_tuple<_Tp, _Tuple, index_sequence<_Idx...>>);
+ return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...);
+ }
#if __cpp_lib_tuple_like // >= C++23
template <typename _Tp, __tuple_like _Tuple>
#else
template <typename _Tp, typename _Tuple>
#endif
- constexpr _Tp
+ constexpr auto
make_from_tuple(_Tuple&& __t)
noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
+#ifdef __cpp_concepts // >= C++20
+ -> _Tp
+ requires __can_make_from_tuple<_Tp, _Tuple>
+#else
+ -> __enable_if_t<__can_make_from_tuple<_Tp, _Tuple>, _Tp>
+#endif
{
constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
#if __has_builtin(__reference_constructs_from_temporary)
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 676cdf2..0554111 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -280,11 +280,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Forward declarations
template<typename>
- struct is_reference;
- template<typename>
- struct is_function;
- template<typename>
- struct is_void;
+ struct is_object;
template<typename>
struct remove_cv;
template<typename>
@@ -294,21 +290,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename>
struct __is_array_unknown_bounds;
+ // An object type which is not an unbounded array.
+ // It might still be an incomplete type, but if this is false_type
+ // then we can be certain it's not a complete object type.
+ template<typename _Tp>
+ using __maybe_complete_object_type
+ = __and_<is_object<_Tp>, __not_<__is_array_unknown_bounds<_Tp>>>;
+
// Helper functions that return false_type for incomplete classes,
// incomplete unions and arrays of known bound from those.
- template <typename _Tp, size_t = sizeof(_Tp)>
- constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>)
- { return {}; }
-
- template <typename _TypeIdentity,
- typename _NestedType = typename _TypeIdentity::type>
- constexpr typename __or_<
- is_reference<_NestedType>,
- is_function<_NestedType>,
- is_void<_NestedType>,
- __is_array_unknown_bounds<_NestedType>
- >::type __is_complete_or_unbounded(_TypeIdentity)
+ // More specialized overload for complete object types (returning true_type).
+ template<typename _Tp,
+ typename = __enable_if_t<__maybe_complete_object_type<_Tp>::value>,
+ size_t = sizeof(_Tp)>
+ constexpr true_type
+ __is_complete_or_unbounded(__type_identity<_Tp>)
+ { return {}; };
+
+ // Less specialized overload for reference and unknown-bound array types
+ // (returning true_type), and incomplete types (returning false_type).
+ template<typename _TypeIdentity,
+ typename _NestedType = typename _TypeIdentity::type>
+ constexpr typename __not_<__maybe_complete_object_type<_NestedType>>::type
+ __is_complete_or_unbounded(_TypeIdentity)
{ return {}; }
// __remove_cv_t (std::remove_cv_t for C++11).
@@ -1036,9 +1041,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __is_array_unknown_bounds<_Tp[]>
: public true_type
{ };
+ /// @endcond
// Destructible and constructible type properties.
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_destructible)
+ /// is_destructible
+ template<typename _Tp>
+ struct is_destructible
+ : public __bool_constant<__is_destructible(_Tp)>
+ { };
+#else
+ /// @cond undocumented
+
// In N3290 is_destructible does not say anything about function
// types and abstract types, see LWG 2049. This implementation
// describes function types as non-destructible and all complete
@@ -1090,7 +1105,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
+#endif
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_destructible)
+ /// is_nothrow_destructible
+ template<typename _Tp>
+ struct is_nothrow_destructible
+ : public __bool_constant<__is_nothrow_destructible(_Tp)>
+ { };
+#else
/// @cond undocumented
// is_nothrow_destructible requires that is_destructible is
@@ -1144,6 +1167,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
+#endif
/// @cond undocumented
template<typename _Tp, typename... _Args>
@@ -1451,6 +1475,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"template argument must be a complete class or an unbounded array");
};
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_trivially_destructible)
+ /// is_trivially_destructible
+ template<typename _Tp>
+ struct is_trivially_destructible
+ : public __bool_constant<__is_trivially_destructible(_Tp)>
+ { };
+#else
/// is_trivially_destructible
template<typename _Tp>
struct is_trivially_destructible
@@ -1460,7 +1491,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
-
+#endif
/// has_virtual_destructor
template<typename _Tp>
@@ -3212,7 +3243,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Fn, typename... _ArgTypes>
struct __is_invocable
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_invocable)
+ : __bool_constant<__is_invocable(_Fn, _ArgTypes...)>
+#else
: __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type
+#endif
{ };
template<typename _Fn, typename _Tp, typename... _Args>
@@ -3263,8 +3298,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// __is_nothrow_invocable (std::is_nothrow_invocable for C++11)
template<typename _Fn, typename... _Args>
struct __is_nothrow_invocable
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_invocable)
+ : __bool_constant<__is_nothrow_invocable(_Fn, _Args...)>
+#else
: __and_<__is_invocable<_Fn, _Args...>,
__call_is_nothrow_<_Fn, _Args...>>::type
+#endif
{ };
#pragma GCC diagnostic push
@@ -3573,8 +3612,13 @@ template <typename _Tp>
inline constexpr bool is_move_assignable_v
= __is_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>);
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_destructible)
+template <typename _Tp>
+ inline constexpr bool is_destructible_v = __is_destructible(_Tp);
+#else
template <typename _Tp>
inline constexpr bool is_destructible_v = is_destructible<_Tp>::value;
+#endif
template <typename _Tp, typename... _Args>
inline constexpr bool is_trivially_constructible_v
@@ -3601,7 +3645,11 @@ template <typename _Tp>
= __is_trivially_assignable(__add_lval_ref_t<_Tp>,
__add_rval_ref_t<_Tp>);
-#if __cpp_concepts
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_trivially_destructible)
+template <typename _Tp>
+ inline constexpr bool is_trivially_destructible_v
+ = __is_trivially_destructible(_Tp);
+#elif __cpp_concepts
template <typename _Tp>
inline constexpr bool is_trivially_destructible_v = false;
@@ -3646,9 +3694,15 @@ template <typename _Tp>
inline constexpr bool is_nothrow_move_assignable_v
= __is_nothrow_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>);
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_destructible)
+template <typename _Tp>
+ inline constexpr bool is_nothrow_destructible_v
+ = __is_nothrow_destructible(_Tp);
+#else
template <typename _Tp>
inline constexpr bool is_nothrow_destructible_v =
is_nothrow_destructible<_Tp>::value;
+#endif
template <typename _Tp>
inline constexpr bool has_virtual_destructor_v
@@ -3704,10 +3758,19 @@ template <typename _From, typename _To>
inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value;
#endif
template<typename _Fn, typename... _Args>
- inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
+ inline constexpr bool is_invocable_v
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_invocable)
+ = __is_invocable(_Fn, _Args...);
+#else
+ = is_invocable<_Fn, _Args...>::value;
+#endif
template<typename _Fn, typename... _Args>
inline constexpr bool is_nothrow_invocable_v
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_invocable)
+ = __is_nothrow_invocable(_Fn, _Args...);
+#else
= is_nothrow_invocable<_Fn, _Args...>::value;
+#endif
template<typename _Ret, typename _Fn, typename... _Args>
inline constexpr bool is_invocable_r_v
= is_invocable_r<_Ret, _Fn, _Args...>::value;
@@ -4002,7 +4065,8 @@ template<typename _Ret, typename _Fn, typename... _Args>
#ifdef __cpp_lib_is_constant_evaluated // C++ >= 20 && HAVE_IS_CONST_EVAL
/// Returns true only when called during constant evaluation.
/// @since C++20
- constexpr inline bool
+ [[__gnu__::__always_inline__]]
+ constexpr bool
is_constant_evaluated() noexcept
{
#if __cpp_if_consteval >= 202106L
diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map
index 37f2273..3ae25d7 100644
--- a/libstdc++-v3/include/std/unordered_map
+++ b/libstdc++-v3/include/std/unordered_map
@@ -49,6 +49,7 @@
#endif
#define __glibcxx_want_allocator_traits_is_always_equal
+#define __glibcxx_want_containers_ranges
#define __glibcxx_want_erase_if
#define __glibcxx_want_generic_unordered_lookup
#define __glibcxx_want_node_extract
diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set
index 4c73e5d..b561163 100644
--- a/libstdc++-v3/include/std/unordered_set
+++ b/libstdc++-v3/include/std/unordered_set
@@ -49,6 +49,7 @@
#endif
#define __glibcxx_want_allocator_traits_is_always_equal
+#define __glibcxx_want_containers_ranges
#define __glibcxx_want_erase_if
#define __glibcxx_want_generic_unordered_lookup
#define __glibcxx_want_node_extract
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index 1c15c75..8a85ccf 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -201,7 +201,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef __cpp_lib_to_underlying // C++ >= 23
/// Convert an object of enumeration type to its underlying type.
template<typename _Tp>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr underlying_type_t<_Tp>
to_underlying(_Tp __value) noexcept
{ return static_cast<underlying_type_t<_Tp>>(__value); }
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index 8bb2543..a98ffb1 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -81,6 +81,7 @@
#define __glibcxx_want_algorithm_default_value_type
#define __glibcxx_want_allocator_traits_is_always_equal
#define __glibcxx_want_constexpr_vector
+#define __glibcxx_want_containers_ranges
#define __glibcxx_want_erase_if
#define __glibcxx_want_incomplete_container_elements
#define __glibcxx_want_nonmember_container_access