aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r--libstdc++-v3/include/Makefile.am17
-rw-r--r--libstdc++-v3/include/Makefile.in20
-rw-r--r--libstdc++-v3/include/bits/align.h17
-rw-r--r--libstdc++-v3/include/bits/allocated_ptr.h96
-rw-r--r--libstdc++-v3/include/bits/atomic_base.h581
-rw-r--r--libstdc++-v3/include/bits/atomic_timed_wait.h444
-rw-r--r--libstdc++-v3/include/bits/atomic_wait.h557
-rw-r--r--libstdc++-v3/include/bits/basic_string.h61
-rw-r--r--libstdc++-v3/include/bits/basic_string.tcc3
-rw-r--r--libstdc++-v3/include/bits/binders.h237
-rw-r--r--libstdc++-v3/include/bits/boost_concept_check.h1
-rw-r--r--libstdc++-v3/include/bits/c++config13
-rw-r--r--libstdc++-v3/include/bits/char_traits.h5
-rw-r--r--libstdc++-v3/include/bits/chrono.h76
-rw-r--r--libstdc++-v3/include/bits/chrono_io.h3759
-rw-r--r--libstdc++-v3/include/bits/cow_string.h36
-rw-r--r--libstdc++-v3/include/bits/cpp_type_traits.h26
-rw-r--r--libstdc++-v3/include/bits/cpyfunc_impl.h273
-rw-r--r--libstdc++-v3/include/bits/deque.tcc13
-rw-r--r--libstdc++-v3/include/bits/formatfwd.h135
-rw-r--r--libstdc++-v3/include/bits/forward_list.h2
-rw-r--r--libstdc++-v3/include/bits/funcref_impl.h202
-rw-r--r--libstdc++-v3/include/bits/functional_hash.h9
-rw-r--r--libstdc++-v3/include/bits/funcwrap.h622
-rw-r--r--libstdc++-v3/include/bits/hashtable.h33
-rw-r--r--libstdc++-v3/include/bits/indirect.h836
-rw-r--r--libstdc++-v3/include/bits/intcmp.h120
-rw-r--r--libstdc++-v3/include/bits/ios_base.h18
-rw-r--r--libstdc++-v3/include/bits/iterator_concepts.h60
-rw-r--r--libstdc++-v3/include/bits/locale_conv.h7
-rw-r--r--libstdc++-v3/include/bits/max_size_type.h152
-rw-r--r--libstdc++-v3/include/bits/mofunc_impl.h82
-rw-r--r--libstdc++-v3/include/bits/move.h34
-rw-r--r--libstdc++-v3/include/bits/move_only_function.h218
-rw-r--r--libstdc++-v3/include/bits/ostream.h4
-rw-r--r--libstdc++-v3/include/bits/predefined_ops.h444
-rw-r--r--libstdc++-v3/include/bits/ptr_traits.h8
-rw-r--r--libstdc++-v3/include/bits/quoted_string.h23
-rw-r--r--libstdc++-v3/include/bits/random.h275
-rw-r--r--libstdc++-v3/include/bits/random.tcc137
-rw-r--r--libstdc++-v3/include/bits/ranges_algo.h1652
-rw-r--r--libstdc++-v3/include/bits/ranges_algobase.h4
-rw-r--r--libstdc++-v3/include/bits/ranges_base.h160
-rw-r--r--libstdc++-v3/include/bits/ranges_cmp.h34
-rw-r--r--libstdc++-v3/include/bits/ranges_uninitialized.h26
-rw-r--r--libstdc++-v3/include/bits/ranges_util.h31
-rw-r--r--libstdc++-v3/include/bits/refwrap.h34
-rw-r--r--libstdc++-v3/include/bits/regex.tcc49
-rw-r--r--libstdc++-v3/include/bits/regex_automaton.tcc4
-rw-r--r--libstdc++-v3/include/bits/regex_compiler.h67
-rw-r--r--libstdc++-v3/include/bits/regex_compiler.tcc2
-rw-r--r--libstdc++-v3/include/bits/regex_executor.tcc17
-rw-r--r--libstdc++-v3/include/bits/sat_arith.h14
-rw-r--r--libstdc++-v3/include/bits/semaphore_base.h358
-rw-r--r--libstdc++-v3/include/bits/shared_ptr.h58
-rw-r--r--libstdc++-v3/include/bits/shared_ptr_atomic.h57
-rw-r--r--libstdc++-v3/include/bits/shared_ptr_base.h225
-rw-r--r--libstdc++-v3/include/bits/std_abs.h9
-rw-r--r--libstdc++-v3/include/bits/std_function.h31
-rw-r--r--libstdc++-v3/include/bits/std_mutex.h26
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h604
-rw-r--r--libstdc++-v3/include/bits/stl_algobase.h102
-rw-r--r--libstdc++-v3/include/bits/stl_construct.h195
-rw-r--r--libstdc++-v3/include/bits/stl_deque.h31
-rw-r--r--libstdc++-v3/include/bits/stl_function.h52
-rw-r--r--libstdc++-v3/include/bits/stl_heap.h71
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h362
-rw-r--r--libstdc++-v3/include/bits/stl_iterator_base_funcs.h70
-rw-r--r--libstdc++-v3/include/bits/stl_iterator_base_types.h7
-rw-r--r--libstdc++-v3/include/bits/stl_map.h22
-rw-r--r--libstdc++-v3/include/bits/stl_multimap.h20
-rw-r--r--libstdc++-v3/include/bits/stl_multiset.h12
-rw-r--r--libstdc++-v3/include/bits/stl_pair.h12
-rw-r--r--libstdc++-v3/include/bits/stl_queue.h14
-rw-r--r--libstdc++-v3/include/bits/stl_set.h14
-rw-r--r--libstdc++-v3/include/bits/stl_stack.h9
-rw-r--r--libstdc++-v3/include/bits/stl_tempbuf.h2
-rw-r--r--libstdc++-v3/include/bits/stl_tree.h132
-rw-r--r--libstdc++-v3/include/bits/stl_uninitialized.h73
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h48
-rw-r--r--libstdc++-v3/include/bits/this_thread_sleep.h19
-rw-r--r--libstdc++-v3/include/bits/unicode-data.h948
-rw-r--r--libstdc++-v3/include/bits/unicode.h208
-rw-r--r--libstdc++-v3/include/bits/uniform_int_dist.h7
-rw-r--r--libstdc++-v3/include/bits/unique_ptr.h3
-rw-r--r--libstdc++-v3/include/bits/unordered_map.h58
-rw-r--r--libstdc++-v3/include/bits/unordered_set.h91
-rw-r--r--libstdc++-v3/include/bits/utility.h53
-rw-r--r--libstdc++-v3/include/bits/valarray_array.h25
-rw-r--r--libstdc++-v3/include/bits/vector.tcc116
-rw-r--r--libstdc++-v3/include/bits/version.def314
-rw-r--r--libstdc++-v3/include/bits/version.h763
-rw-r--r--libstdc++-v3/include/bits/version.tpl9
-rw-r--r--libstdc++-v3/include/c_compatibility/stdckdint.h32
-rw-r--r--libstdc++-v3/include/c_global/ccomplex2
-rw-r--r--libstdc++-v3/include/c_global/ciso64618
-rw-r--r--libstdc++-v3/include/c_global/cmath4
-rw-r--r--libstdc++-v3/include/c_global/cstdalign2
-rw-r--r--libstdc++-v3/include/c_global/cstdbool2
-rw-r--r--libstdc++-v3/include/c_global/ctgmath2
-rw-r--r--libstdc++-v3/include/debug/bitset19
-rw-r--r--libstdc++-v3/include/debug/debug.h2
-rw-r--r--libstdc++-v3/include/debug/deque33
-rw-r--r--libstdc++-v3/include/debug/formatter.h10
-rw-r--r--libstdc++-v3/include/debug/forward_list71
-rw-r--r--libstdc++-v3/include/debug/functions.h10
-rw-r--r--libstdc++-v3/include/debug/helper_functions.h4
-rw-r--r--libstdc++-v3/include/debug/inplace_vector691
-rw-r--r--libstdc++-v3/include/debug/list15
-rw-r--r--libstdc++-v3/include/debug/map.h18
-rw-r--r--libstdc++-v3/include/debug/multimap.h18
-rw-r--r--libstdc++-v3/include/debug/multiset.h10
-rw-r--r--libstdc++-v3/include/debug/safe_base.h99
-rw-r--r--libstdc++-v3/include/debug/safe_container.h38
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.h26
-rw-r--r--libstdc++-v3/include/debug/safe_local_iterator.h102
-rw-r--r--libstdc++-v3/include/debug/safe_local_iterator.tcc4
-rw-r--r--libstdc++-v3/include/debug/safe_sequence.h41
-rw-r--r--libstdc++-v3/include/debug/safe_sequence.tcc11
-rw-r--r--libstdc++-v3/include/debug/safe_unordered_base.h73
-rw-r--r--libstdc++-v3/include/debug/safe_unordered_container.h4
-rw-r--r--libstdc++-v3/include/debug/safe_unordered_container.tcc4
-rw-r--r--libstdc++-v3/include/debug/set.h10
-rw-r--r--libstdc++-v3/include/debug/unordered_map46
-rw-r--r--libstdc++-v3/include/debug/unordered_set78
-rw-r--r--libstdc++-v3/include/debug/vector26
-rw-r--r--libstdc++-v3/include/experimental/memory22
-rw-r--r--libstdc++-v3/include/experimental/numeric5
-rw-r--r--libstdc++-v3/include/ext/atomicity.h49
-rw-r--r--libstdc++-v3/include/ext/numeric_traits.h8
-rw-r--r--libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp3
-rw-r--r--libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp2
-rw-r--r--libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp31
-rw-r--r--libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp4
-rw-r--r--libstdc++-v3/include/ext/pb_ds/detail/rb_tree_map_/node.hpp8
-rw-r--r--libstdc++-v3/include/ext/pb_ds/detail/splay_tree_/node.hpp8
-rw-r--r--libstdc++-v3/include/ext/pointer.h1
-rw-r--r--libstdc++-v3/include/ext/ropeimpl.h2
-rw-r--r--libstdc++-v3/include/precompiled/extc++.h1
-rw-r--r--libstdc++-v3/include/precompiled/stdc++.h10
-rw-r--r--libstdc++-v3/include/pstl/algorithm_impl.h24
-rw-r--r--libstdc++-v3/include/pstl/glue_numeric_impl.h16
-rw-r--r--libstdc++-v3/include/pstl/memory_impl.h4
-rw-r--r--libstdc++-v3/include/pstl/numeric_impl.h40
-rw-r--r--libstdc++-v3/include/pstl/parallel_backend_tbb.h12
-rw-r--r--libstdc++-v3/include/std/algorithm1
-rw-r--r--libstdc++-v3/include/std/array2
-rw-r--r--libstdc++-v3/include/std/atomic14
-rw-r--r--libstdc++-v3/include/std/barrier199
-rw-r--r--libstdc++-v3/include/std/bit31
-rw-r--r--libstdc++-v3/include/std/bitset116
-rw-r--r--libstdc++-v3/include/std/charconv25
-rw-r--r--libstdc++-v3/include/std/chrono385
-rw-r--r--libstdc++-v3/include/std/complex41
-rw-r--r--libstdc++-v3/include/std/concepts25
-rw-r--r--libstdc++-v3/include/std/condition_variable20
-rw-r--r--libstdc++-v3/include/std/debugging77
-rw-r--r--libstdc++-v3/include/std/deque36
-rw-r--r--libstdc++-v3/include/std/expected60
-rw-r--r--libstdc++-v3/include/std/flat_map46
-rw-r--r--libstdc++-v3/include/std/flat_set28
-rw-r--r--libstdc++-v3/include/std/format2149
-rw-r--r--libstdc++-v3/include/std/functional401
-rw-r--r--libstdc++-v3/include/std/future66
-rw-r--r--libstdc++-v3/include/std/generator10
-rw-r--r--libstdc++-v3/include/std/inplace_vector1369
-rw-r--r--libstdc++-v3/include/std/istream13
-rw-r--r--libstdc++-v3/include/std/latch38
-rw-r--r--libstdc++-v3/include/std/limits5
-rw-r--r--libstdc++-v3/include/std/mdspan3399
-rw-r--r--libstdc++-v3/include/std/memory10
-rw-r--r--libstdc++-v3/include/std/mutex24
-rw-r--r--libstdc++-v3/include/std/numeric14
-rw-r--r--libstdc++-v3/include/std/optional599
-rw-r--r--libstdc++-v3/include/std/ostream19
-rw-r--r--libstdc++-v3/include/std/print286
-rw-r--r--libstdc++-v3/include/std/queue103
-rw-r--r--libstdc++-v3/include/std/random3
-rw-r--r--libstdc++-v3/include/std/ranges525
-rw-r--r--libstdc++-v3/include/std/regex1
-rw-r--r--libstdc++-v3/include/std/semaphore31
-rw-r--r--libstdc++-v3/include/std/shared_mutex94
-rw-r--r--libstdc++-v3/include/std/span38
-rw-r--r--libstdc++-v3/include/std/spanstream4
-rw-r--r--libstdc++-v3/include/std/sstream202
-rw-r--r--libstdc++-v3/include/std/stack56
-rw-r--r--libstdc++-v3/include/std/stacktrace54
-rw-r--r--libstdc++-v3/include/std/stop_token26
-rw-r--r--libstdc++-v3/include/std/string21
-rw-r--r--libstdc++-v3/include/std/string_view10
-rw-r--r--libstdc++-v3/include/std/syncstream22
-rw-r--r--libstdc++-v3/include/std/thread66
-rw-r--r--libstdc++-v3/include/std/tuple142
-rw-r--r--libstdc++-v3/include/std/type_traits610
-rw-r--r--libstdc++-v3/include/std/utility93
-rw-r--r--libstdc++-v3/include/std/valarray12
-rw-r--r--libstdc++-v3/include/std/variant36
-rw-r--r--libstdc++-v3/include/std/vector45
-rw-r--r--libstdc++-v3/include/tr2/dynamic_bitset10
199 files changed, 23218 insertions, 7249 deletions
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 537774c..847fc13 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -38,6 +38,7 @@ std_freestanding = \
${std_srcdir}/generator \
${std_srcdir}/iterator \
${std_srcdir}/limits \
+ ${std_srcdir}/mdspan \
${std_srcdir}/memory \
${std_srcdir}/numbers \
${std_srcdir}/numeric \
@@ -67,6 +68,7 @@ std_headers = \
${std_srcdir}/codecvt \
${std_srcdir}/complex \
${std_srcdir}/condition_variable \
+ ${std_srcdir}/debugging \
${std_srcdir}/deque \
${std_srcdir}/execution \
${std_srcdir}/filesystem \
@@ -76,6 +78,7 @@ std_headers = \
${std_srcdir}/forward_list \
${std_srcdir}/fstream \
${std_srcdir}/future \
+ ${std_srcdir}/inplace_vector \
${std_srcdir}/iomanip \
${std_srcdir}/ios \
${std_srcdir}/iosfwd \
@@ -131,6 +134,7 @@ bits_freestanding = \
${bits_srcdir}/enable_special_members.h \
${bits_srcdir}/functexcept.h \
${bits_srcdir}/functional_hash.h \
+ ${bits_srcdir}/intcmp.h \
${bits_srcdir}/invoke.h \
${bits_srcdir}/iterator_concepts.h \
${bits_srcdir}/max_size_type.h \
@@ -188,11 +192,13 @@ bits_headers = \
${bits_srcdir}/basic_ios.tcc \
${bits_srcdir}/basic_string.h \
${bits_srcdir}/basic_string.tcc \
+ ${bits_srcdir}/binders.h \
${bits_srcdir}/charconv.h \
${bits_srcdir}/chrono.h \
${bits_srcdir}/chrono_io.h \
${bits_srcdir}/codecvt.h \
${bits_srcdir}/cow_string.h \
+ ${bits_srcdir}/cpyfunc_impl.h \
${bits_srcdir}/deque.tcc \
${bits_srcdir}/erase_if.h \
${bits_srcdir}/formatfwd.h \
@@ -203,10 +209,13 @@ bits_headers = \
${bits_srcdir}/fs_ops.h \
${bits_srcdir}/fs_path.h \
${bits_srcdir}/fstream.tcc \
+ ${bits_srcdir}/funcref_impl.h \
+ ${bits_srcdir}/funcwrap.h \
${bits_srcdir}/gslice.h \
${bits_srcdir}/gslice_array.h \
${bits_srcdir}/hashtable.h \
${bits_srcdir}/hashtable_policy.h \
+ ${bits_srcdir}/indirect.h \
${bits_srcdir}/indirect_array.h \
${bits_srcdir}/ios_base.h \
${bits_srcdir}/istream.tcc \
@@ -222,7 +231,6 @@ bits_headers = \
${bits_srcdir}/mask_array.h \
${bits_srcdir}/memory_resource.h \
${bits_srcdir}/mofunc_impl.h \
- ${bits_srcdir}/move_only_function.h \
${bits_srcdir}/new_allocator.h \
${bits_srcdir}/node_handle.h \
${bits_srcdir}/ostream.tcc \
@@ -964,6 +972,7 @@ debug_headers = \
${debug_srcdir}/forward_list \
${debug_srcdir}/functions.h \
${debug_srcdir}/helper_functions.h \
+ ${debug_srcdir}/inplace_vector \
${debug_srcdir}/list \
${debug_srcdir}/map \
${debug_srcdir}/macros.h \
@@ -1413,11 +1422,11 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
-e "$$verbose_assert" \
< ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
- -e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
- -e 's/VERSION/_GLIBCXX_VERSION/g' \
+ -e '/PACKAGE/s,^,// ,' \
+ -e '/PACKAGE/!s/VERSION/_GLIBCXX_VERSION/g' \
-e 's/WORDS_/_GLIBCXX_WORDS_/g' \
-e 's/LT_OBJDIR/_GLIBCXX_LT_OBJDIR/g' \
- -e 's/STDC_HEADERS/_GLIBCXX_STDC_HEADERS/g' \
+ -e 's,^#.*STDC_HEADERS,// &,' \
-e 's/_DARWIN_USE_64_BIT_INODE/_GLIBCXX_DARWIN_USE_64_BIT_INODE/g' \
-e 's/_FILE_OFFSET_BITS/_GLIBCXX_FILE_OFFSET_BITS/g' \
-e 's/_LARGE_FILES/_GLIBCXX_LARGE_FILES/g' \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 7b96b22..1d6171b 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -91,8 +91,10 @@ target_triplet = @target@
subdir = include
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+ $(top_srcdir)/../config/clang-plugin.m4 \
$(top_srcdir)/../config/enable.m4 \
$(top_srcdir)/../config/futex.m4 \
+ $(top_srcdir)/../config/gcc-plugin.m4 \
$(top_srcdir)/../config/hwcaps.m4 \
$(top_srcdir)/../config/iconv.m4 \
$(top_srcdir)/../config/lead-dot.m4 \
@@ -222,6 +224,7 @@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
+LLVM_CONFIG = @LLVM_CONFIG@
LN_S = @LN_S@
LONG_DOUBLE_128_FLAGS = @LONG_DOUBLE_128_FLAGS@
LONG_DOUBLE_ALT128_COMPAT_FLAGS = @LONG_DOUBLE_ALT128_COMPAT_FLAGS@
@@ -396,6 +399,7 @@ std_freestanding = \
${std_srcdir}/generator \
${std_srcdir}/iterator \
${std_srcdir}/limits \
+ ${std_srcdir}/mdspan \
${std_srcdir}/memory \
${std_srcdir}/numbers \
${std_srcdir}/numeric \
@@ -423,6 +427,7 @@ std_freestanding = \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/codecvt \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/complex \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/condition_variable \
+@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/debugging \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/deque \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/execution \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/filesystem \
@@ -432,6 +437,7 @@ std_freestanding = \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/forward_list \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/fstream \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/future \
+@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/inplace_vector \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/iomanip \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/ios \
@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/iosfwd \
@@ -486,6 +492,7 @@ bits_freestanding = \
${bits_srcdir}/enable_special_members.h \
${bits_srcdir}/functexcept.h \
${bits_srcdir}/functional_hash.h \
+ ${bits_srcdir}/intcmp.h \
${bits_srcdir}/invoke.h \
${bits_srcdir}/iterator_concepts.h \
${bits_srcdir}/max_size_type.h \
@@ -541,11 +548,13 @@ bits_freestanding = \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/basic_ios.tcc \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/basic_string.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/basic_string.tcc \
+@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/binders.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/charconv.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/chrono.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/chrono_io.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/codecvt.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/cow_string.h \
+@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/cpyfunc_impl.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/deque.tcc \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/erase_if.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/formatfwd.h \
@@ -556,10 +565,13 @@ bits_freestanding = \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/fs_ops.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/fs_path.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/fstream.tcc \
+@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/funcref_impl.h \
+@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/funcwrap.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/gslice.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/gslice_array.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/hashtable.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/hashtable_policy.h \
+@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/indirect.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/indirect_array.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/ios_base.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/istream.tcc \
@@ -575,7 +587,6 @@ bits_freestanding = \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/mask_array.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/memory_resource.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/mofunc_impl.h \
-@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/move_only_function.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/new_allocator.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/node_handle.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/ostream.tcc \
@@ -1298,6 +1309,7 @@ debug_freestanding = \
@GLIBCXX_HOSTED_TRUE@ ${debug_srcdir}/forward_list \
@GLIBCXX_HOSTED_TRUE@ ${debug_srcdir}/functions.h \
@GLIBCXX_HOSTED_TRUE@ ${debug_srcdir}/helper_functions.h \
+@GLIBCXX_HOSTED_TRUE@ ${debug_srcdir}/inplace_vector \
@GLIBCXX_HOSTED_TRUE@ ${debug_srcdir}/list \
@GLIBCXX_HOSTED_TRUE@ ${debug_srcdir}/map \
@GLIBCXX_HOSTED_TRUE@ ${debug_srcdir}/macros.h \
@@ -1890,11 +1902,11 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
-e "$$verbose_assert" \
< ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
- -e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
- -e 's/VERSION/_GLIBCXX_VERSION/g' \
+ -e '/PACKAGE/s,^,// ,' \
+ -e '/PACKAGE/!s/VERSION/_GLIBCXX_VERSION/g' \
-e 's/WORDS_/_GLIBCXX_WORDS_/g' \
-e 's/LT_OBJDIR/_GLIBCXX_LT_OBJDIR/g' \
- -e 's/STDC_HEADERS/_GLIBCXX_STDC_HEADERS/g' \
+ -e 's,^#.*STDC_HEADERS,// &,' \
-e 's/_DARWIN_USE_64_BIT_INODE/_GLIBCXX_DARWIN_USE_64_BIT_INODE/g' \
-e 's/_FILE_OFFSET_BITS/_GLIBCXX_FILE_OFFSET_BITS/g' \
-e 's/_LARGE_FILES/_GLIBCXX_LARGE_FILES/g' \
diff --git a/libstdc++-v3/include/bits/align.h b/libstdc++-v3/include/bits/align.h
index 2b40c37..6a85244 100644
--- a/libstdc++-v3/include/bits/align.h
+++ b/libstdc++-v3/include/bits/align.h
@@ -102,6 +102,23 @@ align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept
}
#endif // __glibcxx_assume_aligned
+#ifdef __glibcxx_is_sufficiently_aligned // C++ >= 26
+ /** @brief Is `__ptr` aligned to an _Align byte boundary?
+ *
+ * @tparam _Align An alignment value
+ * @tparam _Tp An object type
+ *
+ * C++26 20.2.5 [ptr.align]
+ *
+ * @ingroup memory
+ */
+ template<size_t _Align, class _Tp>
+ [[nodiscard,__gnu__::__always_inline__]]
+ inline bool
+ is_sufficiently_aligned(_Tp* __ptr)
+ { return reinterpret_cast<__UINTPTR_TYPE__>(__ptr) % _Align == 0; }
+#endif // __glibcxx_is_sufficiently_aligned
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/bits/allocated_ptr.h b/libstdc++-v3/include/bits/allocated_ptr.h
index 0b2b6fe..aa5355f 100644
--- a/libstdc++-v3/include/bits/allocated_ptr.h
+++ b/libstdc++-v3/include/bits/allocated_ptr.h
@@ -36,6 +36,7 @@
# include <type_traits>
# include <bits/ptr_traits.h>
# include <bits/alloc_traits.h>
+# include <bits/utility.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -136,6 +137,101 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return { std::__allocate_guarded(__a) };
}
+ // An RAII type that acquires memory from an allocator.
+ // N.B. 'scoped' here in in the RAII sense, not the scoped allocator model,
+ // so this has nothing to do with `std::scoped_allocator_adaptor`.
+ // This class can be used to simplify the common pattern:
+ //
+ // auto ptr = alloc.allocate(1);
+ // try {
+ // std::construct_at(std::to_address(ptr), args);
+ // m_ptr = ptr;
+ // } catch (...) {
+ // alloc.deallocate(ptr, 1);
+ // throw;
+ // }
+ //
+ // Instead you can do:
+ //
+ // _Scoped_allocation sa(alloc);
+ // m_ptr = std::construct_at(sa.get(), args);
+ // (void) sa.release();
+ //
+ // Or even simpler:
+ //
+ // _Scoped_allocation sa(alloc, std::in_place, args);
+ // m_ptr = sa.release();
+ //
+ template<typename _Alloc>
+ struct _Scoped_allocation
+ {
+ using value_type = typename allocator_traits<_Alloc>::value_type;
+ using pointer = typename allocator_traits<_Alloc>::pointer;
+
+ // Use `a` to allocate memory for `n` objects.
+ constexpr explicit
+ _Scoped_allocation(const _Alloc& __a, size_t __n = 1)
+ : _M_a(__a), _M_n(__n), _M_p(_M_a.allocate(__n))
+ { }
+
+#if __glibcxx_optional >= 201606L
+ // Allocate memory for a single object and if that succeeds,
+ // construct an object using args.
+ //
+ // Does not do uses-allocator construction; don't use if you need that.
+ //
+ // CAUTION: the destructor will *not* destroy this object, it will only
+ // free the memory. That means the following pattern is unsafe:
+ //
+ // _Scoped_allocation sa(alloc, in_place, args);
+ // potentially_throwing_operations();
+ // return sa.release();
+ //
+ // If the middle operation throws, the object will not be destroyed.
+ template<typename... _Args>
+ constexpr explicit
+ _Scoped_allocation(const _Alloc& __a, in_place_t, _Args&&... __args)
+ : _Scoped_allocation(__a, 1)
+ {
+ // The target constructor has completed, so if the next line throws,
+ // the destructor will deallocate the memory.
+ allocator_traits<_Alloc>::construct(_M_a, get(),
+ std::forward<_Args>(__args)...);
+ }
+#endif
+
+ _GLIBCXX20_CONSTEXPR
+ ~_Scoped_allocation()
+ {
+ if (_M_p) [[__unlikely__]]
+ _M_a.deallocate(_M_p, _M_n);
+ }
+
+ _Scoped_allocation(_Scoped_allocation&&) = delete;
+
+ constexpr _Alloc
+ get_allocator() const noexcept { return _M_a; }
+
+ constexpr value_type*
+ get() const noexcept
+ { return std::__to_address(_M_p); }
+
+ [[__nodiscard__]]
+ constexpr pointer
+ release() noexcept { return std::__exchange(_M_p, nullptr); }
+
+ private:
+ [[__no_unique_address__]] _Alloc _M_a;
+ size_t _M_n;
+ pointer _M_p;
+ };
+
+#if __glibcxx_optional >= 201606L && __cpp_deduction_guides >= 201606L
+ template<typename _Alloc, typename... _Args>
+ _Scoped_allocation(_Alloc, in_place_t, _Args...)
+ -> _Scoped_allocation<_Alloc>;
+#endif
+
/// @endcond
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index 92d1269..90b8df5 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -1508,211 +1508,153 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
#undef _GLIBCXX20_INIT
- template<typename _Tp,
- bool = is_integral_v<_Tp> && !is_same_v<_Tp, bool>,
- bool = is_floating_point_v<_Tp>>
- struct __atomic_ref;
+ // __atomic_ref_base<const _Tp> provides the common APIs for const and
+ // non-const types,
+ // __atomic_ref_base<_Tp> inherits from __atomic_ref_base<const _Tp>,
+ // and provides the common APIs implementing constraints in [atomic.ref].
+ // __atomic_ref<_Tp> inherits from __atomic_ref_base<_Tp> (const or non-const)
+ // adds type-specific mutating APIs.
+ // atomic_ref inherits from __atomic_ref;
+
+ template<typename _Tp>
+ struct __atomic_ref_base;
- // base class for non-integral, non-floating-point, non-pointer types
template<typename _Tp>
- struct __atomic_ref<_Tp, false, false>
+ struct __atomic_ref_base<const _Tp>
{
- static_assert(is_trivially_copyable_v<_Tp>);
+ private:
+ using _Vt = remove_cv_t<_Tp>;
+
+ static consteval bool
+ _S_is_always_lock_free()
+ {
+ if constexpr (is_pointer_v<_Vt>)
+ return ATOMIC_POINTER_LOCK_FREE == 2;
+ else
+ return __atomic_always_lock_free(sizeof(_Vt), 0);
+ }
- // 1/2/4/8/16-byte types must be aligned to at least their size.
- static constexpr int _S_min_alignment
- = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16
- ? 0 : sizeof(_Tp);
+ static consteval int
+ _S_required_alignment()
+ {
+ if constexpr (is_floating_point_v<_Vt> || is_pointer_v<_Vt>)
+ return __alignof__(_Vt);
+ else if constexpr ((sizeof(_Vt) & (sizeof(_Vt) - 1)) || sizeof(_Vt) > 16)
+ return alignof(_Vt);
+ else
+ // 1/2/4/8/16-byte types, including integral types,
+ // must be aligned to at least their size.
+ return (sizeof(_Vt) > alignof(_Vt)) ? sizeof(_Vt) : alignof(_Vt);
+ }
public:
- using value_type = _Tp;
+ using value_type = _Vt;
+ static_assert(is_trivially_copyable_v<value_type>);
- static constexpr bool is_always_lock_free
- = __atomic_always_lock_free(sizeof(_Tp), 0);
+ static constexpr bool is_always_lock_free = _S_is_always_lock_free();
+ static_assert(is_always_lock_free || !is_volatile_v<_Tp>,
+ "atomic operations on volatile T must be lock-free");
- static constexpr size_t required_alignment
- = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp);
+ static constexpr size_t required_alignment = _S_required_alignment();
- __atomic_ref& operator=(const __atomic_ref&) = delete;
+ __atomic_ref_base() = delete;
+ __atomic_ref_base& operator=(const __atomic_ref_base&) = delete;
explicit
- __atomic_ref(_Tp& __t) : _M_ptr(std::__addressof(__t))
+ __atomic_ref_base(const _Tp& __t)
+ : _M_ptr(const_cast<_Tp*>(std::addressof(__t)))
{
__glibcxx_assert(((__UINTPTR_TYPE__)_M_ptr % required_alignment) == 0);
}
- __atomic_ref(const __atomic_ref&) noexcept = default;
-
- _Tp
- operator=(_Tp __t) const noexcept
- {
- this->store(__t);
- return __t;
- }
+ __atomic_ref_base(const __atomic_ref_base&) noexcept = default;
- operator _Tp() const noexcept { return this->load(); }
+ operator value_type() const noexcept { return this->load(); }
bool
is_lock_free() const noexcept
{ return __atomic_impl::is_lock_free<sizeof(_Tp), required_alignment>(); }
- void
- store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept
- { __atomic_impl::store(_M_ptr, __t, __m); }
-
- _Tp
+ value_type
load(memory_order __m = memory_order_seq_cst) const noexcept
{ return __atomic_impl::load(_M_ptr, __m); }
- _Tp
- exchange(_Tp __desired, memory_order __m = memory_order_seq_cst)
- const noexcept
- { return __atomic_impl::exchange(_M_ptr, __desired, __m); }
-
- bool
- compare_exchange_weak(_Tp& __expected, _Tp __desired,
- memory_order __success,
- memory_order __failure) const noexcept
- {
- return __atomic_impl::compare_exchange_weak<true>(
- _M_ptr, __expected, __desired, __success, __failure);
- }
-
- bool
- compare_exchange_strong(_Tp& __expected, _Tp __desired,
- memory_order __success,
- memory_order __failure) const noexcept
- {
- return __atomic_impl::compare_exchange_strong<true>(
- _M_ptr, __expected, __desired, __success, __failure);
- }
-
- bool
- compare_exchange_weak(_Tp& __expected, _Tp __desired,
- memory_order __order = memory_order_seq_cst)
- const noexcept
- {
- return compare_exchange_weak(__expected, __desired, __order,
- __cmpexch_failure_order(__order));
- }
-
- bool
- compare_exchange_strong(_Tp& __expected, _Tp __desired,
- memory_order __order = memory_order_seq_cst)
- const noexcept
- {
- return compare_exchange_strong(__expected, __desired, __order,
- __cmpexch_failure_order(__order));
- }
-
#if __glibcxx_atomic_wait
_GLIBCXX_ALWAYS_INLINE void
- wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
- { __atomic_impl::wait(_M_ptr, __old, __m); }
-
- // TODO add const volatile overload
-
- _GLIBCXX_ALWAYS_INLINE void
- notify_one() const noexcept
- { __atomic_impl::notify_one(_M_ptr); }
-
- // TODO add const volatile overload
-
- _GLIBCXX_ALWAYS_INLINE void
- notify_all() const noexcept
- { __atomic_impl::notify_all(_M_ptr); }
-
- // TODO add const volatile overload
+ wait(value_type __old, memory_order __m = memory_order_seq_cst) const noexcept
+ {
+ // TODO remove when volatile is supported
+ static_assert(!is_volatile_v<_Tp>,
+ "atomic waits on volatile are not supported");
+ __atomic_impl::wait(_M_ptr, __old, __m);
+ }
#endif // __glibcxx_atomic_wait
- private:
+#if __glibcxx_atomic_ref >= 202411L
+ _GLIBCXX_ALWAYS_INLINE constexpr const _Tp*
+ address() const noexcept
+ { return _M_ptr; }
+#endif // __glibcxx_atomic_ref >= 202411L
+
+ protected:
_Tp* _M_ptr;
};
- // base class for atomic_ref<integral-type>
template<typename _Tp>
- struct __atomic_ref<_Tp, true, false>
+ struct __atomic_ref_base
+ : __atomic_ref_base<const _Tp>
{
- static_assert(is_integral_v<_Tp>);
-
- public:
- using value_type = _Tp;
- using difference_type = value_type;
-
- static constexpr bool is_always_lock_free
- = __atomic_always_lock_free(sizeof(_Tp), 0);
-
- static constexpr size_t required_alignment
- = sizeof(_Tp) > alignof(_Tp) ? sizeof(_Tp) : alignof(_Tp);
-
- __atomic_ref() = delete;
- __atomic_ref& operator=(const __atomic_ref&) = delete;
+ using value_type = typename __atomic_ref_base<const _Tp>::value_type;
explicit
- __atomic_ref(_Tp& __t) : _M_ptr(&__t)
- {
- __glibcxx_assert(((__UINTPTR_TYPE__)_M_ptr % required_alignment) == 0);
- }
-
- __atomic_ref(const __atomic_ref&) noexcept = default;
+ __atomic_ref_base(_Tp& __t) : __atomic_ref_base<const _Tp>(__t)
+ { }
- _Tp
- operator=(_Tp __t) const noexcept
+ value_type
+ operator=(value_type __t) const noexcept
{
this->store(__t);
return __t;
}
- operator _Tp() const noexcept { return this->load(); }
-
- bool
- is_lock_free() const noexcept
- {
- return __atomic_impl::is_lock_free<sizeof(_Tp), required_alignment>();
- }
-
void
- store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept
- { __atomic_impl::store(_M_ptr, __t, __m); }
+ store(value_type __t, memory_order __m = memory_order_seq_cst) const noexcept
+ { __atomic_impl::store(this->_M_ptr, __t, __m); }
- _Tp
- load(memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::load(_M_ptr, __m); }
-
- _Tp
- exchange(_Tp __desired,
- memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::exchange(_M_ptr, __desired, __m); }
+ value_type
+ exchange(value_type __desired, memory_order __m = memory_order_seq_cst)
+ const noexcept
+ { return __atomic_impl::exchange(this->_M_ptr, __desired, __m); }
bool
- compare_exchange_weak(_Tp& __expected, _Tp __desired,
+ compare_exchange_weak(value_type& __expected, value_type __desired,
memory_order __success,
memory_order __failure) const noexcept
{
return __atomic_impl::compare_exchange_weak<true>(
- _M_ptr, __expected, __desired, __success, __failure);
+ this->_M_ptr, __expected, __desired, __success, __failure);
}
bool
- compare_exchange_strong(_Tp& __expected, _Tp __desired,
- memory_order __success,
- memory_order __failure) const noexcept
+ compare_exchange_strong(value_type& __expected, value_type __desired,
+ memory_order __success,
+ memory_order __failure) const noexcept
{
return __atomic_impl::compare_exchange_strong<true>(
- _M_ptr, __expected, __desired, __success, __failure);
+ this->_M_ptr, __expected, __desired, __success, __failure);
}
bool
- compare_exchange_weak(_Tp& __expected, _Tp __desired,
+ compare_exchange_weak(value_type& __expected, value_type __desired,
memory_order __order = memory_order_seq_cst)
const noexcept
{
return compare_exchange_weak(__expected, __desired, __order,
- __cmpexch_failure_order(__order));
+ __cmpexch_failure_order(__order));
}
bool
- compare_exchange_strong(_Tp& __expected, _Tp __desired,
+ compare_exchange_strong(value_type& __expected, value_type __desired,
memory_order __order = memory_order_seq_cst)
const noexcept
{
@@ -1722,48 +1664,88 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __glibcxx_atomic_wait
_GLIBCXX_ALWAYS_INLINE void
- wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
- { __atomic_impl::wait(_M_ptr, __old, __m); }
-
- // TODO add const volatile overload
-
- _GLIBCXX_ALWAYS_INLINE void
notify_one() const noexcept
- { __atomic_impl::notify_one(_M_ptr); }
-
- // TODO add const volatile overload
+ {
+ // TODO remove when volatile is supported
+ static_assert(!is_volatile_v<_Tp>,
+ "atomic waits on volatile are not supported");
+ __atomic_impl::notify_one(this->_M_ptr);
+ }
_GLIBCXX_ALWAYS_INLINE void
notify_all() const noexcept
- { __atomic_impl::notify_all(_M_ptr); }
-
- // TODO add const volatile overload
+ {
+ // TODO remove when volatile is supported
+ static_assert(!is_volatile_v<_Tp>,
+ "atomic waits on volatile are not supported");
+ __atomic_impl::notify_all(this->_M_ptr);
+ }
#endif // __glibcxx_atomic_wait
+#if __glibcxx_atomic_ref >= 202411L
+ _GLIBCXX_ALWAYS_INLINE constexpr _Tp*
+ address() const noexcept
+ { return this->_M_ptr; }
+#endif // __glibcxx_atomic_ref >= 202411L
+ };
+
+ template<typename _Tp,
+ bool = is_integral_v<_Tp> && !is_same_v<remove_cv_t<_Tp>, bool>,
+ bool = is_floating_point_v<_Tp>,
+ bool = is_pointer_v<_Tp>>
+ struct __atomic_ref;
+
+ // base class for non-integral, non-floating-point, non-pointer types
+ template<typename _Tp>
+ struct __atomic_ref<_Tp, false, false, false>
+ : __atomic_ref_base<_Tp>
+ {
+ using __atomic_ref_base<_Tp>::__atomic_ref_base;
+ using __atomic_ref_base<_Tp>::operator=;
+ };
+
+ template<typename _Tp>
+ struct __atomic_ref<const _Tp, false, false, false>
+ : __atomic_ref_base<const _Tp>
+ {
+ using __atomic_ref_base<const _Tp>::__atomic_ref_base;
+ };
+
+ // base class for atomic_ref<integral-type>
+ template<typename _Tp>
+ struct __atomic_ref<_Tp, true, false, false>
+ : __atomic_ref_base<_Tp>
+ {
+ using value_type = typename __atomic_ref_base<_Tp>::value_type;
+ using difference_type = value_type;
+
+ using __atomic_ref_base<_Tp>::__atomic_ref_base;
+ using __atomic_ref_base<_Tp>::operator=;
+
value_type
fetch_add(value_type __i,
memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::fetch_add(_M_ptr, __i, __m); }
+ { return __atomic_impl::fetch_add(this->_M_ptr, __i, __m); }
value_type
fetch_sub(value_type __i,
memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::fetch_sub(_M_ptr, __i, __m); }
+ { return __atomic_impl::fetch_sub(this->_M_ptr, __i, __m); }
value_type
fetch_and(value_type __i,
memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::fetch_and(_M_ptr, __i, __m); }
+ { return __atomic_impl::fetch_and(this->_M_ptr, __i, __m); }
value_type
fetch_or(value_type __i,
memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::fetch_or(_M_ptr, __i, __m); }
+ { return __atomic_impl::fetch_or(this->_M_ptr, __i, __m); }
value_type
fetch_xor(value_type __i,
memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::fetch_xor(_M_ptr, __i, __m); }
+ { return __atomic_impl::fetch_xor(this->_M_ptr, __i, __m); }
_GLIBCXX_ALWAYS_INLINE value_type
operator++(int) const noexcept
@@ -1775,284 +1757,98 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
value_type
operator++() const noexcept
- { return __atomic_impl::__add_fetch(_M_ptr, value_type(1)); }
+ { return __atomic_impl::__add_fetch(this->_M_ptr, value_type(1)); }
value_type
operator--() const noexcept
- { return __atomic_impl::__sub_fetch(_M_ptr, value_type(1)); }
+ { return __atomic_impl::__sub_fetch(this->_M_ptr, value_type(1)); }
value_type
operator+=(value_type __i) const noexcept
- { return __atomic_impl::__add_fetch(_M_ptr, __i); }
+ { return __atomic_impl::__add_fetch(this->_M_ptr, __i); }
value_type
operator-=(value_type __i) const noexcept
- { return __atomic_impl::__sub_fetch(_M_ptr, __i); }
+ { return __atomic_impl::__sub_fetch(this->_M_ptr, __i); }
value_type
operator&=(value_type __i) const noexcept
- { return __atomic_impl::__and_fetch(_M_ptr, __i); }
+ { return __atomic_impl::__and_fetch(this->_M_ptr, __i); }
value_type
operator|=(value_type __i) const noexcept
- { return __atomic_impl::__or_fetch(_M_ptr, __i); }
+ { return __atomic_impl::__or_fetch(this->_M_ptr, __i); }
value_type
operator^=(value_type __i) const noexcept
- { return __atomic_impl::__xor_fetch(_M_ptr, __i); }
+ { return __atomic_impl::__xor_fetch(this->_M_ptr, __i); }
+ };
- private:
- _Tp* _M_ptr;
+ template<typename _Tp>
+ struct __atomic_ref<const _Tp, true, false, false>
+ : __atomic_ref_base<const _Tp>
+ {
+ using difference_type = typename __atomic_ref_base<const _Tp>::value_type;
+ using __atomic_ref_base<const _Tp>::__atomic_ref_base;
};
// base class for atomic_ref<floating-point-type>
template<typename _Fp>
- struct __atomic_ref<_Fp, false, true>
+ struct __atomic_ref<_Fp, false, true, false>
+ : __atomic_ref_base<_Fp>
{
- static_assert(is_floating_point_v<_Fp>);
-
- public:
- using value_type = _Fp;
+ using value_type = typename __atomic_ref_base<_Fp>::value_type;
using difference_type = value_type;
- static constexpr bool is_always_lock_free
- = __atomic_always_lock_free(sizeof(_Fp), 0);
-
- static constexpr size_t required_alignment = __alignof__(_Fp);
-
- __atomic_ref() = delete;
- __atomic_ref& operator=(const __atomic_ref&) = delete;
-
- explicit
- __atomic_ref(_Fp& __t) : _M_ptr(&__t)
- {
- __glibcxx_assert(((__UINTPTR_TYPE__)_M_ptr % required_alignment) == 0);
- }
-
- __atomic_ref(const __atomic_ref&) noexcept = default;
-
- _Fp
- operator=(_Fp __t) const noexcept
- {
- this->store(__t);
- return __t;
- }
-
- operator _Fp() const noexcept { return this->load(); }
-
- bool
- is_lock_free() const noexcept
- {
- return __atomic_impl::is_lock_free<sizeof(_Fp), required_alignment>();
- }
-
- void
- store(_Fp __t, memory_order __m = memory_order_seq_cst) const noexcept
- { __atomic_impl::store(_M_ptr, __t, __m); }
-
- _Fp
- load(memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::load(_M_ptr, __m); }
-
- _Fp
- exchange(_Fp __desired,
- memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::exchange(_M_ptr, __desired, __m); }
-
- bool
- compare_exchange_weak(_Fp& __expected, _Fp __desired,
- memory_order __success,
- memory_order __failure) const noexcept
- {
- return __atomic_impl::compare_exchange_weak<true>(
- _M_ptr, __expected, __desired, __success, __failure);
- }
-
- bool
- compare_exchange_strong(_Fp& __expected, _Fp __desired,
- memory_order __success,
- memory_order __failure) const noexcept
- {
- return __atomic_impl::compare_exchange_strong<true>(
- _M_ptr, __expected, __desired, __success, __failure);
- }
-
- bool
- compare_exchange_weak(_Fp& __expected, _Fp __desired,
- memory_order __order = memory_order_seq_cst)
- const noexcept
- {
- return compare_exchange_weak(__expected, __desired, __order,
- __cmpexch_failure_order(__order));
- }
-
- bool
- compare_exchange_strong(_Fp& __expected, _Fp __desired,
- memory_order __order = memory_order_seq_cst)
- const noexcept
- {
- return compare_exchange_strong(__expected, __desired, __order,
- __cmpexch_failure_order(__order));
- }
-
-#if __glibcxx_atomic_wait
- _GLIBCXX_ALWAYS_INLINE void
- wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept
- { __atomic_impl::wait(_M_ptr, __old, __m); }
-
- // TODO add const volatile overload
-
- _GLIBCXX_ALWAYS_INLINE void
- notify_one() const noexcept
- { __atomic_impl::notify_one(_M_ptr); }
-
- // TODO add const volatile overload
-
- _GLIBCXX_ALWAYS_INLINE void
- notify_all() const noexcept
- { __atomic_impl::notify_all(_M_ptr); }
-
- // TODO add const volatile overload
-#endif // __glibcxx_atomic_wait
+ using __atomic_ref_base<_Fp>::__atomic_ref_base;
+ using __atomic_ref_base<_Fp>::operator=;
value_type
fetch_add(value_type __i,
memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::__fetch_add_flt(_M_ptr, __i, __m); }
+ { return __atomic_impl::__fetch_add_flt(this->_M_ptr, __i, __m); }
value_type
fetch_sub(value_type __i,
memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::__fetch_sub_flt(_M_ptr, __i, __m); }
+ { return __atomic_impl::__fetch_sub_flt(this->_M_ptr, __i, __m); }
value_type
operator+=(value_type __i) const noexcept
- { return __atomic_impl::__add_fetch_flt(_M_ptr, __i); }
+ { return __atomic_impl::__add_fetch_flt(this->_M_ptr, __i); }
value_type
operator-=(value_type __i) const noexcept
- { return __atomic_impl::__sub_fetch_flt(_M_ptr, __i); }
+ { return __atomic_impl::__sub_fetch_flt(this->_M_ptr, __i); }
+ };
- private:
- _Fp* _M_ptr;
+ template<typename _Fp>
+ struct __atomic_ref<const _Fp, false, true, false>
+ : __atomic_ref_base<const _Fp>
+ {
+ using difference_type = typename __atomic_ref_base<const _Fp>::value_type;
+ using __atomic_ref_base<const _Fp>::__atomic_ref_base;
};
// base class for atomic_ref<pointer-type>
- template<typename _Tp>
- struct __atomic_ref<_Tp*, false, false>
+ template<typename _Pt>
+ struct __atomic_ref<_Pt, false, false, true>
+ : __atomic_ref_base<_Pt>
{
- public:
- using value_type = _Tp*;
+ using value_type = typename __atomic_ref_base<_Pt>::value_type;
using difference_type = ptrdiff_t;
- static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2;
-
- static constexpr size_t required_alignment = __alignof__(_Tp*);
-
- __atomic_ref() = delete;
- __atomic_ref& operator=(const __atomic_ref&) = delete;
-
- explicit
- __atomic_ref(_Tp*& __t) : _M_ptr(std::__addressof(__t))
- {
- __glibcxx_assert(((__UINTPTR_TYPE__)_M_ptr % required_alignment) == 0);
- }
-
- __atomic_ref(const __atomic_ref&) noexcept = default;
-
- _Tp*
- operator=(_Tp* __t) const noexcept
- {
- this->store(__t);
- return __t;
- }
-
- operator _Tp*() const noexcept { return this->load(); }
-
- bool
- is_lock_free() const noexcept
- {
- return __atomic_impl::is_lock_free<sizeof(_Tp*), required_alignment>();
- }
-
- void
- store(_Tp* __t, memory_order __m = memory_order_seq_cst) const noexcept
- { __atomic_impl::store(_M_ptr, __t, __m); }
-
- _Tp*
- load(memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::load(_M_ptr, __m); }
-
- _Tp*
- exchange(_Tp* __desired,
- memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::exchange(_M_ptr, __desired, __m); }
-
- bool
- compare_exchange_weak(_Tp*& __expected, _Tp* __desired,
- memory_order __success,
- memory_order __failure) const noexcept
- {
- return __atomic_impl::compare_exchange_weak<true>(
- _M_ptr, __expected, __desired, __success, __failure);
- }
-
- bool
- compare_exchange_strong(_Tp*& __expected, _Tp* __desired,
- memory_order __success,
- memory_order __failure) const noexcept
- {
- return __atomic_impl::compare_exchange_strong<true>(
- _M_ptr, __expected, __desired, __success, __failure);
- }
-
- bool
- compare_exchange_weak(_Tp*& __expected, _Tp* __desired,
- memory_order __order = memory_order_seq_cst)
- const noexcept
- {
- return compare_exchange_weak(__expected, __desired, __order,
- __cmpexch_failure_order(__order));
- }
-
- bool
- compare_exchange_strong(_Tp*& __expected, _Tp* __desired,
- memory_order __order = memory_order_seq_cst)
- const noexcept
- {
- return compare_exchange_strong(__expected, __desired, __order,
- __cmpexch_failure_order(__order));
- }
-
-#if __glibcxx_atomic_wait
- _GLIBCXX_ALWAYS_INLINE void
- wait(_Tp* __old, memory_order __m = memory_order_seq_cst) const noexcept
- { __atomic_impl::wait(_M_ptr, __old, __m); }
-
- // TODO add const volatile overload
-
- _GLIBCXX_ALWAYS_INLINE void
- notify_one() const noexcept
- { __atomic_impl::notify_one(_M_ptr); }
-
- // TODO add const volatile overload
-
- _GLIBCXX_ALWAYS_INLINE void
- notify_all() const noexcept
- { __atomic_impl::notify_all(_M_ptr); }
-
- // TODO add const volatile overload
-#endif // __glibcxx_atomic_wait
-
+ using __atomic_ref_base<_Pt>::__atomic_ref_base;
+ using __atomic_ref_base<_Pt>::operator=;
_GLIBCXX_ALWAYS_INLINE value_type
fetch_add(difference_type __d,
memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::fetch_add(_M_ptr, _S_type_size(__d), __m); }
+ { return __atomic_impl::fetch_add(this->_M_ptr, _S_type_size(__d), __m); }
_GLIBCXX_ALWAYS_INLINE value_type
fetch_sub(difference_type __d,
memory_order __m = memory_order_seq_cst) const noexcept
- { return __atomic_impl::fetch_sub(_M_ptr, _S_type_size(__d), __m); }
+ { return __atomic_impl::fetch_sub(this->_M_ptr, _S_type_size(__d), __m); }
value_type
operator++(int) const noexcept
@@ -2065,36 +1861,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
value_type
operator++() const noexcept
{
- return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(1));
+ return __atomic_impl::__add_fetch(this->_M_ptr, _S_type_size(1));
}
value_type
operator--() const noexcept
{
- return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(1));
+ return __atomic_impl::__sub_fetch(this->_M_ptr, _S_type_size(1));
}
value_type
operator+=(difference_type __d) const noexcept
{
- return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(__d));
+ return __atomic_impl::__add_fetch(this->_M_ptr, _S_type_size(__d));
}
value_type
operator-=(difference_type __d) const noexcept
{
- return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(__d));
+ return __atomic_impl::__sub_fetch(this->_M_ptr, _S_type_size(__d));
}
private:
static constexpr ptrdiff_t
_S_type_size(ptrdiff_t __d) noexcept
{
- static_assert(is_object_v<_Tp>);
- return __d * sizeof(_Tp);
+ using _Et = remove_pointer_t<value_type>;
+ static_assert(is_object_v<_Et>);
+ return __d * sizeof(_Et);
}
+ };
- _Tp** _M_ptr;
+ template<typename _Pt>
+ struct __atomic_ref<const _Pt, false, false, true>
+ : __atomic_ref_base<const _Pt>
+ {
+ using difference_type = ptrdiff_t;
+ using __atomic_ref_base<const _Pt>::__atomic_ref_base;
};
#endif // C++2a
diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 9a6ac95..3c3aa2c 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -37,7 +37,6 @@
#include <bits/atomic_wait.h>
#if __glibcxx_atomic_wait
-#include <bits/functional_hash.h>
#include <bits/this_thread_sleep.h>
#include <bits/chrono.h>
@@ -70,383 +69,162 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Dur>& __atime) noexcept
{
using __w_dur = typename __wait_clock_t::duration;
- return chrono::ceil<__w_dur>(__atime);
- }
-
-#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
-#define _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT
- // returns true if wait ended before timeout
- template<typename _Dur>
- bool
- __platform_wait_until_impl(const __platform_wait_t* __addr,
- __platform_wait_t __old,
- const chrono::time_point<__wait_clock_t, _Dur>&
- __atime) noexcept
- {
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
-
- struct timespec __rt =
- {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
-
- auto __e = syscall (SYS_futex, __addr,
- static_cast<int>(__futex_wait_flags::
- __wait_bitset_private),
- __old, &__rt, nullptr,
- static_cast<int>(__futex_wait_flags::
- __bitset_match_any));
-
- if (__e)
- {
- if (errno == ETIMEDOUT)
- return false;
- if (errno != EINTR && errno != EAGAIN)
- __throw_system_error(errno);
- }
- return true;
- }
-
- // returns true if wait ended before timeout
- template<typename _Clock, typename _Dur>
- bool
- __platform_wait_until(const __platform_wait_t* __addr, __platform_wait_t __old,
- const chrono::time_point<_Clock, _Dur>& __atime)
- {
- if constexpr (is_same_v<__wait_clock_t, _Clock>)
- {
- return __platform_wait_until_impl(__addr, __old, __atime);
- }
+ if constexpr (is_same_v<__w_dur, _Dur>)
+ return __atime;
else
- {
- if (!__platform_wait_until_impl(__addr, __old,
- __to_wait_clock(__atime)))
- {
- // We got a timeout when measured against __clock_t but
- // we need to check against the caller-supplied clock
- // to tell whether we should return a timeout.
- if (_Clock::now() < __atime)
- return true;
- }
- return false;
- }
+ return chrono::ceil<__w_dur>(__atime);
}
-#else
-// define _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT and implement __platform_wait_until()
-// if there is a more efficient primitive supported by the platform
-// (e.g. __ulock_wait())which is better than pthread_cond_clockwait
-#endif // ! PLATFORM_TIMED_WAIT
-
-#ifdef _GLIBCXX_HAS_GTHREADS
- // Returns true if wait ended before timeout.
- // _Clock must be either steady_clock or system_clock.
- template<typename _Clock, typename _Dur>
- bool
- __cond_wait_until_impl(__condvar& __cv, mutex& __mx,
- const chrono::time_point<_Clock, _Dur>& __atime)
- {
- static_assert(std::__is_one_of<_Clock, chrono::steady_clock,
- chrono::system_clock>::value);
-
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
- __gthread_time_t __ts =
- {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
+ // This uses a nanoseconds duration for the timeout argument.
+ // For __abi_version=0 that is the time since the steady_clock's epoch.
+ // It's possible that in future we will add new __wait_flags constants
+ // to indicate that the timeout is the time since the system_clock epoch,
+ // or is a relative timeout not an absolute time.
+ __wait_result_type
+ __wait_until_impl(const void* __addr, __wait_args_base& __args,
+ const chrono::nanoseconds& __timeout);
-#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
- if constexpr (is_same_v<chrono::steady_clock, _Clock>)
- __cv.wait_until(__mx, CLOCK_MONOTONIC, __ts);
- else
-#endif
- __cv.wait_until(__mx, __ts);
- return _Clock::now() < __atime;
- }
-
- // returns true if wait ended before timeout
template<typename _Clock, typename _Dur>
- bool
- __cond_wait_until(__condvar& __cv, mutex& __mx,
- const chrono::time_point<_Clock, _Dur>& __atime)
+ __wait_result_type
+ __wait_until(const void* __addr, __wait_args_base& __args,
+ const chrono::time_point<_Clock, _Dur>& __atime) noexcept
{
-#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
- if constexpr (is_same_v<_Clock, chrono::steady_clock>)
- return __detail::__cond_wait_until_impl(__cv, __mx, __atime);
- else
-#endif
- if constexpr (is_same_v<_Clock, chrono::system_clock>)
- return __detail::__cond_wait_until_impl(__cv, __mx, __atime);
- else
- {
- if (__cond_wait_until_impl(__cv, __mx,
- __to_wait_clock(__atime)))
- {
- // We got a timeout when measured against __clock_t but
- // we need to check against the caller-supplied clock
- // to tell whether we should return a timeout.
- if (_Clock::now() < __atime)
- return true;
- }
- return false;
- }
- }
-#endif // _GLIBCXX_HAS_GTHREADS
+ auto __at = __detail::__to_wait_clock(__atime);
+ auto __res = __detail::__wait_until_impl(__addr, __args,
+ __at.time_since_epoch());
- struct __timed_waiter_pool : __waiter_pool_base
- {
- // returns true if wait ended before timeout
- template<typename _Clock, typename _Dur>
- bool
- _M_do_wait_until(__platform_wait_t* __addr, __platform_wait_t __old,
- const chrono::time_point<_Clock, _Dur>& __atime)
- {
-#ifdef _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT
- return __platform_wait_until(__addr, __old, __atime);
-#else
- __platform_wait_t __val;
- __atomic_load(__addr, &__val, __ATOMIC_RELAXED);
- if (__val == __old)
+ if constexpr (!is_same_v<__wait_clock_t, _Clock>)
+ if (__res._M_timeout)
{
- lock_guard<mutex> __l(_M_mtx);
- return __cond_wait_until(_M_cv, _M_mtx, __atime);
+ // We got a timeout when measured against __clock_t but
+ // we need to check against the caller-supplied clock
+ // to tell whether we should return a timeout.
+ if (_Clock::now() < __atime)
+ __res._M_timeout = false;
}
- else
- return true;
-#endif // _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT
- }
- };
-
- struct __timed_backoff_spin_policy
- {
- __wait_clock_t::time_point _M_deadline;
- __wait_clock_t::time_point _M_t0;
-
- template<typename _Clock, typename _Dur>
- __timed_backoff_spin_policy(chrono::time_point<_Clock, _Dur>
- __deadline = _Clock::time_point::max(),
- chrono::time_point<_Clock, _Dur>
- __t0 = _Clock::now()) noexcept
- : _M_deadline(__to_wait_clock(__deadline))
- , _M_t0(__to_wait_clock(__t0))
- { }
-
- bool
- operator()() const noexcept
- {
- using namespace literals::chrono_literals;
- auto __now = __wait_clock_t::now();
- if (_M_deadline <= __now)
- return false;
-
- // FIXME: this_thread::sleep_for not available #ifdef _GLIBCXX_NO_SLEEP
-
- auto __elapsed = __now - _M_t0;
- if (__elapsed > 128ms)
- {
- this_thread::sleep_for(64ms);
- }
- else if (__elapsed > 64us)
- {
- this_thread::sleep_for(__elapsed / 2);
- }
- else if (__elapsed > 4us)
- {
- __thread_yield();
- }
- else
- return false;
- return true;
+ return __res;
}
- };
- template<typename _EntersWait>
- struct __timed_waiter : __waiter_base<__timed_waiter_pool>
+ template<typename _Rep, typename _Period>
+ __wait_result_type
+ __wait_for(const void* __addr, __wait_args_base& __args,
+ const chrono::duration<_Rep, _Period>& __rtime) noexcept
{
- using __base_type = __waiter_base<__timed_waiter_pool>;
-
- template<typename _Tp>
- __timed_waiter(const _Tp* __addr) noexcept
- : __base_type(__addr)
- {
- if constexpr (_EntersWait::value)
- _M_w._M_enter_wait();
- }
-
- ~__timed_waiter()
- {
- if constexpr (_EntersWait::value)
- _M_w._M_leave_wait();
- }
-
- // returns true if wait ended before timeout
- template<typename _Tp, typename _ValFn,
- typename _Clock, typename _Dur>
- bool
- _M_do_wait_until_v(_Tp __old, _ValFn __vfn,
- const chrono::time_point<_Clock, _Dur>&
- __atime) noexcept
- {
- __platform_wait_t __val;
- if (_M_do_spin(__old, std::move(__vfn), __val,
- __timed_backoff_spin_policy(__atime)))
- return true;
- return __base_type::_M_w._M_do_wait_until(__base_type::_M_addr, __val, __atime);
- }
-
- // returns true if wait ended before timeout
- template<typename _Pred,
- typename _Clock, typename _Dur>
- bool
- _M_do_wait_until(_Pred __pred, __platform_wait_t __val,
- const chrono::time_point<_Clock, _Dur>&
- __atime) noexcept
- {
- for (auto __now = _Clock::now(); __now < __atime;
- __now = _Clock::now())
- {
- if (__base_type::_M_w._M_do_wait_until(
- __base_type::_M_addr, __val, __atime)
- && __pred())
- return true;
-
- if (__base_type::_M_do_spin(__pred, __val,
- __timed_backoff_spin_policy(__atime, __now)))
- return true;
- }
- return false;
- }
-
- // returns true if wait ended before timeout
- template<typename _Pred,
- typename _Clock, typename _Dur>
- bool
- _M_do_wait_until(_Pred __pred,
- const chrono::time_point<_Clock, _Dur>&
- __atime) noexcept
+ if (!__rtime.count())
{
- __platform_wait_t __val;
- if (__base_type::_M_do_spin(__pred, __val,
- __timed_backoff_spin_policy(__atime)))
- return true;
- return _M_do_wait_until(__pred, __val, __atime);
- }
-
- template<typename _Tp, typename _ValFn,
- typename _Rep, typename _Period>
- bool
- _M_do_wait_for_v(_Tp __old, _ValFn __vfn,
- const chrono::duration<_Rep, _Period>&
- __rtime) noexcept
- {
- __platform_wait_t __val;
- if (_M_do_spin_v(__old, std::move(__vfn), __val))
- return true;
-
- if (!__rtime.count())
- return false; // no rtime supplied, and spin did not acquire
-
- auto __reltime = chrono::ceil<__wait_clock_t::duration>(__rtime);
-
- return __base_type::_M_w._M_do_wait_until(
- __base_type::_M_addr,
- __val,
- chrono::steady_clock::now() + __reltime);
+ // no rtime supplied, just spin a bit
+ __args._M_flags |= __wait_flags::__do_spin | __wait_flags::__spin_only;
+ return __detail::__wait_impl(__addr, __args);
}
- template<typename _Pred,
- typename _Rep, typename _Period>
- bool
- _M_do_wait_for(_Pred __pred,
- const chrono::duration<_Rep, _Period>& __rtime) noexcept
- {
- __platform_wait_t __val;
- if (__base_type::_M_do_spin(__pred, __val))
- return true;
-
- if (!__rtime.count())
- return false; // no rtime supplied, and spin did not acquire
-
- auto __reltime = chrono::ceil<__wait_clock_t::duration>(__rtime);
-
- return _M_do_wait_until(__pred, __val,
- chrono::steady_clock::now() + __reltime);
- }
- };
-
- using __enters_timed_wait = __timed_waiter<std::true_type>;
- using __bare_timed_wait = __timed_waiter<std::false_type>;
+ auto const __reltime = chrono::ceil<__wait_clock_t::duration>(__rtime);
+ auto const __atime = chrono::steady_clock::now() + __reltime;
+ return __detail::__wait_until(__addr, __args, __atime);
+ }
} // namespace __detail
// returns true if wait ended before timeout
- template<typename _Tp, typename _ValFn,
+ template<typename _Tp,
+ typename _Pred, typename _ValFn,
typename _Clock, typename _Dur>
bool
- __atomic_wait_address_until_v(const _Tp* __addr, _Tp&& __old, _ValFn&& __vfn,
- const chrono::time_point<_Clock, _Dur>&
- __atime) noexcept
+ __atomic_wait_address_until(const _Tp* __addr, _Pred&& __pred,
+ _ValFn&& __vfn,
+ const chrono::time_point<_Clock, _Dur>& __atime,
+ bool __bare_wait = false) noexcept
{
- __detail::__enters_timed_wait __w{__addr};
- return __w._M_do_wait_until_v(__old, __vfn, __atime);
+ __detail::__wait_args __args{ __addr, __bare_wait };
+ _Tp __val = __args._M_setup_wait(__addr, __vfn);
+ while (!__pred(__val))
+ {
+ auto __res = __detail::__wait_until(__addr, __args, __atime);
+ if (__res._M_timeout)
+ return false; // C++26 will also return last observed __val
+ __val = __args._M_setup_wait(__addr, __vfn, __res);
+ }
+ return true; // C++26 will also return last observed __val
}
- template<typename _Tp, typename _Pred,
- typename _Clock, typename _Dur>
+ template<typename _Clock, typename _Dur>
bool
- __atomic_wait_address_until(const _Tp* __addr, _Pred __pred,
- const chrono::time_point<_Clock, _Dur>&
- __atime) noexcept
+ __atomic_wait_address_until_v(const __detail::__platform_wait_t* __addr,
+ __detail::__platform_wait_t __old,
+ int __order,
+ const chrono::time_point<_Clock, _Dur>& __atime,
+ bool __bare_wait = false) noexcept
{
- __detail::__enters_timed_wait __w{__addr};
- return __w._M_do_wait_until(__pred, __atime);
+ // This function must not be used if __wait_impl might use a proxy wait:
+ __glibcxx_assert(__platform_wait_uses_type<__detail::__platform_wait_t>);
+
+ __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
+ auto __res = __detail::__wait_until(__addr, __args, __atime);
+ return !__res._M_timeout; // C++26 will also return last observed __val
}
- template<typename _Pred,
+ template<typename _Tp, typename _ValFn,
typename _Clock, typename _Dur>
bool
- __atomic_wait_address_until_bare(const __detail::__platform_wait_t* __addr,
- _Pred __pred,
- const chrono::time_point<_Clock, _Dur>&
- __atime) noexcept
+ __atomic_wait_address_until_v(const _Tp* __addr, _Tp&& __old,
+ _ValFn&& __vfn,
+ const chrono::time_point<_Clock, _Dur>& __atime,
+ bool __bare_wait = false) noexcept
{
- __detail::__bare_timed_wait __w{__addr};
- return __w._M_do_wait_until(__pred, __atime);
+ auto __pfn = [&](const _Tp& __val) {
+ return !__detail::__atomic_eq(__old, __val);
+ };
+ return std::__atomic_wait_address_until(__addr, __pfn, __vfn, __atime,
+ __bare_wait);
}
- template<typename _Tp, typename _ValFn,
+ template<typename _Tp,
+ typename _Pred, typename _ValFn,
typename _Rep, typename _Period>
bool
- __atomic_wait_address_for_v(const _Tp* __addr, _Tp&& __old, _ValFn&& __vfn,
- const chrono::duration<_Rep, _Period>& __rtime) noexcept
+ __atomic_wait_address_for(const _Tp* __addr, _Pred&& __pred,
+ _ValFn&& __vfn,
+ const chrono::duration<_Rep, _Period>& __rtime,
+ bool __bare_wait = false) noexcept
{
- __detail::__enters_timed_wait __w{__addr};
- return __w._M_do_wait_for_v(__old, __vfn, __rtime);
+ __detail::__wait_args __args{ __addr, __bare_wait };
+ _Tp __val = __args._M_setup_wait(__addr, __vfn);
+ while (!__pred(__val))
+ {
+ auto __res = __detail::__wait_for(__addr, __args, __rtime);
+ if (__res._M_timeout)
+ return false; // C++26 will also return last observed __val
+ __val = __args._M_setup_wait(__addr, __vfn);
+ }
+ return true; // C++26 will also return last observed __val
}
- template<typename _Tp, typename _Pred,
- typename _Rep, typename _Period>
+ template<typename _Rep, typename _Period>
bool
- __atomic_wait_address_for(const _Tp* __addr, _Pred __pred,
- const chrono::duration<_Rep, _Period>& __rtime) noexcept
+ __atomic_wait_address_for_v(const __detail::__platform_wait_t* __addr,
+ __detail::__platform_wait_t __old,
+ int __order,
+ const chrono::duration<_Rep, _Period>& __rtime,
+ bool __bare_wait = false) noexcept
{
+ // This function must not be used if __wait_impl might use a proxy wait:
+ __glibcxx_assert(__platform_wait_uses_type<__detail::__platform_wait_t>);
- __detail::__enters_timed_wait __w{__addr};
- return __w._M_do_wait_for(__pred, __rtime);
+ __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
+ auto __res = __detail::__wait_for(__addr, __args, __rtime);
+ return !__res._M_timeout; // C++26 will also return last observed __val
}
- template<typename _Pred,
+ template<typename _Tp, typename _ValFn,
typename _Rep, typename _Period>
bool
- __atomic_wait_address_for_bare(const __detail::__platform_wait_t* __addr,
- _Pred __pred,
- const chrono::duration<_Rep, _Period>& __rtime) noexcept
+ __atomic_wait_address_for_v(const _Tp* __addr, _Tp&& __old, _ValFn&& __vfn,
+ const chrono::duration<_Rep, _Period>& __rtime,
+ bool __bare_wait = false) noexcept
{
- __detail::__bare_timed_wait __w{__addr};
- return __w._M_do_wait_for(__pred, __rtime);
+ auto __pfn = [&](const _Tp& __val) {
+ return !__detail::__atomic_eq(__old, __val);
+ };
+ return __atomic_wait_address_for(__addr, __pfn, forward<_ValFn>(__vfn),
+ __rtime, __bare_wait);
}
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h
index 6d1554f..84b8b4c 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -37,104 +37,68 @@
#include <bits/version.h>
#if __glibcxx_atomic_wait
-#include <cstdint>
-#include <bits/functional_hash.h>
#include <bits/gthr.h>
#include <ext/numeric_traits.h>
-#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
-# include <cerrno>
-# include <climits>
-# include <unistd.h>
-# include <syscall.h>
-# include <bits/functexcept.h>
-#endif
-
-# include <bits/std_mutex.h> // std::mutex, std::__condvar
+#include <bits/stl_pair.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace __detail
{
-#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
-#define _GLIBCXX_HAVE_PLATFORM_WAIT 1
+ // TODO: this needs to be false for types with padding, e.g. __int20.
+ // TODO: should this be true only for integral, enum, and pointer types?
+ template<typename _Tp>
+ concept __waitable
+ = is_scalar_v<_Tp> && __builtin_popcountg(sizeof(_Tp)) == 1
+ && (sizeof(_Tp) <= sizeof(__UINT64_TYPE__));
+ }
+
+#if defined _GLIBCXX_HAVE_LINUX_FUTEX
+ namespace __detail
+ {
+ // Use futex syscall on int objects.
using __platform_wait_t = int;
inline constexpr size_t __platform_wait_alignment = 4;
+ }
+ // Defined to true for a subset of __waitable types which are statically
+ // known to definitely be able to use futex, not a proxy wait.
+ template<typename _Tp>
+ inline constexpr bool __platform_wait_uses_type
+ = __detail::__waitable<_Tp>
+ && sizeof(_Tp) == sizeof(int) && alignof(_Tp) >= 4;
#else
// define _GLIBCX_HAVE_PLATFORM_WAIT and implement __platform_wait()
// and __platform_notify() if there is a more efficient primitive supported
// by the platform (e.g. __ulock_wait()/__ulock_wake()) which is better than
// a mutex/condvar based wait.
+ namespace __detail
+ {
# if ATOMIC_LONG_LOCK_FREE == 2
using __platform_wait_t = unsigned long;
# else
using __platform_wait_t = unsigned int;
# endif
inline constexpr size_t __platform_wait_alignment
- = __alignof__(__platform_wait_t);
-#endif
+ = sizeof(__platform_wait_t) < __alignof__(__platform_wait_t)
+ ? __alignof__(__platform_wait_t) : sizeof(__platform_wait_t);
} // namespace __detail
- template<typename _Tp>
- inline constexpr bool __platform_wait_uses_type
-#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
- = is_scalar_v<_Tp>
- && ((sizeof(_Tp) == sizeof(__detail::__platform_wait_t))
- && (alignof(_Tp*) >= __detail::__platform_wait_alignment));
-#else
- = false;
+ // This must be false for the general case where we don't know of any
+ // futex-like syscall.
+ template<typename>
+ inline constexpr bool __platform_wait_uses_type = false;
#endif
namespace __detail
{
-#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
- enum class __futex_wait_flags : int
- {
-#ifdef _GLIBCXX_HAVE_LINUX_FUTEX_PRIVATE
- __private_flag = 128,
-#else
- __private_flag = 0,
-#endif
- __wait = 0,
- __wake = 1,
- __wait_bitset = 9,
- __wake_bitset = 10,
- __wait_private = __wait | __private_flag,
- __wake_private = __wake | __private_flag,
- __wait_bitset_private = __wait_bitset | __private_flag,
- __wake_bitset_private = __wake_bitset | __private_flag,
- __bitset_match_any = -1
- };
-
- template<typename _Tp>
- void
- __platform_wait(const _Tp* __addr, __platform_wait_t __val) noexcept
- {
- auto __e = syscall (SYS_futex, static_cast<const void*>(__addr),
- static_cast<int>(__futex_wait_flags::__wait_private),
- __val, nullptr);
- if (!__e || errno == EAGAIN)
- return;
- if (errno != EINTR)
- __throw_system_error(errno);
- }
-
- template<typename _Tp>
- void
- __platform_notify(const _Tp* __addr, bool __all) noexcept
- {
- syscall (SYS_futex, static_cast<const void*>(__addr),
- static_cast<int>(__futex_wait_flags::__wake_private),
- __all ? INT_MAX : 1);
- }
-#endif
-
inline void
__thread_yield() noexcept
{
#if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD
- __gthread_yield();
+ __gthread_yield();
#endif
}
@@ -148,334 +112,233 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
}
- inline constexpr auto __atomic_spin_count_relax = 12;
- inline constexpr auto __atomic_spin_count = 16;
-
- struct __default_spin_policy
- {
- bool
- operator()() const noexcept
- { return false; }
- };
-
- template<typename _Pred,
- typename _Spin = __default_spin_policy>
- bool
- __atomic_spin(_Pred& __pred, _Spin __spin = _Spin{ }) noexcept
- {
- for (auto __i = 0; __i < __atomic_spin_count; ++__i)
- {
- if (__pred())
- return true;
-
- if (__i < __atomic_spin_count_relax)
- __detail::__thread_relax();
- else
- __detail::__thread_yield();
- }
-
- while (__spin())
- {
- if (__pred())
- return true;
- }
-
- return false;
- }
-
// return true if equal
template<typename _Tp>
- bool __atomic_compare(const _Tp& __a, const _Tp& __b)
+ inline bool
+ __atomic_eq(const _Tp& __a, const _Tp& __b)
{
// TODO make this do the correct padding bit ignoring comparison
- return __builtin_memcmp(&__a, &__b, sizeof(_Tp)) == 0;
+ return __builtin_memcmp(std::addressof(__a), std::addressof(__b),
+ sizeof(_Tp)) == 0;
}
- struct __waiter_pool_base
- {
- // Don't use std::hardware_destructive_interference_size here because we
- // don't want the layout of library types to depend on compiler options.
- static constexpr auto _S_align = 64;
-
- alignas(_S_align) __platform_wait_t _M_wait = 0;
+ // Storage for up to 64 bits of value, should be considered opaque bits.
+ using __wait_value_type = __UINT64_TYPE__;
-#ifndef _GLIBCXX_HAVE_PLATFORM_WAIT
- mutex _M_mtx;
-#endif
-
- alignas(_S_align) __platform_wait_t _M_ver = 0;
+ // lightweight std::optional<__wait_value_type>
+ struct __wait_result_type
+ {
+ __wait_value_type _M_val;
+ unsigned char _M_has_val : 1; // _M_val value was loaded before return.
+ unsigned char _M_timeout : 1; // Waiting function ended with timeout.
+ unsigned char _M_unused : 6; // padding
+ };
-#ifndef _GLIBCXX_HAVE_PLATFORM_WAIT
- __condvar _M_cv;
-#endif
- __waiter_pool_base() = default;
+ enum class __wait_flags : __UINT_LEAST32_TYPE__
+ {
+ __abi_version = 0x00000000,
+ // currently unused = 1,
+ __track_contention = 2,
+ __do_spin = 4,
+ __spin_only = 8, // Ignored unless __do_spin is also set.
+ // __abi_version_mask = 0xff000000,
+ };
- void
- _M_enter_wait() noexcept
- { __atomic_fetch_add(&_M_wait, 1, __ATOMIC_SEQ_CST); }
+ [[__gnu__::__always_inline__]]
+ constexpr __wait_flags
+ operator|(__wait_flags __l, __wait_flags __r) noexcept
+ {
+ using _Ut = underlying_type_t<__wait_flags>;
+ return static_cast<__wait_flags>(static_cast<_Ut>(__l)
+ | static_cast<_Ut>(__r));
+ }
- void
- _M_leave_wait() noexcept
- { __atomic_fetch_sub(&_M_wait, 1, __ATOMIC_RELEASE); }
+ [[__gnu__::__always_inline__]]
+ constexpr __wait_flags&
+ operator|=(__wait_flags& __l, __wait_flags __r) noexcept
+ { return __l = __l | __r; }
+ // Simple aggregate containing arguments used by implementation details.
+ struct __wait_args_base
+ {
+ __wait_flags _M_flags;
+ int _M_order = __ATOMIC_ACQUIRE;
+ __wait_value_type _M_old = 0;
+ void* _M_wait_state = nullptr;
+ const void* _M_obj = nullptr; // The address of the object to wait on.
+ unsigned char _M_obj_size = 0; // The size of that object.
+
+ // Test whether _M_flags & __flags is non-zero.
bool
- _M_waiting() const noexcept
+ operator&(__wait_flags __flags) const noexcept
{
- __platform_wait_t __res;
- __atomic_load(&_M_wait, &__res, __ATOMIC_SEQ_CST);
- return __res != 0;
+ using _Ut = underlying_type_t<__wait_flags>;
+ return static_cast<_Ut>(_M_flags) & static_cast<_Ut>(__flags);
}
+ };
- void
- _M_notify(__platform_wait_t* __addr, [[maybe_unused]] bool __all,
- bool __bare) noexcept
- {
-#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
- if (__addr == &_M_ver)
- {
- __atomic_fetch_add(__addr, 1, __ATOMIC_SEQ_CST);
- __all = true;
- }
-
- if (__bare || _M_waiting())
- __platform_notify(__addr, __all);
-#else
+ // Utility for populating a __wait_args_base structure.
+ struct __wait_args : __wait_args_base
+ {
+ template<typename _Tp> requires (!is_same_v<_Tp, __wait_args>)
+ explicit
+ __wait_args(const _Tp* __addr, bool __bare_wait = false) noexcept
+ : __wait_args_base{ _S_flags_for(__addr, __bare_wait) }
{
- lock_guard<mutex> __l(_M_mtx);
- __atomic_fetch_add(__addr, 1, __ATOMIC_RELAXED);
+ _M_obj = __addr; // Might be replaced by _M_setup_wait
+ if constexpr (__waitable<_Tp>)
+ // __wait_impl might be able to wait directly on __addr
+ // instead of using a proxy, depending on its size.
+ _M_obj_size = sizeof(_Tp);
}
- if (__bare || _M_waiting())
- _M_cv.notify_all();
-#endif
- }
- static __waiter_pool_base&
- _S_for(const void* __addr) noexcept
+ __wait_args(const __platform_wait_t* __addr, __platform_wait_t __old,
+ int __order, bool __bare_wait = false) noexcept
+ : __wait_args(__addr, __bare_wait)
{
- constexpr __UINTPTR_TYPE__ __ct = 16;
- static __waiter_pool_base __w[__ct];
- auto __key = ((__UINTPTR_TYPE__)__addr >> 2) % __ct;
- return __w[__key];
+ _M_order = __order;
+ _M_old = __old;
}
- };
- struct __waiter_pool : __waiter_pool_base
- {
- void
- _M_do_wait(const __platform_wait_t* __addr, __platform_wait_t __old) noexcept
- {
-#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
- __platform_wait(__addr, __old);
-#else
- __platform_wait_t __val;
- __atomic_load(__addr, &__val, __ATOMIC_SEQ_CST);
- if (__val == __old)
- {
- lock_guard<mutex> __l(_M_mtx);
- __atomic_load(__addr, &__val, __ATOMIC_RELAXED);
- if (__val == __old)
- _M_cv.wait(_M_mtx);
- }
-#endif // __GLIBCXX_HAVE_PLATFORM_WAIT
- }
- };
+ __wait_args(const __wait_args&) noexcept = default;
+ __wait_args& operator=(const __wait_args&) noexcept = default;
- template<typename _Tp>
- struct __waiter_base
- {
- using __waiter_type = _Tp;
-
- __waiter_type& _M_w;
- __platform_wait_t* _M_addr;
-
- template<typename _Up>
- static __platform_wait_t*
- _S_wait_addr(const _Up* __a, __platform_wait_t* __b)
- {
- if constexpr (__platform_wait_uses_type<_Up>)
- return reinterpret_cast<__platform_wait_t*>(const_cast<_Up*>(__a));
- else
- return __b;
- }
-
- static __waiter_type&
- _S_for(const void* __addr) noexcept
+ template<typename _Tp, typename _ValFn>
+ _Tp
+ _M_setup_wait(const _Tp* __addr, _ValFn __vfn,
+ __wait_result_type __res = {})
{
- static_assert(sizeof(__waiter_type) == sizeof(__waiter_pool_base));
- auto& res = __waiter_pool_base::_S_for(__addr);
- return reinterpret_cast<__waiter_type&>(res);
- }
-
- template<typename _Up>
- explicit __waiter_base(const _Up* __addr) noexcept
- : _M_w(_S_for(__addr))
- , _M_addr(_S_wait_addr(__addr, &_M_w._M_ver))
- { }
-
- void
- _M_notify(bool __all, bool __bare = false) noexcept
- { _M_w._M_notify(_M_addr, __all, __bare); }
-
- template<typename _Up, typename _ValFn,
- typename _Spin = __default_spin_policy>
- static bool
- _S_do_spin_v(__platform_wait_t* __addr,
- const _Up& __old, _ValFn __vfn,
- __platform_wait_t& __val,
- _Spin __spin = _Spin{ })
- {
- auto const __pred = [=]
- { return !__detail::__atomic_compare(__old, __vfn()); };
-
- if constexpr (__platform_wait_uses_type<_Up>)
+ static_assert(is_same_v<_Tp, decay_t<decltype(__vfn())>>);
+
+ if (__res._M_has_val) // A previous wait loaded a recent value.
+ {
+ _M_old = __res._M_val;
+ if constexpr (!__platform_wait_uses_type<_Tp>)
+ {
+ // __res._M_val might be the value of a proxy wait object,
+ // not the value of *__addr. Call __vfn() to get new value.
+ return __vfn();
+ }
+ // Not a proxy wait, so the value in __res._M_val was loaded
+ // from *__addr and we don't need to call __vfn().
+ else if constexpr (sizeof(_Tp) == sizeof(__UINT32_TYPE__))
+ return __builtin_bit_cast(_Tp, (__UINT32_TYPE__)_M_old);
+ else if constexpr (sizeof(_Tp) == sizeof(__UINT64_TYPE__))
+ return __builtin_bit_cast(_Tp, (__UINT64_TYPE__)_M_old);
+ else
+ {
+ static_assert(false); // Unsupported size
+ return {};
+ }
+ }
+
+ if constexpr (!__platform_wait_uses_type<_Tp>)
+ if (_M_setup_proxy_wait(__addr))
{
- __builtin_memcpy(&__val, &__old, sizeof(__val));
+ // We will use a proxy wait for this object.
+ // The library has set _M_obj and _M_obj_size and _M_old.
+ // Call __vfn to load the current value from *__addr
+ // (which must happen after the call to _M_setup_proxy_wait).
+ return __vfn();
}
- else
- {
- __atomic_load(__addr, &__val, __ATOMIC_ACQUIRE);
- }
- return __atomic_spin(__pred, __spin);
- }
-
- template<typename _Up, typename _ValFn,
- typename _Spin = __default_spin_policy>
- bool
- _M_do_spin_v(const _Up& __old, _ValFn __vfn,
- __platform_wait_t& __val,
- _Spin __spin = _Spin{ })
- { return _S_do_spin_v(_M_addr, __old, __vfn, __val, __spin); }
-
- template<typename _Pred,
- typename _Spin = __default_spin_policy>
- static bool
- _S_do_spin(const __platform_wait_t* __addr,
- _Pred __pred,
- __platform_wait_t& __val,
- _Spin __spin = _Spin{ })
- {
- __atomic_load(__addr, &__val, __ATOMIC_ACQUIRE);
- return __atomic_spin(__pred, __spin);
- }
-
- template<typename _Pred,
- typename _Spin = __default_spin_policy>
- bool
- _M_do_spin(_Pred __pred, __platform_wait_t& __val,
- _Spin __spin = _Spin{ })
- { return _S_do_spin(_M_addr, __pred, __val, __spin); }
- };
-
- template<typename _EntersWait>
- struct __waiter : __waiter_base<__waiter_pool>
- {
- using __base_type = __waiter_base<__waiter_pool>;
- template<typename _Tp>
- explicit __waiter(const _Tp* __addr) noexcept
- : __base_type(__addr)
- {
- if constexpr (_EntersWait::value)
- _M_w._M_enter_wait();
- }
+ // We will use a futex-like operation to wait on this object,
+ // and so can just load the value and store it into _M_old.
+ auto __val = __vfn();
+ // We have to consider various sizes, because a future libstdc++.so
+ // might enable non-proxy waits for additional sizes.
+ if constexpr (sizeof(_Tp) == sizeof(__UINT64_TYPE__))
+ _M_old = __builtin_bit_cast(__UINT64_TYPE__, __val);
+ else if constexpr (sizeof(_Tp) == sizeof(__UINT32_TYPE__))
+ _M_old = __builtin_bit_cast(__UINT32_TYPE__, __val);
+ else if constexpr (sizeof(_Tp) == sizeof(__UINT16_TYPE__))
+ _M_old = __builtin_bit_cast(__UINT16_TYPE__, __val);
+ else if constexpr (sizeof(_Tp) == sizeof(__UINT8_TYPE__))
+ _M_old = __builtin_bit_cast(__UINT8_TYPE__, __val);
+ else // _M_setup_proxy_wait should have returned true for this type!
+ __glibcxx_assert(false);
+ return __val;
+ }
- ~__waiter()
+ private:
+ // Returns true if a proxy wait will be used for __addr, false otherwise.
+ // If true, _M_wait_state, _M_obj, _M_obj_size, and _M_old are set.
+ // If false, data members are unchanged.
+ bool
+ _M_setup_proxy_wait(const void* __addr);
+
+ template<typename _Tp>
+ static constexpr __wait_flags
+ _S_flags_for(const _Tp*, bool __bare_wait) noexcept
{
- if constexpr (_EntersWait::value)
- _M_w._M_leave_wait();
+ using enum __wait_flags;
+ __wait_flags __res = __abi_version | __do_spin;
+ if (!__bare_wait)
+ __res |= __track_contention;
+ return __res;
}
+ };
- template<typename _Tp, typename _ValFn>
- void
- _M_do_wait_v(_Tp __old, _ValFn __vfn)
- {
- do
- {
- __platform_wait_t __val;
- if (__base_type::_M_do_spin_v(__old, __vfn, __val))
- return;
- __base_type::_M_w._M_do_wait(__base_type::_M_addr, __val);
- }
- while (__detail::__atomic_compare(__old, __vfn()));
- }
-
- template<typename _Pred>
- void
- _M_do_wait(_Pred __pred) noexcept
- {
- do
- {
- __platform_wait_t __val;
- if (__base_type::_M_do_spin(__pred, __val))
- return;
- __base_type::_M_w._M_do_wait(__base_type::_M_addr, __val);
- }
- while (!__pred());
- }
- };
+ __wait_result_type
+ __wait_impl(const void* __addr, __wait_args_base&);
- using __enters_wait = __waiter<std::true_type>;
- using __bare_wait = __waiter<std::false_type>;
+ void
+ __notify_impl(const void* __addr, bool __all, const __wait_args_base&);
} // namespace __detail
- template<typename _Tp, typename _ValFn>
+ // Wait on __addr while __pred(__vfn()) is false.
+ // If __bare_wait is false, increment a counter while waiting.
+ // For callers that keep their own count of waiters, use __bare_wait=true.
+ // The effect of __vfn() must be an atomic load from __addr and nothing else.
+ template<typename _Tp, typename _Pred, typename _ValFn>
void
- __atomic_wait_address_v(const _Tp* __addr, _Tp __old,
- _ValFn __vfn) noexcept
+ __atomic_wait_address(const _Tp* __addr, _Pred&& __pred, _ValFn&& __vfn,
+ bool __bare_wait = false) noexcept
{
- __detail::__enters_wait __w(__addr);
- __w._M_do_wait_v(__old, __vfn);
+ __detail::__wait_args __args{ __addr, __bare_wait };
+ _Tp __val = __args._M_setup_wait(__addr, __vfn);
+ while (!__pred(__val))
+ {
+ auto __res = __detail::__wait_impl(__addr, __args);
+ __val = __args._M_setup_wait(__addr, __vfn, __res);
+ }
+ // C++26 will return __val
}
- template<typename _Tp, typename _Pred>
- void
- __atomic_wait_address(const _Tp* __addr, _Pred __pred) noexcept
- {
- __detail::__enters_wait __w(__addr);
- __w._M_do_wait(__pred);
- }
+ // Wait on __addr while *__addr == __old is true.
+ inline void
+ __atomic_wait_address_v(const __detail::__platform_wait_t* __addr,
+ __detail::__platform_wait_t __old,
+ int __order, bool __bare_wait = false)
+ {
+ // This function must not be used if __wait_impl might use a proxy wait:
+ __glibcxx_assert(__platform_wait_uses_type<__detail::__platform_wait_t>);
- // This call is to be used by atomic types which track contention externally
- template<typename _Pred>
+ __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
+ // C++26 will not ignore the return value here
+ __detail::__wait_impl(__addr, __args);
+ }
+
+ // Wait on __addr while __vfn() == __old is true.
+ template<typename _Tp, typename _ValFn>
void
- __atomic_wait_address_bare(const __detail::__platform_wait_t* __addr,
- _Pred __pred) noexcept
+ __atomic_wait_address_v(const _Tp* __addr, _Tp __old,
+ _ValFn __vfn) noexcept
{
-#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
- do
- {
- __detail::__platform_wait_t __val;
- if (__detail::__bare_wait::_S_do_spin(__addr, __pred, __val))
- return;
- __detail::__platform_wait(__addr, __val);
- }
- while (!__pred());
-#else // !_GLIBCXX_HAVE_PLATFORM_WAIT
- __detail::__bare_wait __w(__addr);
- __w._M_do_wait(__pred);
-#endif
+ auto __pfn = [&](const _Tp& __val)
+ { return !__detail::__atomic_eq(__old, __val); };
+ std::__atomic_wait_address(__addr, __pfn, forward<_ValFn>(__vfn));
}
template<typename _Tp>
void
- __atomic_notify_address(const _Tp* __addr, bool __all) noexcept
+ __atomic_notify_address(const _Tp* __addr, bool __all,
+ bool __bare_wait = false) noexcept
{
- __detail::__bare_wait __w(__addr);
- __w._M_notify(__all);
+ __detail::__wait_args __args{ __addr, __bare_wait };
+ __detail::__notify_impl(__addr, __all, __args);
}
- // This call is to be used by atomic types which track contention externally
- inline void
- __atomic_notify_address_bare(const __detail::__platform_wait_t* __addr,
- bool __all) noexcept
- {
-#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
- __detail::__platform_notify(__addr, __all);
-#else
- __detail::__bare_wait __w(__addr);
- __w._M_notify(__all, true);
-#endif
- }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __glibcxx_atomic_wait
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 9c431c7..b1db722 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -269,8 +269,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
void
_M_set_length(size_type __n)
{
- _M_length(__n);
traits_type::assign(_M_data()[__n], _CharT());
+ _M_length(__n);
}
_GLIBCXX20_CONSTEXPR
@@ -411,7 +411,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
if (__pos > this->size())
__throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "
"this->size() (which is %zu)"),
- __s, __pos, this->size());
+ __s, (size_t)__pos, (size_t)this->size());
return __pos;
}
@@ -488,8 +488,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
is_same<_IterBase, const _CharT*>>::value)
_S_copy(__p, std::__niter_base(__k1), __k2 - __k1);
#if __cpp_lib_concepts
- else if constexpr (contiguous_iterator<_Iterator>
- && is_same_v<iter_value_t<_Iterator>, _CharT>)
+ else if constexpr (requires {
+ requires contiguous_iterator<_Iterator>;
+ { std::to_address(__k1) }
+ -> convertible_to<const _CharT*>;
+ })
{
const auto __d = __k2 - __k1;
(void) (__k1 + __d); // See P3349R1
@@ -499,7 +502,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
else
#endif
for (; __k1 != __k2; ++__k1, (void)++__p)
- traits_type::assign(*__p, *__k1); // These types are off.
+ traits_type::assign(*__p, static_cast<_CharT>(*__k1));
}
#pragma GCC diagnostic pop
@@ -527,12 +530,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
static constexpr void
_S_copy_range(pointer __p, _Rg&& __rg, size_type __n)
{
- if constexpr (ranges::contiguous_range<_Rg>
- && is_same_v<ranges::range_value_t<_Rg>, _CharT>)
+ if constexpr (requires {
+ requires ranges::contiguous_range<_Rg>;
+ { ranges::data(std::forward<_Rg>(__rg)) }
+ -> convertible_to<const _CharT*>;
+ })
_S_copy(__p, ranges::data(std::forward<_Rg>(__rg)), __n);
else
- for (auto&& __e : __rg)
- traits_type::assign(*__p++, std::forward<decltype(__e)>(__e));
+ {
+ auto __first = ranges::begin(__rg);
+ const auto __last = ranges::end(__rg);
+ for (; __first != __last; ++__first)
+ traits_type::assign(*__p++, static_cast<_CharT>(*__first));
+ }
}
#endif
@@ -1154,7 +1164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{
size_type __sz = _M_string_length;
if (__sz > max_size ())
- __builtin_unreachable ();
+ __builtin_unreachable();
return __sz;
}
@@ -1269,7 +1279,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
size_t __sz = _M_is_local() ? size_type(_S_local_capacity)
: _M_allocated_capacity;
if (__sz < _S_local_capacity || __sz > max_size ())
- __builtin_unreachable ();
+ __builtin_unreachable();
return __sz;
}
@@ -3432,6 +3442,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ return basic_string(*this,
_M_check(__pos, "basic_string::substr"), __n); }
+#ifdef __glibcxx_string_subview // >= C++26
+ /**
+ * @brief Get a subview.
+ * @param __pos Index of first character (default 0).
+ * @param __n Number of characters in subview (default remainder).
+ * @return The subview.
+ * @throw std::out_of_range If __pos > size().
+ *
+ * Construct and return a subview using the `__n` characters starting at
+ * `__pos`. If the string is too short, use the remainder of the
+ * characters. If `__pos` is beyond the end of the string, out_of_range
+ * is thrown.
+ */
+ [[nodiscard]]
+ constexpr basic_string_view<_CharT, _Traits>
+ subview(size_type __pos = 0, size_type __n = npos) const
+ { return __sv_type(*this).subview(__pos, __n); }
+#endif
+
/**
* @brief Compare to a string.
* @param __str String to compare against.
@@ -3928,21 +3957,23 @@ _GLIBCXX_END_NAMESPACE_CXX11
operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
basic_string<_CharT, _Traits, _Alloc>&& __rhs)
{
-#if _GLIBCXX_USE_CXX11_ABI
- using _Alloc_traits = allocator_traits<_Alloc>;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ // Return value must use __lhs.get_allocator(), but if __rhs has equal
+ // allocator then we can choose which parameter to modify in-place.
bool __use_rhs = false;
- if _GLIBCXX17_CONSTEXPR (typename _Alloc_traits::is_always_equal{})
+ if constexpr (allocator_traits<_Alloc>::is_always_equal::value)
__use_rhs = true;
else if (__lhs.get_allocator() == __rhs.get_allocator())
__use_rhs = true;
if (__use_rhs)
-#endif
{
const auto __size = __lhs.size() + __rhs.size();
if (__size > __lhs.capacity() && __size <= __rhs.capacity())
return std::move(__rhs.insert(0, __lhs));
}
return std::move(__lhs.append(__rhs));
+#pragma GCC diagnostic pop
}
template<typename _CharT, typename _Traits, typename _Alloc>
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index 02230ac..bca55bc 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -210,7 +210,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_data(__another);
_M_capacity(__capacity);
}
- traits_type::assign(_M_data()[__len++], *__beg);
+ traits_type::assign(_M_data()[__len++],
+ static_cast<_CharT>(*__beg));
++__beg;
}
diff --git a/libstdc++-v3/include/bits/binders.h b/libstdc++-v3/include/bits/binders.h
new file mode 100644
index 0000000..9724717
--- /dev/null
+++ b/libstdc++-v3/include/bits/binders.h
@@ -0,0 +1,237 @@
+// Implementation of std::move_only_function, std::copyable_function
+// and std::function_ref -*- 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 include/bits/binder.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _GLIBCXX_BINDERS_H
+#define _GLIBCXX_BINDERS_H 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#if __cplusplus >= 202002L
+
+#include <bits/invoke.h>
+#include <bits/move.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<size_t, typename _Tp>
+ struct _Indexed_bound_arg
+ {
+ [[no_unique_address]] _Tp _M_val;
+ };
+
+ template<typename... _IndexedArgs>
+ struct _Bound_arg_storage : _IndexedArgs...
+ {
+ template<bool _Back, typename _Fd, typename _Self, typename... _CallArgs>
+ static constexpr
+ decltype(auto)
+ _S_apply(_Fd&& __fd, _Self&& __self, _CallArgs&&... __call_args)
+ {
+ if constexpr (_Back)
+ return std::__invoke(std::forward<_Fd>(__fd),
+ std::forward<_CallArgs>(__call_args)...,
+ __like_t<_Self, _IndexedArgs>(__self)._M_val...);
+ else
+ return std::__invoke(std::forward<_Fd>(__fd),
+ __like_t<_Self, _IndexedArgs>(__self)._M_val...,
+ std::forward<_CallArgs>(__call_args)...);
+ }
+ };
+
+ template<typename... _BoundArgs, typename... _Args>
+ constexpr auto
+ __make_bound_args(_Args&&... __args)
+ {
+ if constexpr (sizeof...(_BoundArgs) == 1)
+ // pack has one element, so return copy of arg
+ return (_BoundArgs(std::forward<_Args>(__args)), ...);
+ else
+ {
+ auto __impl = [&]<size_t... _Inds>(index_sequence<_Inds...>)
+ {
+ return _Bound_arg_storage<_Indexed_bound_arg<_Inds, _BoundArgs>...>
+ { {_BoundArgs(std::forward<_Args>(__args))}... };
+ };
+ return __impl(index_sequence_for<_BoundArgs...>());
+ }
+ }
+
+ template<bool _Back, typename _Fd, typename... _BoundArgs>
+ class _Binder
+ {
+ template<typename _Self, typename... _CallArgs>
+ using _Result_t = __conditional_t<
+ _Back,
+ invoke_result<__like_t<_Self, _Fd>,
+ _CallArgs..., __like_t<_Self, _BoundArgs>...>,
+ invoke_result<__like_t<_Self, _Fd>,
+ __like_t<_Self, _BoundArgs>..., _CallArgs...>>::type;
+
+ template<typename _Self, typename... _CallArgs>
+ static consteval bool
+ _S_noexcept_invocable()
+ {
+ if constexpr (_Back)
+ return is_nothrow_invocable_v< __like_t<_Self, _Fd>,
+ _CallArgs..., __like_t<_Self, _BoundArgs>...>;
+ else
+ return is_nothrow_invocable_v<__like_t<_Self, _Fd>,
+ __like_t<_Self, _BoundArgs>..., _CallArgs...>;
+ }
+
+ public:
+ static_assert(is_move_constructible_v<_Fd>);
+ static_assert((is_move_constructible_v<_BoundArgs> && ...));
+
+ // First parameter is to ensure this constructor is never used
+ // instead of the copy/move constructor.
+ template<typename _Fn, typename... _Args>
+ explicit constexpr
+ _Binder(int, _Fn&& __fn, _Args&&... __args)
+ noexcept(__and_<is_nothrow_constructible<_Fd, _Fn>,
+ is_nothrow_constructible<_BoundArgs, _Args>...>::value)
+ : _M_fd(std::forward<_Fn>(__fn)),
+ _M_bound_args(__make_bound_args<_BoundArgs...>(std::forward<_Args>(__args)...))
+ { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); }
+
+#if _GLIBCXX_EXPLICIT_THIS_PARAMETER
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this
+ template<typename _Self, typename... _CallArgs>
+ constexpr _Result_t<_Self, _CallArgs...>
+ operator()(this _Self&& __self, _CallArgs&&... __call_args)
+ noexcept(_S_noexcept_invocable<_Self, _CallArgs...>())
+ {
+ return _S_call(__like_t<_Self, _Binder>(__self),
+ std::forward<_CallArgs>(__call_args)...);
+ }
+# pragma GCC diagnostic pop
+#else
+ template<typename... _CallArgs>
+ requires true
+ constexpr _Result_t<_Binder&, _CallArgs...>
+ operator()(_CallArgs&&... __call_args) &
+ noexcept(_S_noexcept_invocable<_Binder&, _CallArgs...>())
+ {
+ return _S_call(*this, std::forward<_CallArgs>(__call_args)...);
+ }
+
+ template<typename... _CallArgs>
+ requires true
+ constexpr _Result_t<const _Binder&, _CallArgs...>
+ operator()(_CallArgs&&... __call_args) const &
+ noexcept(_S_noexcept_invocable<const _Binder&, _CallArgs...>())
+ {
+ return _S_call(*this, std::forward<_CallArgs>(__call_args)...);
+ }
+
+ template<typename... _CallArgs>
+ requires true
+ constexpr _Result_t<_Binder&&, _CallArgs...>
+ operator()(_CallArgs&&... __call_args) &&
+ noexcept(_S_noexcept_invocable<_Binder&&, _CallArgs...>())
+ {
+ return _S_call(std::move(*this),
+ std::forward<_CallArgs>(__call_args)...);
+ }
+
+ template<typename... _CallArgs>
+ requires true
+ constexpr _Result_t<const _Binder&&, _CallArgs...>
+ operator()(_CallArgs&&... __call_args) const &&
+ noexcept(_S_noexcept_invocable<const _Binder&&, _CallArgs...>())
+ {
+ return _S_call(std::move(*this),
+ std::forward<_CallArgs>(__call_args)...);
+ }
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) & = delete;
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) const & = delete;
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) && = delete;
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) const && = delete;
+#endif
+
+ template<typename _Tp, typename... _CallArgs>
+ static constexpr
+ decltype(auto)
+ _S_call(_Tp&& __g, _CallArgs&&... __call_args)
+ {
+ if constexpr (sizeof...(_BoundArgs) > 1)
+ return _BoundArgsStorage::template _S_apply<_Back>(
+ std::forward<_Tp>(__g)._M_fd,
+ std::forward<_Tp>(__g)._M_bound_args,
+ std::forward<_CallArgs>(__call_args)...);
+ else if constexpr (sizeof...(_BoundArgs) == 0)
+ return std::__invoke(std::forward<_Tp>(__g)._M_fd,
+ std::forward<_CallArgs>(__call_args)...);
+ else if constexpr (_Back) // sizeof...(_BoundArgs) == 1
+ return std::__invoke(std::forward<_Tp>(__g)._M_fd,
+ std::forward<_CallArgs>(__call_args)...,
+ std::forward<_Tp>(__g)._M_bound_args);
+ else // !_Back && sizeof...(_BoundArgs) == 1
+ return std::__invoke(std::forward<_Tp>(__g)._M_fd,
+ std::forward<_Tp>(__g)._M_bound_args,
+ std::forward<_CallArgs>(__call_args)...);
+ }
+
+ private:
+ using _BoundArgsStorage
+ // _BoundArgs are required to be move-constructible, so this is valid.
+ = decltype(__make_bound_args<_BoundArgs...>(std::declval<_BoundArgs>()...));
+
+ [[no_unique_address]] _Fd _M_fd;
+ [[no_unique_address]] _BoundArgsStorage _M_bound_args;
+ };
+
+ template<typename _Fn, typename... _Args>
+ using _Bind_front_t = _Binder<false, decay_t<_Fn>, decay_t<_Args>...>;
+
+ // for zero bounds args behavior of bind_front and bind_back is the same,
+ // so reuse _Bind_front_t, i.e. _Binder<false, ...>
+ template<typename _Fn, typename... _Args>
+ using _Bind_back_t
+ = _Binder<(sizeof...(_Args) > 0), decay_t<_Fn>, decay_t<_Args>...>;
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // __cplusplus >= 202002L
+#endif // _GLIBCXX_BINDERS_H
diff --git a/libstdc++-v3/include/bits/boost_concept_check.h b/libstdc++-v3/include/bits/boost_concept_check.h
index 7a99f74..a1f488d 100644
--- a/libstdc++-v3/include/bits/boost_concept_check.h
+++ b/libstdc++-v3/include/bits/boost_concept_check.h
@@ -68,6 +68,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
+#pragma GCC diagnostic ignored "-Wlong-long"
#define _IsUnused __attribute__ ((__unused__))
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 676f5ee..e6d8f18 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -273,6 +273,12 @@
#define _GLIBCXX_NOEXCEPT_QUAL
#endif
+#if __cpp_auto_cast
+# define _GLIBCXX_AUTO_CAST(X) auto(X)
+#else
+# define _GLIBCXX_AUTO_CAST(X) ::std::__decay_t<decltype((X))>(X)
+#endif
+
// Macro for extern template, ie controlling template linkage via use
// of extern keyword on template declaration. As documented in the g++
// manual, it inhibits all implicit instantiations and is used
@@ -921,6 +927,13 @@ namespace __gnu_cxx
# define _GLIBCXX_USE_BUILTIN_TRAIT(BT) 0
#endif
+// Whether deducing this is usable either officially, if in C++23 mode, or
+// as an extension (Clang doesn't support the latter).
+#if __cpp_explicit_this_parameter \
+ || (__cplusplus >= 201103L && __GNUC__ >= 14 && !defined(_GLIBCXX_CLANG))
+# define _GLIBCXX_EXPLICIT_THIS_PARAMETER 202110L
+#endif
+
// Mark code that should be ignored by the compiler, but seen by Doxygen.
#define _GLIBCXX_DOXYGEN_ONLY(X)
diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h
index 67e18e8..5ca3466 100644
--- a/libstdc++-v3/include/bits/char_traits.h
+++ b/libstdc++-v3/include/bits/char_traits.h
@@ -284,7 +284,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#endif
- if _GLIBCXX17_CONSTEXPR (sizeof(_CharT) == 1 && __is_trivial(_CharT))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ if _GLIBCXX_CONSTEXPR (sizeof(_CharT) == 1 && __is_trivial(_CharT))
{
if (__n)
{
@@ -298,6 +300,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
for (std::size_t __i = 0; __i < __n; ++__i)
__s[__i] = __a;
}
+#pragma GCC diagnostic pop
return __s;
}
diff --git a/libstdc++-v3/include/bits/chrono.h b/libstdc++-v3/include/bits/chrono.h
index fad2162..4dc3998 100644
--- a/libstdc++-v3/include/bits/chrono.h
+++ b/libstdc++-v3/include/bits/chrono.h
@@ -1244,6 +1244,7 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
now() noexcept;
// Map to C API
+ [[__gnu__::__always_inline__]]
static std::time_t
to_time_t(const time_point& __t) noexcept
{
@@ -1251,6 +1252,7 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
(__t.time_since_epoch()).count());
}
+ [[__gnu__::__always_inline__]]
static time_point
from_time_t(std::time_t __t) noexcept
{
@@ -1513,6 +1515,80 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
} // namespace filesystem
#endif // C++17 && HOSTED
+#if _GLIBCXX_HOSTED
+#if ! defined _GLIBCXX_NO_SLEEP || defined _GLIBCXX_HAS_GTHREADS \
+ || _GLIBCXX_HAVE_LINUX_FUTEX
+namespace chrono
+{
+/// @cond undocumented
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions"
+ // Convert a chrono::duration to a relative time represented as timespec
+ // (e.g. for use with nanosleep).
+ template<typename _Rep, typename _Period>
+ [[__nodiscard__]] _GLIBCXX14_CONSTEXPR inline
+ struct ::timespec
+ __to_timeout_timespec(const duration<_Rep, _Period>& __d)
+ {
+ struct ::timespec __ts{};
+
+ if (__d < __d.zero()) // Negative timeouts don't make sense.
+ return __ts;
+
+ if constexpr (ratio_greater<_Period, ratio<1>>::value
+ || treat_as_floating_point<_Rep>::value)
+ {
+ // Converting from e.g. chrono::hours::max() to chrono::seconds
+ // would evaluate LLONG_MAX * 3600 which would overflow.
+ // Limit to chrono::seconds::max().
+ chrono::duration<double> __fmax(chrono::seconds::max());
+ if (__d > __fmax) [[__unlikely__]]
+ return chrono::__to_timeout_timespec(chrono::seconds::max());
+ }
+
+ auto __s = chrono::duration_cast<chrono::seconds>(__d);
+
+ if constexpr (is_integral<time_t>::value) // POSIX.1-2001 allows floating
+ {
+ // Also limit to time_t maximum (only relevant for 32-bit time_t).
+ constexpr auto __tmax = numeric_limits<time_t>::max();
+ if (__s.count() > __tmax) [[__unlikely__]]
+ {
+ __ts.tv_sec = __tmax;
+ return __ts;
+ }
+ }
+
+ auto __ns = chrono::duration_cast<chrono::nanoseconds>(__d - __s);
+
+ if constexpr (treat_as_floating_point<_Rep>::value)
+ if (__ns.count() > 999999999) [[__unlikely__]]
+ __ns = chrono::nanoseconds(999999999);
+
+ __ts.tv_sec = static_cast<time_t>(__s.count());
+ __ts.tv_nsec = static_cast<long>(__ns.count());
+ return __ts;
+ }
+#pragma GCC diagnostic pop
+
+ // Convert a chrono::time_point to an absolute time represented as timespec.
+ // All times before the epoch get converted to the epoch, so this assumes
+ // that we only use it for clocks where that's true.
+ // It should be safe to use this for system_clock and steady_clock.
+ template<typename _Clock, typename _Dur>
+ [[__nodiscard__]] _GLIBCXX14_CONSTEXPR inline
+ struct ::timespec
+ __to_timeout_timespec(const time_point<_Clock, _Dur>& __t)
+ {
+ return chrono::__to_timeout_timespec(__t.time_since_epoch());
+ }
+
+/// @endcond
+} // namespace chrono
+#endif // !NO_SLEEP || HAS_GTHREADS || HAVE_LINUX_FUTEX
+#endif // HOSTED
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index b7f6f5f..3b1f586 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -37,7 +37,6 @@
#if __cplusplus >= 202002L
#include <sstream> // ostringstream
-#include <iomanip> // setw, setfill
#include <format>
#include <charconv> // from_chars
#include <stdexcept> // __sso_string
@@ -189,11 +188,6 @@ namespace __format
{
[[noreturn,__gnu__::__always_inline__]]
inline void
- __no_timezone_available()
- { __throw_format_error("format error: no timezone available for %Z or %z"); }
-
- [[noreturn,__gnu__::__always_inline__]]
- inline void
__not_valid_for_duration()
{ __throw_format_error("format error: chrono-format-spec not valid for "
"chrono::duration"); }
@@ -204,45 +198,355 @@ namespace __format
{ __throw_format_error("format error: chrono-format-spec not valid for "
"argument type"); }
+ // Represents the information provided by a chrono type.
+ // e.g. month_weekday has month and weekday but no year or time of day,
+ // hh_mm_ss has time of day but no date, sys_time is time_point+timezone.
+ enum class _ChronoParts : unsigned short {
+ _None = 0, _TotalSeconds = 1u, _Subseconds = 1u << 2,
+
+ // time since epoch
+ _EpochUnits = 1u << 3, _UnitSuffix = 1u << 4,
+ _EpochSeconds = _EpochUnits | _TotalSeconds,
+
+ // local (wall) time
+ _LocalDays = 1u << 5,
+ _LocalSeconds = _LocalDays | _TotalSeconds,
+
+ _Year = 1u << 6, _Month = 1u << 7, _Day = 1u << 8,
+ _Weekday = 1u << 9, _WeekdayIndex = 1u << 10, _DayOfYear = 1u << 11,
+ _IndexedWeekday = _Weekday | _WeekdayIndex,
+ _YearMonthDay = _Year | _Month | _Day,
+ _Date = _LocalDays | _YearMonthDay | _IndexedWeekday | _DayOfYear,
+
+ _HoursMinutesSeconds = 1u << 12,
+ _TimeOfDay = _HoursMinutesSeconds | _Subseconds,
+ _Time = _TimeOfDay | _TotalSeconds,
+ _EpochTime = _Time | _EpochUnits | _UnitSuffix,
+ _DateTime = _Date | _Time,
+
+ _ZoneAbbrev = 1u << 13, _ZoneOffset = 1u << 14,
+ _TimeZone = _ZoneAbbrev | _ZoneOffset,
+ _ZonedDateTime = _DateTime | _TimeZone,
+ };
+
+ [[__gnu__::__always_inline__]]
+ constexpr _ChronoParts
+ operator&(_ChronoParts __x, _ChronoParts __y) noexcept
+ { return static_cast<_ChronoParts>((unsigned)__x & (unsigned)__y); }
+
+ [[__gnu__::__always_inline__]]
+ constexpr _ChronoParts&
+ operator&=(_ChronoParts& __x, _ChronoParts __y) noexcept
+ { return __x = __x & __y; }
+
+ [[__gnu__::__always_inline__]]
+ constexpr _ChronoParts
+ operator|(_ChronoParts __x, _ChronoParts __y) noexcept
+ { return static_cast<_ChronoParts>((unsigned short)__x | (unsigned short)__y); }
+
+ [[__gnu__::__always_inline__]]
+ constexpr _ChronoParts&
+ operator|=(_ChronoParts& __x, _ChronoParts __y) noexcept
+ { return __x = __x | __y; }
+
+ // returns copy of x with all bits from y unset.
+ [[__gnu__::__always_inline__]]
+ constexpr _ChronoParts
+ operator-(_ChronoParts __x, _ChronoParts __y) noexcept
+ { return static_cast<_ChronoParts>((unsigned short)__x & ~(unsigned short)__y); }
+
+ // unsets all bits of x that are set in y
+ [[__gnu__::__always_inline__]]
+ constexpr _ChronoParts&
+ operator-=(_ChronoParts& __x, _ChronoParts __y) noexcept
+ { return __x = __x - __y; }
+
+ [[__gnu__::__always_inline__]]
+ constexpr bool
+ operator==(_ChronoParts __x, decltype(nullptr)) noexcept
+ { return (unsigned short)__x == 0; }
+
template<typename _CharT>
struct _ChronoSpec : _Spec<_CharT>
{
- basic_string_view<_CharT> _M_chrono_specs;
+ // When _M_prec_kind is _WP_none, the _M_prec contains the default
+ // value of fraction digits to be used for time '%S'.
- // Use one of the reserved bits in __format::_Spec<C>.
+ // Placed in tail-padding of __format::_Spec<C>.
// This indicates that a locale-dependent conversion specifier such as
// %a is used in the chrono-specs. This is not the same as the
// _Spec<C>::_M_localized member which indicates that "L" was present
// in the format-spec, e.g. "{:L%a}" is localized and locale-specific,
// but "{:L}" is only localized and "{:%a}" is only locale-specific.
- constexpr bool
- _M_locale_specific() const noexcept
- { return this->_M_reserved; }
+ unsigned _M_locale_specific : 1;
+ // Indicates if parts that are checked for ok come directly from the
+ // input, instead of being computed.
+ unsigned _M_needs_ok_check : 1;
+ // Indicates that duration should be treated as floating point.
+ unsigned _M_floating_point_rep : 1;
+ // Indicate that duration uses user-defined representation.
+ unsigned _M_custom_rep : 1;
+ unsigned _M_unused : 4;
+
+ // Chrono parts required by format specs
+ _ChronoParts _M_needed;
+ basic_string_view<_CharT> _M_chrono_specs;
- constexpr void
- _M_locale_specific(bool __b) noexcept
- { this->_M_reserved = __b; }
+ [[__gnu__::__always_inline__]]
+ constexpr bool
+ _M_needs(_ChronoParts __parts) const
+ { return (_M_needed & __parts) != 0; }
};
- // Represents the information provided by a chrono type.
- // e.g. month_weekday has month and weekday but no year or time of day,
- // hh_mm_ss has time of day but no date, sys_time is time_point+timezone.
- enum _ChronoParts {
- _Year = 1, _Month = 2, _Day = 4, _Weekday = 8, _TimeOfDay = 16,
- _TimeZone = 32,
- _Date = _Year | _Month | _Day | _Weekday,
- _DateTime = _Date | _TimeOfDay,
- _ZonedDateTime = _DateTime | _TimeZone,
- _Duration = 128 // special case
+ template<typename _CharT>
+ struct _ChronoFormats
+ {
+ using _String_view = basic_string_view<_CharT>;
+
+ static consteval
+ _String_view
+ _S_ftz() noexcept
+ { return _GLIBCXX_WIDEN("%F %T %Z"); }
+
+ static consteval
+ _String_view
+ _S_ft() noexcept
+ { return _S_ftz().substr(0, 5); }
+
+ static consteval
+ _String_view
+ _S_f() noexcept
+ { return _S_ftz().substr(0, 2); }
+
+ static consteval
+ _String_view
+ _S_t() noexcept
+ { return _S_ftz().substr(3, 2); }
+
+ static consteval
+ _String_view
+ _S_ymd() noexcept
+ { return _GLIBCXX_WIDEN("%Y/%b/%d"); }
+
+ static consteval
+ _String_view
+ _S_ym() noexcept
+ { return _S_ymd().substr(0, 5); }
+
+ static consteval
+ _String_view
+ _S_md() noexcept
+ { return _S_ymd().substr(3); }
+
+ static consteval
+ _String_view
+ _S_y() noexcept
+ { return _S_ymd().substr(0, 2); }
+
+ static consteval
+ _String_view
+ _S_m() noexcept
+ { return _S_ymd().substr(3, 2); }
+
+ static consteval
+ _String_view
+ _S_d() noexcept
+ { return _S_ymd().substr(6, 2); }
+
+ static consteval
+ _String_view
+ _S_ymwi() noexcept
+ // %\0 is extension for handling weekday index
+ { return _String_view(_GLIBCXX_WIDEN("%Y/%b/%a[%\0]"), 12); }
+
+ static consteval
+ _String_view
+ _S_mwi() noexcept
+ { return _S_ymwi().substr(3); }
+
+ static consteval
+ _String_view
+ _S_wi() noexcept
+ { return _S_ymwi().substr(6); }
+
+ static consteval
+ _String_view
+ _S_w() noexcept
+ { return _S_ymwi().substr(6, 2); }
+
+ static consteval
+ _String_view
+ _S_ymwl() noexcept
+ { return _GLIBCXX_WIDEN("%Y/%b/%a[last]"); }
+
+ static consteval
+ _String_view
+ _S_mwl() noexcept
+ { return _S_ymwl().substr(3); }
+
+ static consteval
+ _String_view
+ _S_wl() noexcept
+ { return _S_ymwl().substr(6); }
+
+ static consteval
+ _String_view
+ _S_yml() noexcept
+ { return _GLIBCXX_WIDEN("%Y/%b/last"); }
+
+ static consteval
+ _String_view
+ _S_ml() noexcept
+ { return _S_yml().substr(3); }
};
- constexpr _ChronoParts
- operator|(_ChronoParts __x, _ChronoParts __y) noexcept
- { return static_cast<_ChronoParts>((int)__x | (int)__y); }
+ template<typename _CharT>
+ struct _ChronoData
+ {
+ static constexpr unsigned _S_max_prec = 18;
+ using _Attoseconds = chrono::duration<__UINT_LEAST64_TYPE__, atto>;
+
+ using _FormatContext
+ = basic_format_context<_Sink_iter<_CharT>, _CharT>;
+ using _FormatArgs = basic_format_args<_FormatContext>;
+ static inline auto _S_args = std::make_format_args<_FormatContext>();
+
+ _ChronoData() = default;
+ _ChronoData(_ChronoData&&) = delete;
+
+ // time since epoch
+ chrono::seconds _M_eseconds;
+ // n.b. due offset being seconds or coarser, local and epoch subseconds
+ // has the same value
+ _Attoseconds _M_subseconds;
+ // _M_ereps.get(0) stores duration units
+ // _M_ereps.get(1) stores subseconds units
+ // _M_ereps.get(2) stores precision
+ _FormatArgs _M_ereps = _S_args;
+ basic_string_view<_CharT> _M_unit_suffix;
+
+ // local (wall) time
+ chrono::local_seconds _M_lseconds;
+ chrono::local_days _M_ldays;
+
+ chrono::year _M_year;
+ chrono::month _M_month;
+ chrono::day _M_day;
+ chrono::weekday _M_weekday;
+ unsigned char _M_weekday_index;
+ chrono::days _M_day_of_year;
+
+ bool _M_is_neg;
+ chrono::hours _M_hours;
+ chrono::minutes _M_minutes;
+ chrono::seconds _M_seconds;
+
+ chrono::seconds _M_zone_offset;
+ basic_string_view<_CharT> _M_zone_abbrev;
+ const char* _M_zone_cstr = "";
+
+ template<typename _YearMonth>
+ [[__gnu__::__always_inline__]]
+ _ChronoParts
+ _M_fill_year_month(const _YearMonth& __ym, _ChronoParts __parts)
+ {
+ _M_year = __ym.year();
+ __parts -= _ChronoParts::_Year;
+ _M_month = __ym.month();
+ __parts -= _ChronoParts::_Month;
+ return __parts;
+ }
- constexpr _ChronoParts&
- operator|=(_ChronoParts& __x, _ChronoParts __y) noexcept
- { return __x = __x | __y; }
+ [[__gnu__::__always_inline__]]
+ _ChronoParts
+ _M_fill_day(chrono::day __d, _ChronoParts __parts)
+ {
+ _M_day = __d;
+ __parts -= _ChronoParts::_Day;
+ _M_weekday_index = ((unsigned)__d + 6u) / 7u;
+ __parts -= _ChronoParts::_WeekdayIndex;
+ return __parts;
+ }
+
+ [[__gnu__::__always_inline__]]
+ _ChronoParts
+ _M_fill_weekday(chrono::weekday_indexed __wi, _ChronoParts __parts)
+ {
+ _M_weekday = __wi.weekday();
+ __parts -= _ChronoParts::_Weekday;
+ _M_weekday_index = __wi.index();
+ __parts -= _ChronoParts::_WeekdayIndex;
+ return __parts;
+ }
+
+ // pre: _M_year is set
+ [[__gnu__::__always_inline__]]
+ _ChronoParts
+ _M_fill_aux(chrono::local_days __ld, _ChronoParts __parts)
+ {
+ using namespace chrono;
+ if ((__parts & _ChronoParts::_Weekday) != 0)
+ _M_weekday = weekday(__ld);
+ __parts -= _ChronoParts::_Weekday;
+ if ((__parts & _ChronoParts::_DayOfYear) != 0)
+ // See "Calculating Ordinal Dates" at
+ // https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes
+ _M_day_of_year = __ld - local_days(_M_year/January/0);
+ __parts -= _ChronoParts::_DayOfYear;
+ return __parts;
+ }
+
+ // pre: _M_year is set
+ [[__gnu__::__always_inline__]]
+ _ChronoParts
+ _M_fill_ldays(chrono::local_days __ld, _ChronoParts __parts)
+ {
+ _M_ldays = __ld;
+ __parts -= _ChronoParts::_LocalDays;
+ return _M_fill_aux(__ld, __parts);
+ }
+
+ void
+ _M_fill_time(chrono::seconds __d)
+ {
+ chrono::hh_mm_ss<chrono::seconds> __hms(__d);
+ _M_hours = __hms.hours();
+ _M_minutes = __hms.minutes();
+ _M_seconds = __hms.seconds();
+ }
+
+ void
+ _M_fill_date_time(chrono::local_seconds __ls, _ChronoParts __parts)
+ {
+ _M_ldays = chrono::floor<chrono::days>(__ls);
+ __parts -= _ChronoParts::_LocalDays;
+ if ((__parts & _ChronoParts::_HoursMinutesSeconds) != 0)
+ _M_fill_time(_M_lseconds - _M_ldays);
+
+ if ((__parts & _ChronoParts::_Date) != 0)
+ {
+ const chrono::year_month_day __ymd(_M_ldays);
+ _M_fill_year_month(__ymd, __parts);
+ _M_fill_day(__ymd.day(), __parts);
+ _M_fill_aux(_M_ldays, __parts);
+ }
+ }
+
+ void
+ _M_fill_zone(const char* __abbrev, const wchar_t* __wabbrev)
+ {
+ if constexpr (is_same_v<_CharT, char>)
+ _M_zone_abbrev = __abbrev;
+ else
+ _M_zone_abbrev = __wabbrev;
+ _M_zone_cstr = __abbrev;
+ }
+
+ [[__gnu__::__always_inline__]]
+ void
+ _M_fill_utc_zone()
+ { _M_fill_zone("UTC", L"UTC"); }
+ };
// TODO rename this to chrono::__formatter? or chrono::__detail::__formatter?
template<typename _CharT>
@@ -251,270 +555,300 @@ namespace __format
using __string_view = basic_string_view<_CharT>;
using __string = basic_string<_CharT>;
- template<typename _ParseContext>
- constexpr typename _ParseContext::iterator
- _M_parse(_ParseContext& __pc, _ChronoParts __parts)
- {
- auto __first = __pc.begin();
- auto __last = __pc.end();
-
- _ChronoSpec<_CharT> __spec{};
-
- auto __finalize = [this, &__spec] {
- _M_spec = __spec;
- };
-
- auto __finished = [&] {
- if (__first == __last || *__first == '}')
- {
- __finalize();
- return true;
- }
- return false;
- };
+ __formatter_chrono() = default;
- if (__finished())
- return __first;
-
- __first = __spec._M_parse_fill_and_align(__first, __last);
- if (__finished())
- return __first;
+ constexpr explicit
+ __formatter_chrono(_ChronoSpec<_CharT> __spec) noexcept
+ : _M_spec(__spec)
+ { }
- __first = __spec._M_parse_width(__first, __last, __pc);
- if (__finished())
- return __first;
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ _M_parse(basic_format_parse_context<_CharT>& __pc, _ChronoParts __parts,
+ const _ChronoSpec<_CharT>& __def)
+ {
+ auto __first = __pc.begin();
+ auto __last = __pc.end();
+
+ _ChronoSpec<_CharT> __spec = __def;
+
+ auto __finalize = [this, &__spec, &__def] {
+ using enum _ChronoParts;
+ _ChronoParts __checked
+ = __spec._M_debug ? _YearMonthDay|_IndexedWeekday
+ : _Month|_Weekday;
+ // n.b. for calendar types __def._M_needed contains only parts
+ // copied from the input, remaining ones are computed, and thus ok
+ __spec._M_needs_ok_check
+ = __spec._M_needs(__def._M_needed & __checked);
+ _M_spec = __spec;
+ };
- if (__parts & _ChronoParts::_Duration)
+ auto __finished = [&] {
+ if (__first == __last || *__first == '}')
{
- __first = __spec._M_parse_precision(__first, __last, __pc);
- if (__finished())
- return __first;
+ __finalize();
+ return true;
}
+ return false;
+ };
- __first = __spec._M_parse_locale(__first, __last);
- if (__finished())
- return __first;
+ if (__finished())
+ return __first;
- // Everything up to the end of the string or the first '}' is a
- // chrono-specs string. Check it is valid.
- {
- __string_view __str(__first, __last - __first);
- auto __end = __str.find('}');
- if (__end != __str.npos)
- {
- __str.remove_suffix(__str.length() - __end);
- __last = __first + __end;
- }
- if (__str.find('{') != __str.npos)
- __throw_format_error("chrono format error: '{' in chrono-specs");
- }
+ __first = __spec._M_parse_fill_and_align(__first, __last);
+ if (__finished())
+ return __first;
- // Parse chrono-specs in [first,last), checking each conversion-spec
- // against __parts (so fail for %Y if no year in parts).
- // Save range in __spec._M_chrono_specs.
+ __first = __spec._M_parse_width(__first, __last, __pc);
+ if (__finished())
+ return __first;
- const auto __chrono_specs = __first++; // Skip leading '%'
- if (*__chrono_specs != '%')
- __throw_format_error("chrono format error: no '%' at start of "
- "chrono-specs");
+ if (*__first == '.')
+ {
+ if ((__parts & _ChronoParts::_EpochUnits) == 0
+ || !__spec._M_floating_point_rep)
+ __throw_format_error("format error: invalid precision for duration");
+
+ // Precision is allowed, but value is ignored.
+ __first = _Spec<_CharT>()._M_parse_precision(__first, __last, __pc);
+ // Still inditate that there was user supplied precision.
+ __spec._M_prec_kind = _WP_value;
+ if (__finished())
+ return __first;
+ }
- _CharT __mod{};
- bool __conv = true;
- int __needed = 0;
- bool __locale_specific = false;
+ __spec._M_localized = false;
+ __first = __spec._M_parse_locale(__first, __last);
+ if (__finished())
+ return __first;
- while (__first != __last)
+ // Everything up to the end of the string or the first '}' is a
+ // chrono-specs string. Check it is valid.
+ {
+ __string_view __str(__first, __last - __first);
+ auto __end = __str.find('}');
+ if (__end != __str.npos)
{
- enum _Mods { _Mod_none, _Mod_E, _Mod_O, _Mod_E_O };
- _Mods __allowed_mods = _Mod_none;
-
- _CharT __c = *__first++;
- switch (__c)
- {
- case 'a':
- case 'A':
- __needed = _Weekday;
- __locale_specific = true;
- break;
- case 'b':
- case 'h':
- case 'B':
- __needed = _Month;
- __locale_specific = true;
- break;
- case 'c':
- __needed = _DateTime;
- __allowed_mods = _Mod_E;
- __locale_specific = true;
- break;
- case 'C':
- __needed = _Year;
- __allowed_mods = _Mod_E;
- break;
- case 'd':
- case 'e':
- __needed = _Day;
- __allowed_mods = _Mod_O;
- break;
- case 'D':
- case 'F':
- __needed = _Date;
- break;
- case 'g':
- case 'G':
- __needed = _Date;
- break;
- case 'H':
- case 'I':
- __needed = _TimeOfDay;
- __allowed_mods = _Mod_O;
- break;
- case 'j':
- if (!(__parts & _Duration))
- __needed = _Date;
- break;
- case 'm':
- __needed = _Month;
- __allowed_mods = _Mod_O;
- break;
- case 'M':
- __needed = _TimeOfDay;
- __allowed_mods = _Mod_O;
- break;
- case 'p':
- case 'r':
- __locale_specific = true;
- [[fallthrough]];
- case 'R':
- case 'T':
- __needed = _TimeOfDay;
- break;
- case 'q':
- case 'Q':
- __needed = _Duration;
- break;
- case 'S':
- __needed = _TimeOfDay;
- __allowed_mods = _Mod_O;
- break;
- case 'u':
- case 'w':
- __needed = _Weekday;
- __allowed_mods = _Mod_O;
- break;
- case 'U':
- case 'V':
- case 'W':
- __needed = _Date;
- __allowed_mods = _Mod_O;
- break;
- case 'x':
- __needed = _Date;
- __locale_specific = true;
- __allowed_mods = _Mod_E;
- break;
- case 'X':
- __needed = _TimeOfDay;
- __locale_specific = true;
- __allowed_mods = _Mod_E;
- break;
- case 'y':
- __needed = _Year;
- __allowed_mods = _Mod_E_O;
- break;
- case 'Y':
- __needed = _Year;
- __allowed_mods = _Mod_E;
- break;
- case 'z':
- __needed = _TimeZone;
- __allowed_mods = _Mod_E_O;
- break;
- case 'Z':
- __needed = _TimeZone;
- break;
- case 'n':
- case 't':
- case '%':
- break;
- case 'O':
- case 'E':
- if (__mod) [[unlikely]]
- {
- __allowed_mods = _Mod_none;
- break;
- }
- __mod = __c;
- continue;
- default:
- __throw_format_error("chrono format error: invalid "
- " specifier in chrono-specs");
- }
+ __str.remove_suffix(__str.length() - __end);
+ __last = __first + __end;
+ }
+ if (__str.find('{') != __str.npos)
+ __throw_format_error("chrono format error: '{' in chrono-specs");
+ }
- if ((__mod == 'E' && !(__allowed_mods & _Mod_E))
- || (__mod == 'O' && !(__allowed_mods & _Mod_O)))
- __throw_format_error("chrono format error: invalid "
- " modifier in chrono-specs");
- if (__mod && __c != 'z')
- __locale_specific = true;
- __mod = _CharT();
+ // Parse chrono-specs in [first,last), checking each conversion-spec
+ // against __parts (so fail for %Y if no year in parts).
+ // Save range in __spec._M_chrono_specs.
+ __spec._M_debug = false;
+ __spec._M_locale_specific = false;
+ __spec._M_needed = _ChronoParts::_None;
+ __spec._M_chrono_specs = __string_view();
+
+ const auto __chrono_specs = __first++; // Skip leading '%'
+ if (*__chrono_specs != '%')
+ __throw_format_error("chrono format error: no '%' at start of "
+ "chrono-specs");
+
+ _CharT __mod{};
+ bool __conv = true;
+ while (__first != __last)
+ {
+ enum _Mods { _Mod_none, _Mod_E, _Mod_O, _Mod_E_O };
+ _Mods __allowed_mods = _Mod_none;
- if ((__parts & __needed) != __needed)
- __throw_format_error("chrono format error: format argument "
- "does not contain the information "
- "required by the chrono-specs");
+ _ChronoParts __needed = _ChronoParts::_None;
+ bool __locale_specific = false;
- // Scan for next '%', ignoring literal-chars before it.
- size_t __pos = __string_view(__first, __last - __first).find('%');
- if (__pos == 0)
- ++__first;
- else
- {
- if (__pos == __string_view::npos)
- {
- __first = __last;
- __conv = false;
- }
- else
- __first += __pos + 1;
- }
+ _CharT __c = *__first++;
+ switch (__c)
+ {
+ using enum _ChronoParts;
+ case 'a':
+ case 'A':
+ __needed = _Weekday;
+ __locale_specific = true;
+ break;
+ case 'b':
+ case 'h':
+ case 'B':
+ __needed = _Month;
+ __locale_specific = true;
+ break;
+ case 'c':
+ __needed = _Date|_HoursMinutesSeconds;
+ __allowed_mods = _Mod_E;
+ __locale_specific = true;
+ break;
+ case 'C':
+ __needed = _Year;
+ __allowed_mods = _Mod_E;
+ break;
+ case 'd':
+ case 'e':
+ __needed = _Day;
+ __allowed_mods = _Mod_O;
+ break;
+ case 'D':
+ case 'F':
+ __needed = _YearMonthDay;
+ break;
+ case 'g':
+ case 'G':
+ case 'V':
+ __needed = _LocalDays|_Year|_DayOfYear|_Weekday;
+ break;
+ case 'H':
+ case 'I':
+ __needed = _HoursMinutesSeconds;
+ __allowed_mods = _Mod_O;
+ break;
+ case 'j':
+ __needed = __parts & _DayOfYear;
+ // If we do not know day-of-year then we must have a duration,
+ // which is to be formatted as decimal number of days.
+ if (__needed == _None)
+ __needed = _HoursMinutesSeconds;
+ break;
+ case 'm':
+ __needed = _Month;
+ __allowed_mods = _Mod_O;
+ break;
+ case 'M':
+ __needed = _HoursMinutesSeconds;
+ __allowed_mods = _Mod_O;
+ break;
+ case 'p':
+ case 'r':
+ __locale_specific = true;
+ [[fallthrough]];
+ case 'R':
+ __needed = _HoursMinutesSeconds;
+ break;
+ case 'T':
+ __needed = _TimeOfDay;
+ break;
+ case 'q':
+ __needed = _UnitSuffix;
+ break;
+ case 'Q':
+ __needed = _EpochUnits;
+ break;
+ case 'S':
+ __needed = _TimeOfDay;
+ __allowed_mods = _Mod_O;
+ break;
+ case 'u':
+ case 'w':
+ __needed = _Weekday;
+ __allowed_mods = _Mod_O;
+ break;
+ case 'U':
+ case 'W':
+ __needed = _DayOfYear|_Weekday;
+ __allowed_mods = _Mod_O;
+ break;
+ case 'x':
+ __needed = _Date;
+ __locale_specific = true;
+ __allowed_mods = _Mod_E;
+ break;
+ case 'X':
+ __needed = _HoursMinutesSeconds;
+ __locale_specific = true;
+ __allowed_mods = _Mod_E;
+ break;
+ case 'y':
+ __needed = _Year;
+ __allowed_mods = _Mod_E_O;
+ break;
+ case 'Y':
+ __needed = _Year;
+ __allowed_mods = _Mod_E;
+ break;
+ case 'z':
+ __needed = _ZoneOffset;
+ __allowed_mods = _Mod_E_O;
+ break;
+ case 'Z':
+ __needed = _ZoneAbbrev;
+ break;
+ case 'n':
+ case 't':
+ case '%':
+ break;
+ case 'O':
+ case 'E':
+ if (__mod) [[unlikely]]
+ {
+ __allowed_mods = _Mod_none;
+ break;
+ }
+ __mod = __c;
+ continue;
+ default:
+ __throw_format_error("chrono format error: invalid specifier "
+ "in chrono-specs");
}
- // Check for a '%' conversion-spec without a type.
- if (__conv || __mod != _CharT())
- __throw_format_error("chrono format error: unescaped '%' in "
- "chrono-specs");
+ if ((__mod == 'E' && !(__allowed_mods & _Mod_E))
+ || (__mod == 'O' && !(__allowed_mods & _Mod_O)))
+ __throw_format_error("chrono format error: invalid modifier "
+ "in chrono-specs");
+ if (__mod && __c != 'z')
+ __locale_specific = true;
+ __mod = _CharT();
+
+ // localized formats do not include subseconds
+ if (__locale_specific)
+ __needed -= _ChronoParts::_Subseconds;
+
+ if ((__parts & __needed) != __needed)
+ __throw_format_error("chrono format error: format argument does "
+ "not contain the information required by the "
+ "chrono-specs");
+ __spec._M_needed |= __needed;
+ __spec._M_locale_specific |= __locale_specific;
+
+ // Scan for next '%', ignoring literal-chars before it.
+ size_t __pos = __string_view(__first, __last - __first).find('%');
+ if (__pos == 0)
+ ++__first;
+ else
+ {
+ if (__pos == __string_view::npos)
+ {
+ __first = __last;
+ __conv = false;
+ }
+ else
+ __first += __pos + 1;
+ }
+ }
+
+ // Check for a '%' conversion-spec without a type.
+ if (__conv || __mod != _CharT())
+ __throw_format_error("chrono format error: unescaped '%' in "
+ "chrono-specs");
- _M_spec = __spec;
- _M_spec._M_chrono_specs
- = __string_view(__chrono_specs, __first - __chrono_specs);
- _M_spec._M_locale_specific(__locale_specific);
+ __spec._M_chrono_specs
+ = __string_view(__chrono_specs, __first - __chrono_specs);
- return __first;
- }
+ __finalize();
+ return __first;
+ }
- // TODO this function template is instantiated for every different _Tp.
- // Consider creating a polymorphic interface for calendar types so
- // that we instantiate fewer different specializations. Similar to
- // _Sink_iter for std::format. Replace each _S_year, _S_day etc. with
- // member functions of that type.
- template<typename _Tp, typename _FormatContext>
+ // pre: !_M_spec._M_chrono_specs.empty()
+ template<typename _FormatContext>
typename _FormatContext::iterator
- _M_format(const _Tp& __t, _FormatContext& __fc,
- bool __is_neg = false) const
+ _M_format(const _ChronoData<_CharT>& __t, _FormatContext& __fc) const
{
- auto __first = _M_spec._M_chrono_specs.begin();
- const auto __last = _M_spec._M_chrono_specs.end();
- if (__first == __last)
- return _M_format_to_ostream(__t, __fc, __is_neg);
-
#if defined _GLIBCXX_USE_NL_LANGINFO_L && __CHAR_BIT__ == 8
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3565. Handling of encodings in localized formatting
// of chrono types is underspecified
if constexpr (is_same_v<_CharT, char>)
if constexpr (__unicode::__literal_encoding_is_utf8())
- if (_M_spec._M_localized && _M_spec._M_locale_specific())
+ if (_M_spec._M_localized && _M_spec._M_locale_specific)
{
extern locale __with_encoding_conversion(const locale&);
@@ -522,36 +856,207 @@ namespace __format
// in the locale's encoding to UTF-8.
locale __loc = __fc.locale();
if (__loc != locale::classic())
- __fc._M_loc = __with_encoding_conversion(__loc);
+ __fc._M_loc = __with_encoding_conversion(__loc);
}
#endif
- _Sink_iter<_CharT> __out;
- __format::_Str_sink<_CharT> __sink;
- bool __write_direct = false;
- if constexpr (is_same_v<typename _FormatContext::iterator,
- _Sink_iter<_CharT>>)
- {
- if (_M_spec._M_width_kind == __format::_WP_none)
+ const size_t __padwidth = _M_spec._M_get_width(__fc);
+ if (__padwidth == 0)
+ return _M_format_to(__t, __fc.out(), __fc);
+
+ using _Out = typename _FormatContext::iterator;
+ _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth);
+ _M_format_to(__t, __sink.out(), __fc);
+ return __sink._M_finish(_M_spec._M_align, _M_spec._M_fill);
+ }
+
+ _ChronoSpec<_CharT> _M_spec;
+
+ protected:
+ static constexpr const _CharT* _S_chars
+ = _GLIBCXX_WIDEN("0123456789.Lf:/ +-{}");
+ static constexpr _CharT _S_dot = _S_chars[10];
+ static constexpr _CharT _S_colon = _S_chars[13];
+ static constexpr _CharT _S_slash = _S_chars[14];
+ static constexpr _CharT _S_space = _S_chars[15];
+ static constexpr const _CharT* _S_fp_fmt = _S_chars + 11;
+ static constexpr const _CharT* _S_plus_minus = _S_chars + 16;
+ static constexpr const _CharT* _S_minus_empty_spec = _S_chars + 17;
+ static constexpr const _CharT* _S_empty_spec = _S_chars + 18;
+
+ [[__gnu__::__always_inline__]]
+ static _Runtime_format_string<_CharT>
+ _S_empty_fs()
+ { return _Runtime_format_string<_CharT>(_S_empty_spec); }
+
+ static constexpr const _CharT* _S_weekdays[]
+ {
+ _GLIBCXX_WIDEN("Sunday"),
+ _GLIBCXX_WIDEN("Monday"),
+ _GLIBCXX_WIDEN("Tuesday"),
+ _GLIBCXX_WIDEN("Wednesday"),
+ _GLIBCXX_WIDEN("Thursday"),
+ _GLIBCXX_WIDEN("Friday"),
+ _GLIBCXX_WIDEN("Saturday"),
+ };
+
+ static constexpr const _CharT* _S_months[]
+ {
+ _GLIBCXX_WIDEN("January"),
+ _GLIBCXX_WIDEN("February"),
+ _GLIBCXX_WIDEN("March"),
+ _GLIBCXX_WIDEN("April"),
+ _GLIBCXX_WIDEN("May"),
+ _GLIBCXX_WIDEN("June"),
+ _GLIBCXX_WIDEN("July"),
+ _GLIBCXX_WIDEN("August"),
+ _GLIBCXX_WIDEN("September"),
+ _GLIBCXX_WIDEN("October"),
+ _GLIBCXX_WIDEN("November"),
+ _GLIBCXX_WIDEN("December"),
+ };
+
+ private:
+ template<typename _OutIter>
+ _OutIter
+ _M_write(_OutIter __out, const locale& __loc, __string_view __s) const
+ {
+#if defined _GLIBCXX_USE_NL_LANGINFO_L && __CHAR_BIT__ == 8
+ __sso_string __buf;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3565. Handling of encodings in localized formatting
+ // of chrono types is underspecified
+ if constexpr (is_same_v<_CharT, char>)
+ if constexpr (__unicode::__literal_encoding_is_utf8())
+ if (_M_spec._M_localized && _M_spec._M_locale_specific
+ && __loc != locale::classic())
{
- __out = __fc.out();
- __write_direct = true;
+ extern string_view
+ __locale_encoding_to_utf8(const locale&, string_view, void*);
+
+ __s = __locale_encoding_to_utf8(__loc, __s, &__buf);
}
- else
- __out = __sink.out();
+#endif
+ return __format::__write(std::move(__out), __s);
+ }
+
+ [[__gnu__::__always_inline__]]
+ static bool
+ _S_localized_spec(_CharT __conv, _CharT __mod)
+ {
+ switch (__conv)
+ {
+ case 'a':
+ case 'A':
+ case 'b':
+ case 'B':
+ case 'c':
+ case 'h':
+ case 'p':
+ case 'r':
+ case 'x':
+ case 'X':
+ return true;
+ case 'z':
+ return false;
+ default:
+ return (bool)__mod;
+ };
+ }
+
+ // Use the formatting locale's std::time_put facet to produce
+ // a locale-specific representation.
+ template<typename _Iter>
+ _Iter
+ _M_locale_fmt(_Iter __out, const locale& __loc, const struct tm& __tm,
+ char __fmt, char __mod) const
+ {
+ basic_ostringstream<_CharT> __os;
+ __os.imbue(__loc);
+ const auto& __tp = use_facet<time_put<_CharT>>(__loc);
+ __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod);
+ if (__os)
+ __out = _M_write(std::move(__out), __loc, __os.view());
+ return __out;
+ }
+
+ __string_view
+ _M_check_ok(const _ChronoData<_CharT>& __t, _CharT& __conv) const
+ {
+ if (!_M_spec._M_debug)
+ {
+ switch (__conv)
+ {
+ case 'a':
+ case 'A':
+ if (!__t._M_weekday.ok()) [[unlikely]]
+ __throw_format_error("format error: invalid weekday");
+ break;
+ case 'b':
+ case 'h':
+ case 'B':
+ if (!__t._M_month.ok()) [[unlikely]]
+ __throw_format_error("format error: invalid month");
+ break;
+ default:
+ break;
}
- else
- __out = __sink.out();
+ return __string_view();
+ }
- // formatter<duration> passes the correct value of __is_neg
- // for durations but for hh_mm_ss we decide it here.
- if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>)
- __is_neg = __t.is_negative();
+ switch (__conv)
+ {
+ // %\0 is extension for handling weekday index
+ case '\0':
+ if (__t._M_weekday_index < 1 || __t._M_weekday_index > 5) [[unlikely]]
+ return _GLIBCXX_WIDEN("index");
+ break;
+ case 'a':
+ case 'A':
+ if (!__t._M_weekday.ok()) [[unlikely]]
+ {
+ __conv = 'w'; // print as decimal number
+ return _GLIBCXX_WIDEN("weekday");
+ }
+ break;
+ case 'b':
+ case 'h':
+ case 'B':
+ if (!__t._M_month.ok()) [[unlikely]]
+ {
+ __conv = 'm'; // print as decimal number
+ return _GLIBCXX_WIDEN("month");
+ }
+ break;
+ case 'd':
+ case 'e':
+ if (!__t._M_day.ok()) [[unlikely]]
+ return _GLIBCXX_WIDEN("day");
+ break;
+ case 'F':
+ if (!(__t._M_year/__t._M_month/__t._M_day).ok()) [[unlikely]]
+ return _GLIBCXX_WIDEN("date");
+ break;
+ case 'Y':
+ if (!__t._M_year.ok()) [[unlikely]]
+ return _GLIBCXX_WIDEN("year");
+ break;
+ default:
+ break;
+ }
+ return __string_view();
+ }
- auto __print_sign = [&__is_neg, &__out] {
- if constexpr (chrono::__is_duration_v<_Tp>
- || __is_specialization_of<_Tp, chrono::hh_mm_ss>)
- if (__is_neg)
+ template<typename _OutIter, typename _FormatContext>
+ _OutIter
+ _M_format_to(const _ChronoData<_CharT>& __t, _OutIter __out,
+ _FormatContext& __fc) const
+ {
+ auto __first = _M_spec._M_chrono_specs.begin();
+ const auto __last = _M_spec._M_chrono_specs.end();
+
+ auto __print_sign = [__is_neg = __t._M_is_neg, &__out] () mutable {
+ if (__is_neg)
{
*__out++ = _S_plus_minus[1];
__is_neg = false;
@@ -559,6 +1064,36 @@ namespace __format
return std::move(__out);
};
+ struct tm __tm{};
+ bool __use_locale_fmt = false;
+ if (_M_spec._M_localized && _M_spec._M_locale_specific)
+ if (__fc.locale() != locale::classic())
+ {
+ __use_locale_fmt = true;
+
+ __tm.tm_year = (int)__t._M_year - 1900;
+ __tm.tm_yday = __t._M_day_of_year.count();
+ __tm.tm_mon = (unsigned)__t._M_month - 1;
+ __tm.tm_mday = (unsigned)__t._M_day;
+ __tm.tm_wday = __t._M_weekday.c_encoding();
+ __tm.tm_hour = __t._M_hours.count();
+ __tm.tm_min = __t._M_minutes.count();
+ __tm.tm_sec = __t._M_seconds.count();
+
+ // Some locales use %Z in their %c format but we don't want strftime
+ // to use the system's local time zone (from /etc/localtime or $TZ)
+ // as the output for %Z. Setting tm_isdst to -1 says there is no
+ // time zone info available for the time in __tm.
+ __tm.tm_isdst = -1;
+
+#ifdef _GLIBCXX_USE_STRUCT_TM_TM_ZONE
+ // POSIX.1-2024 adds tm.tm_zone which will be used for %Z.
+ // BSD has had tm_zone since 1987 but as char* so cast away const.
+ if (__t._M_zone_cstr)
+ __tm.tm_zone = const_cast<char*>(__t._M_zone_cstr);
+#endif
+ }
+
// Characters to output for "%n", "%t" and "%%" specifiers.
constexpr const _CharT* __literals = _GLIBCXX_WIDEN("\n\t%");
@@ -568,100 +1103,101 @@ namespace __format
do
{
_CharT __c = *__first++;
- switch (__c)
+ __string_view __invalid;
+ if (_M_spec._M_needs_ok_check)
+ __invalid = _M_check_ok(__t, __c);
+
+ if (__invalid.empty() &&__use_locale_fmt
+ && _S_localized_spec(__c, __mod)) [[unlikely]]
+ __out = _M_locale_fmt(std::move(__out), __fc.locale(),
+ __tm, __c, __mod);
+ else switch (__c)
{
+ // %\0 is extension for handling weekday index
+ case '\0':
+ __out = _M_wi(__t._M_weekday_index, std::move(__out));
+ break;
case 'a':
case 'A':
- __out = _M_a_A(__t, std::move(__out), __fc, __c == 'A');
+ __out = _M_a_A(__t._M_weekday, std::move(__out), __c == 'A');
break;
case 'b':
case 'h':
case 'B':
- __out = _M_b_B(__t, std::move(__out), __fc, __c == 'B');
+ __out = _M_b_B(__t._M_month, std::move(__out), __c == 'B');
break;
case 'c':
- __out = _M_c(__t, std::move(__out), __fc, __mod == 'E');
+ __out = _M_c(__t, std::move(__out));
break;
case 'C':
case 'y':
case 'Y':
- __out = _M_C_y_Y(__t, std::move(__out), __fc, __c, __mod);
+ __out = _M_C_y_Y(__t._M_year, std::move(__out), __c);
break;
case 'd':
case 'e':
- __out = _M_d_e(__t, std::move(__out), __fc, __c, __mod == 'O');
+ __out = _M_d_e(__t._M_day, std::move(__out), __c);
break;
case 'D':
- __out = _M_D(__t, std::move(__out), __fc);
+ case 'x':
+ __out = _M_D_x(__t, std::move(__out));
break;
case 'F':
- __out = _M_F(__t, std::move(__out), __fc);
+ __out = _M_F(__t, std::move(__out));
break;
case 'g':
case 'G':
- __out = _M_g_G(__t, std::move(__out), __fc, __c == 'G');
+ case 'V':
+ __out = _M_g_G_V(__t, std::move(__out), __c);
break;
case 'H':
case 'I':
- __out = _M_H_I(__t, __print_sign(), __fc, __c, __mod == 'O');
+ __out = _M_H_I(__t._M_hours, __print_sign(), __c);
break;
case 'j':
- __out = _M_j(__t, __print_sign(), __fc);
+ __out = _M_j(__t, __print_sign());
break;
case 'm':
- __out = _M_m(__t, std::move(__out), __fc, __mod == 'O');
+ __out = _M_m(__t._M_month, std::move(__out));
break;
case 'M':
- __out = _M_M(__t, __print_sign(), __fc, __mod == 'O');
+ __out = _M_M(__t._M_minutes, __print_sign());
break;
case 'p':
- __out = _M_p(__t, std::move(__out), __fc);
+ __out = _M_p(__t._M_hours, std::move(__out));
break;
case 'q':
- __out = _M_q(__t, std::move(__out), __fc);
+ __out = _M_q(__t._M_unit_suffix, std::move(__out));
break;
case 'Q':
- // %Q The duration's numeric value.
- if constexpr (chrono::__is_duration_v<_Tp>)
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 4118. How should duration formatters format custom rep?
- __out = std::format_to(__print_sign(), _S_empty_spec,
- +__t.count());
- else
- __throw_format_error("chrono format error: argument is "
- "not a duration");
+ __out = _M_Q(__t, __print_sign(), __fc);
break;
case 'r':
- __out = _M_r(__t, __print_sign(), __fc);
+ __out = _M_r(__t, __print_sign());
break;
case 'R':
+ case 'X':
+ __out = _M_R_X(__t, __print_sign(), __c != 'R');
+ break;
case 'T':
- __out = _M_R_T(__t, __print_sign(), __fc, __c == 'T');
+ __out = _M_T(__t, __print_sign(), __fc);
break;
case 'S':
- __out = _M_S(__t, __print_sign(), __fc, __mod == 'O');
+ __out = _M_S(__t, __print_sign(), __fc, __mod != 'O');
break;
case 'u':
case 'w':
- __out = _M_u_w(__t, std::move(__out), __fc, __c, __mod == 'O');
+ __out = _M_u_w(__t._M_weekday, std::move(__out), __c);
break;
case 'U':
- case 'V':
case 'W':
- __out = _M_U_V_W(__t, std::move(__out), __fc, __c,
- __mod == 'O');
- break;
- case 'x':
- __out = _M_x(__t, std::move(__out), __fc, __mod == 'E');
- break;
- case 'X':
- __out = _M_X(__t, __print_sign(), __fc, __mod == 'E');
+ __out = _M_U_W(__t, std::move(__out), __c);
break;
case 'z':
- __out = _M_z(__t, std::move(__out), __fc, (bool)__mod);
+ __out = _M_z(__t._M_zone_offset, std::move(__out), (bool)__mod);
break;
case 'Z':
- __out = _M_Z(__t, std::move(__out), __fc);
+ __out = _M_Z(__t._M_zone_abbrev, std::move(__out));
break;
case 'n':
*__out++ = __literals[0];
@@ -680,6 +1216,14 @@ namespace __format
__first = __last;
break;
}
+
+ if (!__invalid.empty())
+ {
+ constexpr __string_view __pref = _GLIBCXX_WIDEN(" is not a valid ");
+ __out = __format::__write(std::move(__out), __pref);
+ __out = __format::__write(std::move(__out), __invalid);
+ }
+
__mod = _CharT();
// Scan for next '%' and write out everything before it.
__string_view __str(__first, __last - __first);
@@ -699,241 +1243,64 @@ namespace __format
}
}
while (__first != __last);
-
- if constexpr (is_same_v<typename _FormatContext::iterator,
- _Sink_iter<_CharT>>)
- if (__write_direct)
- return __out;
-
- auto __str = std::move(__sink).get();
- return __format::__write_padded_as_spec(__str, __str.size(),
- __fc, _M_spec);
+ return std::move(__out);
}
- _ChronoSpec<_CharT> _M_spec;
-
- private:
- // Return the formatting locale.
- template<typename _FormatContext>
- std::locale
- _M_locale(_FormatContext& __fc) const
- {
- if (!_M_spec._M_localized)
- return std::locale::classic();
- else
- return __fc.locale();
- }
-
- // Format for empty chrono-specs, e.g. "{}" (C++20 [time.format] p6).
- // TODO: consider moving body of every operator<< into this function
- // and use std::format("{}", t) to implement those operators. That
- // would avoid std::format("{}", t) calling operator<< which calls
- // std::format again.
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_format_to_ostream(const _Tp& __t, _FormatContext& __fc,
- bool __is_neg) const
- {
- using ::std::chrono::__detail::__utc_leap_second;
- using ::std::chrono::__detail::__local_time_fmt;
-
- basic_ostringstream<_CharT> __os;
- __os.imbue(_M_locale(__fc));
-
- if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
- {
- // Format as "{:L%F %T}"
- auto __days = chrono::floor<chrono::days>(__t._M_time);
- __os << chrono::year_month_day(__days) << ' '
- << chrono::hh_mm_ss(__t._M_time - __days);
-
- // For __local_time_fmt the __is_neg flags says whether to
- // append " %Z" to the result.
- if (__is_neg)
- {
- if (!__t._M_abbrev) [[unlikely]]
- __format::__no_timezone_available();
- else if constexpr (is_same_v<_CharT, char>)
- __os << ' ' << *__t._M_abbrev;
- else
- {
- __os << L' ';
- for (char __c : *__t._M_abbrev)
- __os << __c;
- }
- }
- }
- else
- {
- if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
- __os << __t._M_date << ' ' << __t._M_time;
- else if constexpr (chrono::__is_time_point_v<_Tp>)
- {
- // Need to be careful here because not all specializations
- // of chrono::sys_time can be written to an ostream.
- // For the specializations of time_point that can be
- // formatted with an empty chrono-specs, either it's a
- // sys_time with period greater or equal to days:
- if constexpr (is_convertible_v<_Tp, chrono::sys_days>)
- __os << _S_date(__t);
- else // Or it's formatted as "{:L%F %T}":
- {
- auto __days = chrono::floor<chrono::days>(__t);
- __os << chrono::year_month_day(__days) << ' '
- << chrono::hh_mm_ss(__t - __days);
- }
- }
- else
- {
- if constexpr (chrono::__is_duration_v<_Tp>)
- if (__is_neg) [[unlikely]]
- __os << _S_plus_minus[1];
- __os << __t;
- }
- }
-
- auto __str = std::move(__os).str();
- return __format::__write_padded_as_spec(__str, __str.size(),
- __fc, _M_spec);
- }
-
- static constexpr const _CharT* _S_chars
- = _GLIBCXX_WIDEN("0123456789+-:/ {}");
- static constexpr const _CharT* _S_plus_minus = _S_chars + 10;
- static constexpr _CharT _S_colon = _S_chars[12];
- static constexpr _CharT _S_slash = _S_chars[13];
- static constexpr _CharT _S_space = _S_chars[14];
- static constexpr const _CharT* _S_empty_spec = _S_chars + 15;
-
template<typename _OutIter>
_OutIter
- _M_write(_OutIter __out, const locale& __loc, __string_view __s) const
+ _M_wi(unsigned __wi, _OutIter __out) const
{
-#if defined _GLIBCXX_USE_NL_LANGINFO_L && __CHAR_BIT__ == 8
- __sso_string __buf;
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 3565. Handling of encodings in localized formatting
- // of chrono types is underspecified
- if constexpr (is_same_v<_CharT, char>)
- if constexpr (__unicode::__literal_encoding_is_utf8())
- if (_M_spec._M_localized && _M_spec._M_locale_specific()
- && __loc != locale::classic())
- {
- extern string_view
- __locale_encoding_to_utf8(const locale&, string_view, void*);
-
- __s = __locale_encoding_to_utf8(__loc, __s, &__buf);
- }
-#endif
- return __format::__write(std::move(__out), __s);
+ // %\0 Extension to format weekday index, used only by empty format spec
+ _CharT __buf[3];
+ __out = __format::__write(std::move(__out), _S_str_d1(__buf, __wi));
+ return std::move(__out);
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_a_A(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __full) const
+ template<typename _OutIter>
+ _OutIter
+ _M_a_A(chrono::weekday __wd, _OutIter __out, bool __full) const
{
// %a Locale's abbreviated weekday name.
// %A Locale's full weekday name.
- chrono::weekday __wd = _S_weekday(__t);
- if (!__wd.ok())
- __throw_format_error("format error: invalid weekday");
-
- locale __loc = _M_locale(__ctx);
- const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
- const _CharT* __days[7];
- if (__full)
- __tp._M_days(__days);
- else
- __tp._M_days_abbreviated(__days);
- __string_view __str(__days[__wd.c_encoding()]);
- return _M_write(std::move(__out), __loc, __str);
+ __string_view __str = _S_weekdays[__wd.c_encoding()];
+ if (!__full)
+ __str = __str.substr(0, 3);
+ return __format::__write(std::move(__out), __str);
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_b_B(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __full) const
+ template<typename _OutIter>
+ _OutIter
+ _M_b_B(chrono::month __m, _OutIter __out, bool __full) const
{
// %b Locale's abbreviated month name.
// %B Locale's full month name.
- chrono::month __m = _S_month(__t);
- if (!__m.ok())
- __throw_format_error("format error: invalid month");
- locale __loc = _M_locale(__ctx);
- const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
- const _CharT* __months[12];
- if (__full)
- __tp._M_months(__months);
- else
- __tp._M_months_abbreviated(__months);
- __string_view __str(__months[(unsigned)__m - 1]);
- return _M_write(std::move(__out), __loc, __str);
+ __string_view __str = _S_months[(unsigned)__m - 1];
+ if (!__full)
+ __str = __str.substr(0, 3);
+ return __format::__write(std::move(__out), __str);
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_c(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __mod = false) const
+ template<typename _OutIter>
+ _OutIter
+ _M_c(const _ChronoData<_CharT>& __t, _OutIter __out) const
{
- // %c Locale's date and time representation.
- // %Ec Locale's alternate date and time representation.
-
- using namespace chrono;
- using ::std::chrono::__detail::__utc_leap_second;
- using ::std::chrono::__detail::__local_time_fmt;
-
- struct tm __tm{};
-
- // Some locales use %Z in their %c format but we don't want strftime
- // to use the system's local time zone (from /etc/localtime or $TZ)
- // as the output for %Z. Setting tm_isdst to -1 says there is no
- // time zone info available for the time in __tm.
- __tm.tm_isdst = -1;
-
-#ifdef _GLIBCXX_USE_STRUCT_TM_TM_ZONE
- // POSIX.1-2024 adds tm.tm_zone which will be used for %Z.
- // BSD has had tm_zone since 1987 but as char* so cast away const.
- if constexpr (__is_time_point_v<_Tp>)
- {
- // One of sys_time, utc_time, or local_time.
- if constexpr (!is_same_v<typename _Tp::clock, local_t>)
- __tm.tm_zone = const_cast<char*>("UTC");
- }
- else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
- {
- // local-time-format-t is used to provide time zone info for
- // one of zoned_time, tai_time, gps_time, or local_time.
- if (__t._M_abbrev)
- __tm.tm_zone = const_cast<char*>(__t._M_abbrev->c_str());
- }
- else
- __tm.tm_zone = const_cast<char*>("UTC");
-#endif
-
- auto __d = _S_days(__t); // Either sys_days or local_days.
- using _TDays = decltype(__d);
- const year_month_day __ymd(__d);
- const auto __y = __ymd.year();
- const auto __hms = _S_hms(__t);
-
- __tm.tm_year = (int)__y - 1900;
- __tm.tm_yday = (__d - _TDays(__y/January/1)).count();
- __tm.tm_mon = (unsigned)__ymd.month() - 1;
- __tm.tm_mday = (unsigned)__ymd.day();
- __tm.tm_wday = weekday(__d).c_encoding();
- __tm.tm_hour = __hms.hours().count();
- __tm.tm_min = __hms.minutes().count();
- __tm.tm_sec = __hms.seconds().count();
-
- return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 'c',
- __mod ? 'E' : '\0');
+ // %c Locale's date and time representation, for C-locale: %a %b %e %T %Y
+ // %Ec Locale's alternate date and time representation, for C-locale same as above
+
+ __out = _M_a_A(__t._M_weekday, std::move(__out), false);
+ *__out = _S_space;
+ __out = _M_b_B(__t._M_month, std::move(++__out), false);
+ *__out = _S_space;
+ __out = _M_d_e(__t._M_day, std::move(++__out), 'e');
+ *__out = _S_space;
+ __out = _M_R_X(__t, std::move(++__out), true);
+ *__out = _S_space;
+ return _M_C_y_Y(__t._M_year, std::move(++__out), 'Y');
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_C_y_Y(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, _CharT __conv, _CharT __mod = 0) const
+ template<typename _OutIter>
+ _OutIter
+ _M_C_y_Y(chrono::year __y, _OutIter __out, _CharT __conv) const
{
// %C Year divided by 100 using floored division.
// %EC Locale's alternative preresentation of the century (era name).
@@ -943,598 +1310,486 @@ namespace __format
// %Y Year as a decimal number.
// %EY Locale's alternative full year representation.
- chrono::year __y = _S_year(__t);
-
- if (__mod && _M_spec._M_localized) [[unlikely]]
- if (auto __loc = __ctx.locale(); __loc != locale::classic())
- {
- struct tm __tm{};
- __tm.tm_year = (int)__y - 1900;
- return _M_locale_fmt(std::move(__out), __loc, __tm,
- __conv, __mod);
- }
-
- basic_string<_CharT> __s;
int __yi = (int)__y;
const bool __is_neg = __yi < 0;
__yi = __builtin_abs(__yi);
+ int __ci = __yi / 100;
+ // For floored division -123//100 is -2 and -100//100 is -1
+ if (__conv == 'C' && __is_neg && (__ci * 100) != __yi) [[unlikely]]
+ ++__ci;
- if (__conv == 'Y' || __conv == 'C')
+ if (__conv != 'y' && __ci >= 100) [[unlikely]]
+ {
+ using _FmtStr = _Runtime_format_string<_CharT>;
+ __string_view __fs = _S_minus_empty_spec + !__is_neg;
+ __out = std::format_to(std::move(__out), _FmtStr(__fs),
+ __conv == 'C' ? __ci : __yi);
+ }
+ else
{
- int __ci = __yi / 100;
- if (__is_neg) [[unlikely]]
+ _CharT __buf[5];
+ __buf[0] = _S_plus_minus[1];
+ __string_view __sv(__buf + 3, __buf + 3);
+ if (__conv != 'y')
{
- __s.assign(1, _S_plus_minus[1]);
- // For floored division -123//100 is -2 and -100//100 is -1
- if (__conv == 'C' && (__ci * 100) != __yi)
- ++__ci;
+ _S_fill_two_digits(__buf + 1, __ci);
+ __sv = __string_view(__buf + !__is_neg, __buf + 3);
}
- if (__ci >= 100) [[unlikely]]
+ if (__conv != 'C')
{
- __s += std::format(_S_empty_spec, __ci / 100);
- __ci %= 100;
+ _S_fill_two_digits(__buf + 3, __yi % 100);
+ __sv = __string_view(__sv.data(), __buf + 5);
}
- __s += _S_two_digits(__ci);
+ __out = __format::__write(std::move(__out), __sv);
}
-
- if (__conv == 'Y' || __conv == 'y')
- __s += _S_two_digits(__yi % 100);
-
- return __format::__write(std::move(__out), __string_view(__s));
+ return __out;
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_D(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext&) const
+ template<typename _OutIter>
+ _OutIter
+ _M_D_x(const _ChronoData<_CharT>& __t, _OutIter __out) const
{
- auto __ymd = _S_date(__t);
- basic_string<_CharT> __s;
-#if ! _GLIBCXX_USE_CXX11_ABI
- __s.reserve(8);
-#endif
- __s = _S_two_digits((unsigned)__ymd.month());
- __s += _S_slash;
- __s += _S_two_digits((unsigned)__ymd.day());
- __s += _S_slash;
- __s += _S_two_digits(__builtin_abs((int)__ymd.year()) % 100);
- return __format::__write(std::move(__out), __string_view(__s));
+ // %D Equivalent to %m/%d/%y
+ // %x Locale's date rep, for C-locale: %m/%d/%y
+ // %Ex Locale's alternative date representation, for C-locale same as above
+
+ auto __di = (unsigned)__t._M_day;
+ auto __mi = (unsigned)__t._M_month;
+ auto __yi = __builtin_abs((int)__t._M_year) % 100;
+
+ if (__mi >= 100 || __di >= 100) [[unlikely]]
+ {
+ using _FmtStr = _Runtime_format_string<_CharT>;
+ __string_view __fs = _GLIBCXX_WIDEN("{:02d}/{:02d}/{:02d}");
+ __out = std::format_to(std::move(__out), _FmtStr(__fs),
+ __mi, __di, __yi);
+ }
+ else
+ {
+ _CharT __buf[8];
+ __buf[2] = _S_slash;
+ __buf[5] = _S_slash;
+ __string_view __sv(__buf, __buf + 8);
+
+ _S_fill_two_digits(__buf, __mi);
+ _S_fill_two_digits(__buf + 3, __di);
+ _S_fill_two_digits(__buf + 6, __yi);
+ __out = __format::__write(std::move(__out), __sv);
+ }
+ return std::move(__out);
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_d_e(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
+ template<typename _OutIter>
+ _OutIter
+ _M_d_e(chrono::day __d, _OutIter __out, _CharT __conv) const
{
// %d The day of month as a decimal number.
// %Od Locale's alternative representation.
// %e Day of month as decimal number, padded with space.
// %Oe Locale's alternative digits.
- chrono::day __d = _S_day(__t);
unsigned __i = (unsigned)__d;
- if (__mod && _M_spec._M_localized) [[unlikely]]
- if (auto __loc = __ctx.locale(); __loc != locale::classic())
- {
- struct tm __tm{};
- __tm.tm_mday = __i;
- return _M_locale_fmt(std::move(__out), __loc, __tm,
- (char)__conv, 'O');
- }
-
- auto __sv = _S_two_digits(__i);
- _CharT __buf[2];
+ _CharT __buf[3];
+ auto __sv = _S_str_d2(__buf, __i);
if (__conv == _CharT('e') && __i < 10)
{
- __buf[0] = _S_space;
__buf[1] = __sv[1];
+ __buf[0] = _S_space;
__sv = {__buf, 2};
}
- return __format::__write(std::move(__out), __sv);
+
+ __out = __format::__write(std::move(__out), __sv);
+ return std::move(__out);
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_F(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext&) const
+ template<typename _OutIter>
+ _OutIter
+ _M_F(const _ChronoData<_CharT>& __t, _OutIter __out) const
{
- auto __ymd = _S_date(__t);
- auto __s = std::format(_GLIBCXX_WIDEN("{:04d}- - "),
- (int)__ymd.year());
- auto __sv = _S_two_digits((unsigned)__ymd.month());
- __s[__s.size() - 5] = __sv[0];
- __s[__s.size() - 4] = __sv[1];
- __sv = _S_two_digits((unsigned)__ymd.day());
- __s[__s.size() - 2] = __sv[0];
- __s[__s.size() - 1] = __sv[1];
- __sv = __s;
- return __format::__write(std::move(__out), __sv);
+ auto __di = (unsigned)__t._M_day;
+ auto __mi = (unsigned)__t._M_month;
+ auto __yi = (int)__t._M_year;
+ const bool __is_neg = __yi < 0;
+ __yi = __builtin_abs(__yi);
+
+ if (__yi >= 10000 || __mi >= 100 || __di >= 100) [[unlikely]]
+ {
+ using _FmtStr = _Runtime_format_string<_CharT>;
+ __string_view __fs
+ = _GLIBCXX_WIDEN("-{:04d}-{:02d}-{:02d}") + !__is_neg;
+ __out = std::format_to(std::move(__out), _FmtStr(__fs),
+ __yi, __mi, __di);
+ }
+ else
+ {
+ _CharT __buf[11];
+ __buf[0] = _S_plus_minus[1];
+ __buf[5] = _S_plus_minus[1];
+ __buf[8] = _S_plus_minus[1];
+ __string_view __sv(__buf + !__is_neg, __buf + 11);
+
+ _S_fill_two_digits(__buf + 1, __yi / 100);
+ _S_fill_two_digits(__buf + 3, __yi % 100);
+ _S_fill_two_digits(__buf + 6, __mi);
+ _S_fill_two_digits(__buf + 9, __di);
+ __out = __format::__write(std::move(__out), __sv);
+ }
+
+ return std::move(__out);
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_g_G(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __full) const
+ template<typename _OutIter>
+ _OutIter
+ _M_g_G_V(const _ChronoData<_CharT>& __t, _OutIter __out,
+ _CharT __conv) const
{
- // %g last two decimal digits of the ISO week-based year.
- // %G ISO week-based year.
+ // %g last two decimal digits of the ISO week-based year.
+ // %G ISO week-based year.
+ // %V ISO week-based week number as a decimal number.
+ // %OV Locale's alternative numeric rep.
+
+ // ISO week-based year of __t is the year that contains the nearest
+ // Thursday. The ISO week of __t is the number of weeks since
+ // January 1 of that year.
+
using namespace chrono;
- auto __d = _S_days(__t);
- // Move to nearest Thursday:
- __d -= (weekday(__d) - Monday) - days(3);
- // ISO week-based year is the year that contains that Thursday:
- year __y = year_month_day(__d).year();
- return _M_C_y_Y(__y, std::move(__out), __ctx, "yY"[__full]);
+ // Offset of the nearest Thursday:
+ const days __offset = (__t._M_weekday - Monday) - days(3);
+ // Nearest Thursday as local days:
+ const local_days __ild = __t._M_ldays - __offset;
+ // Day of year of nearest Thursday:
+ days __idoy = __t._M_day_of_year - __offset;
+
+ // Year of nearest Thursday:
+ year __iyear;
+ if (__idoy <= days(0))
+ __iyear = __t._M_year - years(1);
+ else if (__idoy <= days(365))
+ __iyear = __t._M_year;
+ else if (__idoy == days(366) && __t._M_year.is_leap())
+ __iyear = __t._M_year;
+ else if (__idoy <= days(730))
+ __iyear = __t._M_year + years(1);
+ else [[unlikely]]
+ __iyear = year_month_day(__ild).year();
+
+ if (__conv != 'V')
+ return _M_C_y_Y(__iyear, std::move(__out), "yY"[__conv == 'G']);
+
+ if (__iyear != __t._M_year)
+ __idoy = __ild - local_days(__iyear/January/0);
+
+ const auto __wi = chrono::floor<weeks>(__idoy - days(1)).count() + 1;
+ return __format::__write(std::move(__out), _S_two_digits(__wi));
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_H_I(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
+ template<typename _OutIter>
+ _OutIter
+ _M_H_I(chrono::hours __h, _OutIter __out, _CharT __conv) const
{
// %H The hour (24-hour clock) as a decimal number.
// %OH Locale's alternative representation.
// %I The hour (12-hour clock) as a decimal number.
// %OI Locale's alternative representation.
- const auto __hms = _S_hms(__t);
- int __i = __hms.hours().count();
-
- if (__mod && _M_spec._M_localized) [[unlikely]]
- if (auto __loc = __ctx.locale(); __loc != locale::classic())
- {
- struct tm __tm{};
- __tm.tm_hour = __i;
- return _M_locale_fmt(std::move(__out), __loc, __tm,
- (char)__conv, 'O');
- }
+ int __i = __h.count();
if (__conv == _CharT('I'))
{
+ __i %= 12;
if (__i == 0)
__i = 12;
- else if (__i > 12)
- __i -= 12;
}
+ else if (__i >= 100) [[unlikely]]
+ return std::format_to(std::move(__out), _S_empty_fs(), __i);
+
return __format::__write(std::move(__out), _S_two_digits(__i));
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_j(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext&) const
+ template<typename _OutIter>
+ _OutIter
+ _M_j(const _ChronoData<_CharT>& __t, _OutIter __out) const
{
- if constexpr (chrono::__is_duration_v<_Tp>)
- {
- // Decimal number of days, without padding.
- unsigned __d = chrono::duration_cast<chrono::days>(__t).count();
- return std::format_to(std::move(__out), _S_empty_spec, __d);
- }
- else
- {
- // Day of the year as a decimal number, padding with zero.
- using namespace chrono;
- auto __day = _S_days(__t);
- auto __ymd = _S_date(__t);
- days __d;
- // See "Calculating Ordinal Dates" at
- // https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes
- if constexpr (is_same_v<typename decltype(__day)::clock, local_t>)
- __d = __day - local_days(__ymd.year()/January/0);
- else
- __d = __day - sys_days(__ymd.year()/January/0);
- return std::format_to(std::move(__out), _GLIBCXX_WIDEN("{:03d}"),
- __d.count());
- }
+ if (!_M_spec._M_needs(_ChronoParts::_DayOfYear))
+ {
+ // Decimal number of days, without padding.
+ auto __d = chrono::floor<chrono::days>(__t._M_hours).count();
+ return std::format_to(std::move(__out), _S_empty_fs(), __d);
+ }
+
+ auto __d = __t._M_day_of_year.count();
+ if (__d >= 1000) [[unlikely]]
+ return std::format_to(std::move(__out), _S_empty_fs(), __d);
+
+ _CharT __buf[3];
+ return __format::__write(std::move(__out), _S_str_d3(__buf, __d));
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_m(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __mod) const
+ template<typename _OutIter>
+ _OutIter
+ _M_m(chrono::month __m, _OutIter __out) const
{
// %m month as a decimal number.
// %Om Locale's alternative representation.
-
- auto __m = _S_month(__t);
auto __i = (unsigned)__m;
+ if (__i == 0 && _M_spec._M_debug) [[unlikely]]
+ // 0 should not be padded to two digits
+ return __format::__write(std::move(__out), _S_digit(0));
- if (__mod && _M_spec._M_localized) [[unlikely]] // %Om
- if (auto __loc = __ctx.locale(); __loc != locale::classic())
- {
- struct tm __tm{};
- __tm.tm_mon = __i - 1;
- return _M_locale_fmt(std::move(__out), __loc, __tm,
- 'm', 'O');
- }
-
- return __format::__write(std::move(__out), _S_two_digits(__i));
+ _CharT __buf[3];
+ return __format::__write(std::move(__out), _S_str_d2(__buf, __i));
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_M(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __mod) const
+ template<typename _OutIter>
+ _OutIter
+ _M_M(chrono::minutes __m, _OutIter __out) const
{
// %M The minute as a decimal number.
// %OM Locale's alternative representation.
- auto __m = _S_hms(__t).minutes();
auto __i = __m.count();
-
- if (__mod && _M_spec._M_localized) [[unlikely]] // %OM
- if (auto __loc = __ctx.locale(); __loc != locale::classic())
- {
- struct tm __tm{};
- __tm.tm_min = __i;
- return _M_locale_fmt(std::move(__out), __loc, __tm,
- 'M', 'O');
- }
-
return __format::__write(std::move(__out), _S_two_digits(__i));
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_p(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx) const
+ template<typename _OutIter>
+ _OutIter
+ _M_p(chrono::hours __h, _OutIter __out) const
{
// %p The locale's equivalent of the AM/PM designations.
- auto __hms = _S_hms(__t);
- locale __loc = _M_locale(__ctx);
- const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
- const _CharT* __ampm[2];
- __tp._M_am_pm(__ampm);
- return _M_write(std::move(__out), __loc,
- __ampm[__hms.hours().count() >= 12]);
+
+ _CharT __buf[2];
+ _S_fill_ampm(__buf, __h);
+ return __format::__write(std::move(__out), __string_view(__buf, 2));
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_q(const _Tp&, typename _FormatContext::iterator __out,
- _FormatContext&) const
+ template<typename _OutIter>
+ _OutIter
+ _M_q(__string_view __us, _OutIter __out) const
{
// %q The duration's unit suffix
- if constexpr (!chrono::__is_duration_v<_Tp>)
- __throw_format_error("format error: argument is not a duration");
- else
- {
- namespace __d = chrono::__detail;
- using period = typename _Tp::period;
- return __d::__fmt_units_suffix<period, _CharT>(std::move(__out));
- }
+ return __format::__write(std::move(__out), __us);
}
- // %Q handled in _M_format
+ template<typename _OutIter, typename _FormatContext>
+ _OutIter
+ _M_Q(const _ChronoData<_CharT>& __t, _OutIter __out,
+ _FormatContext&) const
+ {
+ // %Q The duration's numeric value.
+ return std::vformat_to(std::move(__out), _S_empty_spec, __t._M_ereps);
+ }
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_r(const _Tp& __tt, typename _FormatContext::iterator __out,
- _FormatContext& __ctx) const
+ template<typename _OutIter>
+ _OutIter
+ _M_r(const _ChronoData<_CharT>& __t, _OutIter __out) const
{
- // %r locale's 12-hour clock time.
- auto __t = _S_floor_seconds(__tt);
- locale __loc = _M_locale(__ctx);
- const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
- const _CharT* __ampm_fmt;
- __tp._M_am_pm_format(&__ampm_fmt);
- basic_string<_CharT> __fmt(_S_empty_spec);
- __fmt.insert(1u, 1u, _S_colon);
- __fmt.insert(2u, __ampm_fmt);
- using _FmtStr = _Runtime_format_string<_CharT>;
- return _M_write(std::move(__out), __loc,
- std::format(__loc, _FmtStr(__fmt), __t));
+ // %r Locale's 12-hour clock time, for C-locale: %I:%M:%S %p
+ auto __hi = __t._M_hours.count() % 12;
+ if (__hi == 0)
+ __hi = 12;
+
+ _CharT __buf[11];
+ __buf[2] = _S_colon;
+ __buf[5] = _S_colon;
+ __buf[8] = _S_space;
+ _S_fill_two_digits(__buf, __hi);
+ _S_fill_two_digits(__buf + 3, __t._M_minutes.count());
+ _S_fill_two_digits(__buf + 6, __t._M_seconds.count());
+ _S_fill_ampm(__buf + 9, __t._M_hours);
+
+ return __format::__write(std::move(__out), __string_view(__buf, 11));
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_R_T(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __secs) const
+ template<typename _OutIter>
+ _OutIter
+ _M_R_X(const _ChronoData<_CharT>& __t, _OutIter __out,
+ bool __secs) const
{
- // %R Equivalent to %H:%M
- // %T Equivalent to %H:%M:%S
- auto __hms = _S_hms(__t);
-
- auto __s = std::format(_GLIBCXX_WIDEN("{:02d}:00"),
- __hms.hours().count());
- auto __sv = _S_two_digits(__hms.minutes().count());
- __s[__s.size() - 2] = __sv[0];
- __s[__s.size() - 1] = __sv[1];
- __sv = __s;
- __out = __format::__write(std::move(__out), __sv);
- if (__secs)
+ // %R Equivalent to %H:%M
+ // %X Locale's time rep, for C-locale: %H:%M:%S (without subseconds)
+ // %EX Locale's alternative time representation, for C-locale same as above
+
+ auto __hi = __t._M_hours.count();
+
+ _CharT __buf[8];
+ __buf[2] = _S_colon;
+ __buf[5] = _S_colon;
+ __string_view __sv(__buf, 8);
+
+ if (__hi >= 100) [[unlikely]]
{
- *__out++ = _S_colon;
- __out = _M_S(__hms, std::move(__out), __ctx);
+ __out = std::format_to(std::move(__out), _S_empty_fs(), __hi);
+ __sv.remove_prefix(2);
}
- return __out;
+ else
+ _S_fill_two_digits(__buf, __hi);
+
+ _S_fill_two_digits(__buf + 3, __t._M_minutes.count());
+ if (__secs)
+ _S_fill_two_digits(__buf + 6, __t._M_seconds.count());
+ else
+ __sv.remove_suffix(3);
+
+ return __format::__write(std::move(__out), __sv);
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_S(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __mod = false) const
+ template<typename _OutIter, typename _FormatContext>
+ _OutIter
+ _M_S(const _ChronoData<_CharT>& __t, _OutIter __out,
+ _FormatContext& __ctx, bool __subs = true) const
{
// %S Seconds as a decimal number.
// %OS The locale's alternative representation.
- auto __hms = _S_hms(__t);
- auto __s = __hms.seconds();
+ auto __s = __t._M_seconds;
- if (__mod) [[unlikely]] // %OS
- {
- if (_M_spec._M_localized)
- if (auto __loc = __ctx.locale(); __loc != locale::classic())
- {
- struct tm __tm{};
- __tm.tm_sec = (int)__s.count();
- return _M_locale_fmt(std::move(__out), __loc, __tm,
- 'S', 'O');
- }
+ __out = __format::__write(std::move(__out),
+ _S_two_digits(__s.count()));
+ if (__subs)
+ __out = _M_subsecs(__t, std::move(__out), __ctx);
+ return __out;
+ }
- // %OS formats don't include subseconds, so just format that:
- return __format::__write(std::move(__out),
- _S_two_digits(__s.count()));
+ template<typename _OutIter, typename _FormatContext>
+ _OutIter
+ _M_subsecs(const _ChronoData<_CharT>& __t, _OutIter __out,
+ _FormatContext& __ctx) const
+ {
+ unsigned __prec = _M_spec._M_prec_kind != _WP_none
+ ? _M_spec._M_get_precision(__ctx)
+ : _M_spec._M_prec;
+ if (__prec == 0)
+ return __out;
+
+ _CharT __dot = _S_dot;
+ if (_M_spec._M_localized) [[unlikely]]
+ {
+ auto __loc = __ctx.locale();
+ const auto& __np = use_facet<numpunct<_CharT>>(__loc);
+ __dot = __np.decimal_point();
}
+ *__out = __dot;
+ ++__out;
- if constexpr (__hms.fractional_width == 0)
- __out = __format::__write(std::move(__out),
- _S_two_digits(__s.count()));
- else
+ if (_M_spec._M_floating_point_rep)
{
- locale __loc = _M_locale(__ctx);
- auto __ss = __hms.subseconds();
- using rep = typename decltype(__ss)::rep;
- if constexpr (is_floating_point_v<rep>)
- {
- chrono::duration<rep> __fs = __s + __ss;
- __out = std::format_to(std::move(__out), __loc,
- _GLIBCXX_WIDEN("{:#0{}.{}Lf}"),
- __fs.count(),
- 3 + __hms.fractional_width,
- __hms.fractional_width);
- }
+ _Str_sink<_CharT> __sink;
+ if (_M_spec._M_localized && _M_spec._M_custom_rep) [[unlikely]]
+ std::vformat_to(__sink.out(), __ctx.locale(),
+ _GLIBCXX_WIDEN("{1:0.{2}Lf}"), __t._M_ereps);
else
- {
- const auto& __np
- = use_facet<numpunct<_CharT>>(__loc);
- __out = __format::__write(std::move(__out),
- _S_two_digits(__s.count()));
- *__out++ = __np.decimal_point();
- if constexpr (is_integral_v<rep>)
- __out = std::format_to(std::move(__out),
- _GLIBCXX_WIDEN("{:0{}}"),
- __ss.count(),
- __hms.fractional_width);
- else
- {
- auto __str = std::format(_S_empty_spec, __ss.count());
- __out = std::format_to(_GLIBCXX_WIDEN("{:0>{}s}"),
- __str,
- __hms.fractional_width);
- }
- }
+ std::vformat_to(__sink.out(),
+ _GLIBCXX_WIDEN("{1:0.{2}f}"), __t._M_ereps);
+
+ auto __sv = __sink.view();
+ // Skip leading zero and dot
+ __sv.remove_prefix(2);
+ return __format::__write(std::move(__out), __sv);
}
- return __out;
+
+ constexpr unsigned __max_prec = _ChronoData<_CharT>::_S_max_prec;
+ constexpr typename _ChronoData<_CharT>::_Attoseconds::rep __pow10t[]
+ {
+ 1u,
+ 10u, 100u, 1000u,
+ 10'000u, 100'000u, 1000'000u,
+ 10'000'000u, 100'000'000u, 1000'000'000u,
+ 10'000'000'000u, 100'000'000'000u, 1000'000'000'000u,
+ 10'000'000'000'000u, 100'000'000'000'000u, 1000'000'000'000'000u,
+ 10'000'000'000'000'000u, 100'000'000'000'000'000u, 1000'000'000'000'000'000u,
+ };
+
+ auto __subs = __t._M_subseconds.count();
+ if (__prec < __max_prec)
+ __subs /= __pow10t[__max_prec - __prec];
+ else if (__prec > __max_prec)
+ __prec = __max_prec;
+
+ using _FmtStr = _Runtime_format_string<_CharT>;
+ return std::format_to(__out, _FmtStr(_GLIBCXX_WIDEN("{0:0{1}}")),
+ __subs, __prec);
}
// %t handled in _M_format
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_u_w(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
+ template<typename _OutIter, typename _FormatContext>
+ _OutIter
+ _M_T(const _ChronoData<_CharT>& __t, _OutIter __out,
+ _FormatContext& __ctx) const
+ {
+ // %T Equivalent to %H:%M:%S, with subseconds
+ __out = _M_R_X(__t, std::move(__out), true);
+ return _M_subsecs(__t, std::move(__out), __ctx);
+ }
+
+ template<typename _OutIter>
+ _OutIter
+ _M_u_w(chrono::weekday __wd, _OutIter __out, _CharT __conv) const
{
// %u ISO weekday as a decimal number (1-7), where Monday is 1.
// %Ou Locale's alternative numeric rep.
// %w Weekday as a decimal number (0-6), where Sunday is 0.
// %Ow Locale's alternative numeric rep.
-
- chrono::weekday __wd = _S_weekday(__t);
-
- if (__mod && _M_spec._M_localized) [[unlikely]]
- if (auto __loc = __ctx.locale(); __loc != locale::classic())
- {
- struct tm __tm{};
- __tm.tm_wday = __wd.c_encoding();
- return _M_locale_fmt(std::move(__out), __loc, __tm,
- (char)__conv, 'O');
- }
-
unsigned __wdi = __conv == 'u' ? __wd.iso_encoding()
: __wd.c_encoding();
- const _CharT __d = _S_digit(__wdi);
- return __format::__write(std::move(__out), __string_view(&__d, 1));
+ _CharT __buf[3];
+ return __format::__write(std::move(__out), _S_str_d1(__buf, __wdi));
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_U_V_W(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
+ template<typename _OutIter>
+ _OutIter
+ _M_U_W(const _ChronoData<_CharT>& __t, _OutIter __out,
+ _CharT __conv) const
{
// %U Week number of the year as a decimal number, from first Sunday.
// %OU Locale's alternative numeric rep.
- // %V ISO week-based week number as a decimal number.
- // %OV Locale's alternative numeric rep.
// %W Week number of the year as a decimal number, from first Monday.
// %OW Locale's alternative numeric rep.
- using namespace chrono;
- auto __d = _S_days(__t);
- using _TDays = decltype(__d); // Either sys_days or local_days.
-
- if (__mod && _M_spec._M_localized) [[unlikely]]
- if (auto __loc = __ctx.locale(); __loc != locale::classic())
- {
- const year_month_day __ymd(__d);
- const year __y = __ymd.year();
- struct tm __tm{};
- __tm.tm_year = (int)__y - 1900;
- __tm.tm_yday = (__d - _TDays(__y/January/1)).count();
- __tm.tm_wday = weekday(__d).c_encoding();
- return _M_locale_fmt(std::move(__out), __loc, __tm,
- (char)__conv, 'O');
- }
- _TDays __first; // First day of week 1.
- if (__conv == 'V') // W01 begins on Monday before first Thursday.
- {
- // Move to nearest Thursday:
- __d -= (weekday(__d) - Monday) - days(3);
- // ISO week of __t is number of weeks since January 1 of the
- // same year as that nearest Thursday.
- __first = _TDays(year_month_day(__d).year()/January/1);
- }
- else
- {
- year __y;
- if constexpr (requires { __t.year(); })
- __y = __t.year();
- else
- __y = year_month_day(__d).year();
- const weekday __weekstart = __conv == 'U' ? Sunday : Monday;
- __first = _TDays(__y/January/__weekstart[1]);
- }
- auto __weeks = chrono::floor<weeks>(__d - __first);
- __string_view __sv = _S_two_digits(__weeks.count() + 1);
- return __format::__write(std::move(__out), __sv);
- }
-
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_x(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __mod = false) const
- {
- // %x Locale's date rep
- // %Ex Locale's alternative date representation.
- locale __loc = _M_locale(__ctx);
- const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
- const _CharT* __date_reps[2];
- __tp._M_date_formats(__date_reps);
- const _CharT* __rep = __date_reps[__mod];
- if (!*__rep)
- return _M_D(__t, std::move(__out), __ctx);
-
- basic_string<_CharT> __fmt(_S_empty_spec);
- __fmt.insert(1u, 1u, _S_colon);
- __fmt.insert(2u, __rep);
- using _FmtStr = _Runtime_format_string<_CharT>;
- return _M_write(std::move(__out), __loc,
- std::format(__loc, _FmtStr(__fmt), __t));
- }
-
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_X(const _Tp& __tt, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __mod = false) const
- {
- // %X Locale's time rep
- // %EX Locale's alternative time representation.
- auto __t = _S_floor_seconds(__tt);
- locale __loc = _M_locale(__ctx);
- const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
- const _CharT* __time_reps[2];
- __tp._M_time_formats(__time_reps);
- const _CharT* __rep = __time_reps[__mod];
- if (!*__rep)
- return _M_R_T(__t, std::move(__out), __ctx, true);
-
- basic_string<_CharT> __fmt(_S_empty_spec);
- __fmt.insert(1u, 1u, _S_colon);
- __fmt.insert(2u, __rep);
- using _FmtStr = _Runtime_format_string<_CharT>;
- return _M_write(std::move(__out), __loc,
- std::format(__loc, _FmtStr(__fmt), __t));
+ using namespace chrono;
+ const weekday __weekstart = __conv == 'U' ? Sunday : Monday;
+ const days __offset = __t._M_weekday - __weekstart;
+ auto __weeks = chrono::floor<weeks>(__t._M_day_of_year - __offset - days(1));
+ return __format::__write(std::move(__out), _S_two_digits(__weeks.count() + 1));
}
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_z(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext&, bool __mod = false) const
+ template<typename _OutIter>
+ _OutIter
+ _M_z(chrono::seconds __ts, _OutIter __out, bool __mod = false) const
{
- using ::std::chrono::__detail::__utc_leap_second;
- using ::std::chrono::__detail::__local_time_fmt;
-
- auto __utc = __mod ? __string_view(_GLIBCXX_WIDEN("+00:00"), 6)
- : __string_view(_GLIBCXX_WIDEN("+0000"), 5);
-
- if constexpr (chrono::__is_time_point_v<_Tp>)
+ if (__ts == 0s)
{
- if constexpr (is_same_v<typename _Tp::clock,
- chrono::system_clock>)
- return __format::__write(std::move(__out), __utc);
+ __string_view __zero
+ = __mod ? _GLIBCXX_WIDEN("+00:00") : _GLIBCXX_WIDEN("+0000");
+ return __format::__write(std::move(__out), __zero);
}
- else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
- {
- if (__t._M_offset_sec)
- {
- auto __sv = __utc;
- basic_string<_CharT> __s;
- if (*__t._M_offset_sec != 0s)
- {
- chrono:: hh_mm_ss __hms(*__t._M_offset_sec);
- __s = _S_plus_minus[__hms.is_negative()];
- __s += _S_two_digits(__hms.hours().count());
- if (__mod)
- __s += _S_colon;
- __s += _S_two_digits(__hms.minutes().count());
- __sv = __s;
- }
- return __format::__write(std::move(__out), __sv);
- }
- }
- else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
- return __format::__write(std::move(__out), __utc);
- __no_timezone_available();
- }
+ chrono::hh_mm_ss<chrono::seconds> __hms(__ts);
+ unsigned __mo = 3 + __mod;
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_Z(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx) const
- {
- using ::std::chrono::__detail::__utc_leap_second;
- using ::std::chrono::__detail::__local_time_fmt;
+ _CharT __buf[6];
+ __buf[0] = _S_plus_minus[__hms.is_negative()];
+ __buf[3] = _S_colon;
+ _S_fill_two_digits(__buf + 1, __hms.hours().count());
+ _S_fill_two_digits(__buf + __mo, __hms.minutes().count());
- __string_view __utc(_GLIBCXX_WIDEN("UTC"), 3);
- if constexpr (chrono::__is_time_point_v<_Tp>)
- {
- if constexpr (is_same_v<typename _Tp::clock,
- chrono::system_clock>)
- return __format::__write(std::move(__out), __utc);
- }
- else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
- {
- if (__t._M_abbrev)
- {
- string_view __sv = *__t._M_abbrev;
- if constexpr (is_same_v<_CharT, char>)
- return __format::__write(std::move(__out), __sv);
- else
- {
- // TODO use resize_and_overwrite
- basic_string<_CharT> __ws(__sv.size(), _CharT());
- auto& __ct = use_facet<ctype<_CharT>>(_M_locale(__ctx));
- __ct.widen(__sv.begin(), __sv.end(), __ws.data());
- __string_view __wsv = __ws;
- return __format::__write(std::move(__out), __wsv);
- }
- }
- }
- else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
- return __format::__write(std::move(__out), __utc);
-
- __no_timezone_available();
+ __string_view __sv(__buf, __mo + 2);
+ return __format::__write(std::move(__out), __sv);
}
+ template<typename _OutIter>
+ _OutIter
+ _M_Z(__string_view __abbrev, _OutIter __out) const
+ { return __format::__write(std::move(__out), __abbrev); }
+
// %% handled in _M_format
- // A single digit character in the range '0'..'9'.
- static _CharT
+ // A string view of single digit character, "0".."9".
+ static basic_string_view<_CharT>
_S_digit(int __n) noexcept
{
// Extra 9s avoid past-the-end read on bad input.
- return _GLIBCXX_WIDEN("0123456789999999")[__n & 0xf];
+ return { _GLIBCXX_WIDEN("0123456789999999") + (__n & 0xf), 1 };
}
// A string view of two digit characters, "00".."99".
@@ -1553,178 +1808,352 @@ namespace __format
};
}
- // Accessors for the components of chrono types:
+ // Fills __buf[0] and __buf[1] with 2 digit value of __n.
+ [[__gnu__::__always_inline__]]
+ static void
+ _S_fill_two_digits(_CharT* __buf, unsigned __n)
+ {
+ auto __sv = _S_two_digits(__n);
+ __buf[0] = __sv[0];
+ __buf[1] = __sv[1];
+ }
+
+ // Fills __buf[0] and __buf[1] with "AM", "PM" depending on __h.
+ [[__gnu__::__always_inline__]]
+ static void
+ _S_fill_ampm(_CharT* __buf, chrono::hours __h)
+ {
+ auto __hi = __h.count();
+ if (__hi >= 24) [[unlikely]]
+ __hi %= 24;
+
+ constexpr const _CharT* __apm = _GLIBCXX_WIDEN("APM");
+ __buf[0] = __apm[__hi >= 12];
+ __buf[1] = __apm[2];
+ }
+
+ // Returns decimal representation of __n.
+ // Returned string_view may point to __buf.
+ [[__gnu__::__always_inline__]]
+ static basic_string_view<_CharT>
+ _S_str_d1(span<_CharT, 3> __buf, unsigned __n)
+ {
+ if (__n < 10) [[likely]]
+ return _S_digit(__n);
+ return _S_str_d2(__buf, __n);
+ }
+
+ // Returns decimal representation of __n, padded to 2 digits.
+ // Returned string_view may point to __buf.
+ [[__gnu__::__always_inline__]]
+ static basic_string_view<_CharT>
+ _S_str_d2(span<_CharT, 3> __buf, unsigned __n)
+ {
+ if (__n < 100) [[likely]]
+ return _S_two_digits(__n);
+ return _S_str_d3(__buf, __n);
+ }
- // Returns a hh_mm_ss.
- template<typename _Tp>
- static decltype(auto)
- _S_hms(const _Tp& __t)
+ // Returns decimal representation of __n, padded to 3 digits.
+ // Returned string_view points to __buf.
+ [[__gnu__::__always_inline__]]
+ static basic_string_view<_CharT>
+ _S_str_d3(span<_CharT, 3> __buf, unsigned __n)
+ {
+ _S_fill_two_digits(__buf.data(), __n / 10);
+ __buf[2] = _S_chars[__n % 10];
+ return __string_view(__buf.data(), 3);
+ }
+ };
+
+ template<typename _CharT>
+ struct __formatter_duration : private __formatter_chrono<_CharT>
+ {
+ template<typename _Rep, typename _Period>
+ constexpr static auto
+ _S_subseconds(const chrono::duration<_Rep, _Period>& __d)
{
- using ::std::chrono::__detail::__utc_leap_second;
- using ::std::chrono::__detail::__local_time_fmt;
-
- if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>)
- return __t;
- else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
- return __t._M_time;
- else if constexpr (chrono::__is_duration_v<_Tp>)
- return chrono::hh_mm_ss<_Tp>(__t);
- else if constexpr (chrono::__is_time_point_v<_Tp>)
- return chrono::hh_mm_ss(__t - chrono::floor<chrono::days>(__t));
- else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
- return _S_hms(__t._M_time);
+ if constexpr (chrono::treat_as_floating_point_v<_Rep>)
+ return chrono::duration<_Rep>(__d);
+ else if constexpr (_Period::den == 1)
+ return chrono::seconds(0);
else
- {
- __invalid_chrono_spec();
- return chrono::hh_mm_ss<chrono::seconds>();
- }
- }
+ {
+ using _Attoseconds = _ChronoData<_CharT>::_Attoseconds;
+ using _CRep = common_type_t<_Rep, typename _Attoseconds::rep>;
+ chrono::duration<_CRep, _Period> subs(__d.count());
+ return chrono::duration_cast<_Attoseconds>(subs);
+ }
+ }
- // Returns a sys_days or local_days.
- template<typename _Tp>
- static auto
- _S_days(const _Tp& __t)
+ public:
+ template<typename _Duration>
+ static consteval
+ _ChronoSpec<_CharT>
+ _S_spec_for(_ChronoParts __parts)
{
- using namespace chrono;
- using ::std::chrono::__detail::__utc_leap_second;
- using ::std::chrono::__detail::__local_time_fmt;
-
- if constexpr (__is_time_point_v<_Tp>)
- return chrono::floor<days>(__t);
- else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
- return __t._M_date;
- else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
- return chrono::floor<days>(__t._M_time);
- else if constexpr (is_same_v<_Tp, year_month_day>
- || is_same_v<_Tp, year_month_day_last>
- || is_same_v<_Tp, year_month_weekday>
- || is_same_v<_Tp, year_month_weekday_last>)
- return sys_days(__t);
- else
+ using _Rep = typename _Duration::rep;
+ using enum _ChronoParts;
+
+ _ChronoSpec<_CharT> __res{};
+ __res._M_floating_point_rep = chrono::treat_as_floating_point_v<_Rep>;
+ __res._M_custom_rep = !is_arithmetic_v<_Rep>;
+ __res._M_prec = chrono::hh_mm_ss<_Duration>::fractional_width;
+ if ((__parts & _TimeOfDay) != 0)
+ __res._M_localized = __res._M_prec > 0 || __res._M_floating_point_rep;
+
+ if ((__parts & _TimeOfDay) != 0)
+ __res._M_needed |= _TimeOfDay;
+ if ((__parts & _Date) != 0)
+ __res._M_needed |= _YearMonthDay;
+ if ((__parts & _ZoneAbbrev) != 0)
+ __res._M_needed |= _ZoneAbbrev;
+
+ switch (__parts)
{
- if constexpr (__is_duration_v<_Tp>)
- __not_valid_for_duration();
- else
- __invalid_chrono_spec();
- return chrono::sys_days();
+ case _ZonedDateTime:
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ftz();
+ break;
+ case _DateTime:
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ft();
+ break;
+ case _Date:
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_f();
+ break;
+ case _Time:
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_t();
+ break;
+ case _None:
+ break;
+ default:
+ __builtin_unreachable();
}
- }
+ return __res;
+ };
- // Returns a year_month_day.
- template<typename _Tp>
- static chrono::year_month_day
- _S_date(const _Tp& __t)
+ template<typename _Duration>
+ static consteval
+ _ChronoSpec<_CharT>
+ _S_spec_for_tp()
{
- if constexpr (is_same_v<_Tp, chrono::year_month_day>)
- return __t;
+ using enum _ChronoParts;
+ // streaming of local_time is defined in terms of sys_time
+ constexpr bool __stream_insertable =
+ requires (basic_ostream<_CharT>& __os, chrono::sys_time<_Duration> __t)
+ { __os << __t; };
+ if constexpr (!__stream_insertable)
+ return _S_spec_for<_Duration>(_None);
+ else if constexpr (is_convertible_v<_Duration, chrono::days>)
+ return _S_spec_for<_Duration>(_Date);
else
- return chrono::year_month_day(_S_days(__t));
+ return _S_spec_for<_Duration>(_DateTime);
}
- template<typename _Tp>
- static chrono::day
- _S_day(const _Tp& __t)
+ using __formatter_chrono<_CharT>::__formatter_chrono;
+ using __formatter_chrono<_CharT>::_M_spec;
+
+ template<typename _Duration>
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ _M_parse(basic_format_parse_context<_CharT>& __pc, _ChronoParts __parts,
+ const _ChronoSpec<_CharT>& __def)
{
- using namespace chrono;
+ using _Rep = typename _Duration::rep;
+ using enum _ChronoParts;
+
+ auto __res
+ = __formatter_chrono<_CharT>::_M_parse(__pc, __parts, __def);
+ // n.b. durations do not contain date parts, and for time point all
+ // date parts are computed, and they are always ok.
+ _M_spec._M_needs_ok_check = false;
+
+ // check for custom floating point durations, if digits of output
+ // will contain subseconds, then formatters must support specifying
+ // precision.
+ if constexpr (!is_floating_point_v<_Rep>)
+ if constexpr (chrono::treat_as_floating_point_v<_Rep>)
+ if (_M_spec._M_needs(_Subseconds|_EpochUnits)
+ || _M_spec._M_prec_kind != _WP_none
+ || _M_spec._M_prec_value > 0)
+ {
+ constexpr const _CharT* __fs = _GLIBCXX_WIDEN("#02.5Lf");
+ basic_format_parse_context<_CharT> __npc(__fs);
+ formatter<_Rep, _CharT> __fmtter;
+ __fmtter.parse(__npc);
+ }
+ return __res;
+ }
- if constexpr (is_same_v<_Tp, day>)
- return __t;
- else if constexpr (requires { __t.day(); })
- return __t.day();
+ // Return the formatting locale.
+ template<typename _FormatContext>
+ std::locale
+ _M_locale(_FormatContext& __fc) const
+ {
+ if (!_M_spec._M_localized)
+ return std::locale::classic();
else
- return _S_date(__t).day();
+ return __fc.locale();
}
- template<typename _Tp>
- static chrono::month
- _S_month(const _Tp& __t)
+ // Format duration for empty chrono-specs, e.g. "{}" (C++20 [time.format] p6).
+ template<typename _Rep, typename _Period, typename _FormatContext>
+ typename _FormatContext::iterator
+ _M_format_to_ostream(const chrono::duration<_Rep, _Period>& __d,
+ bool __is_neg,
+ _FormatContext& __fc) const
{
- using namespace chrono;
+ basic_ostringstream<_CharT> __os;
+ __os.imbue(this->_M_locale(__fc));
- if constexpr (is_same_v<_Tp, month>)
- return __t;
- else if constexpr (requires { __t.month(); })
- return __t.month();
- else
- return _S_date(__t).month();
+ if (__is_neg) [[unlikely]]
+ __os << this->_S_plus_minus[1];
+ __os << __d;
+
+ auto __str = std::move(__os).str();
+ return __format::__write_padded_as_spec(__str, __str.size(),
+ __fc, _M_spec);
}
- template<typename _Tp>
- static chrono::year
- _S_year(const _Tp& __t)
+ template<typename _Rep1, typename _Period1,
+ typename _Rep2, typename _Period2,
+ typename _FormatContext>
+ typename _FormatContext::iterator
+ _M_format_units(_ChronoData<_CharT>& __cd,
+ const chrono::duration<_Rep1, _Period1>& __ed,
+ const chrono::duration<_Rep2, _Period2>& __ss,
+ _FormatContext& __fc) const
{
- using namespace chrono;
+ __format::_Str_sink<_CharT> __suffix_store;
+ constexpr auto _S_unit_suffix
+ = chrono::__detail::__units_suffix<_Period1, _CharT>();
+ if constexpr (!_S_unit_suffix.empty())
+ __cd._M_unit_suffix = _S_unit_suffix;
+ else if (_M_spec._M_needs(_ChronoParts::_UnitSuffix))
+ {
+ chrono::__detail::
+ __fmt_units_suffix<_Period1, _CharT>(__suffix_store.out());
+ __cd._M_unit_suffix = __suffix_store.view();
+ }
- if constexpr (is_same_v<_Tp, year>)
- return __t;
- else if constexpr (requires { __t.year(); })
- return __t.year();
- else
- return _S_date(__t).year();
+ const auto __prec = _M_spec._M_prec_kind != _WP_none
+ ? _M_spec._M_get_precision(__fc)
+ : _M_spec._M_prec;
+
+ using _ErasedContext = typename _ChronoData<_CharT>::_FormatContext;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4118. How should duration formatters format custom rep?
+ auto __ereps = +__ed.count();
+ if (!_M_spec._M_needs(_ChronoParts::_Subseconds))
+ {
+ auto __ssreps = 0u;
+ auto __args_store
+ = std::make_format_args<_ErasedContext>(__ereps, __ssreps, __prec);
+ __cd._M_ereps = __args_store;
+ return this->_M_format(__cd, __fc);
+ }
+
+ using _Attoseconds = _ChronoData<_CharT>::_Attoseconds;
+ auto __nss = _S_subseconds(__ss);
+ __cd._M_subseconds = chrono::duration_cast<_Attoseconds>(__nss);
+
+ auto __ssreps = __nss.count();
+ auto __args_store
+ = std::make_format_args<_ErasedContext>(__ereps, __ssreps, __prec);
+ __cd._M_ereps = __args_store;
+
+ return this->_M_format(__cd, __fc);
}
- template<typename _Tp>
- static chrono::weekday
- _S_weekday(const _Tp& __t)
+ // pre: __cd._M_lseconds and __cd._M_eseconds are set.
+ template<typename _Rep1, typename _Period1, typename _FormatContext>
+ typename _FormatContext::iterator
+ _M_format_time_point(_ChronoData<_CharT>& __cd,
+ const chrono::duration<_Rep1, _Period1>& __ed,
+ _FormatContext& __fc) const
{
- using namespace ::std::chrono;
- using ::std::chrono::__detail::__local_time_fmt;
-
- if constexpr (is_same_v<_Tp, weekday>)
- return __t;
- else if constexpr (requires { __t.weekday(); })
- return __t.weekday();
- else if constexpr (is_same_v<_Tp, month_weekday>)
- return __t.weekday_indexed().weekday();
- else if constexpr (is_same_v<_Tp, month_weekday_last>)
- return __t.weekday_last().weekday();
- else
- return weekday(_S_days(__t));
+ auto __parts = _M_spec._M_needed - _ChronoParts::_TotalSeconds;
+ if ((__parts & _ChronoParts::_DateTime) != 0)
+ __cd._M_fill_date_time(__cd._M_lseconds, __parts);
+ return _M_format_units(__cd, __ed, __ed - __cd._M_eseconds, __fc);
}
+ };
+
+#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
+ template<typename _CharT>
+ struct __formatter_chrono_info
+ {
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ { return _M_f._M_parse(__pc, _ChronoParts(), {}); }
- // Remove subsecond precision from a time_point.
- template<typename _Tp>
- static auto
- _S_floor_seconds(const _Tp& __t)
+ template<typename _Info, typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const _Info& __i,
+ basic_format_context<_Out, _CharT>& __fc) const
{
- using chrono::__detail::__local_time_fmt;
- if constexpr (chrono::__is_time_point_v<_Tp>
- || chrono::__is_duration_v<_Tp>)
- {
- if constexpr (_Tp::period::den != 1)
- return chrono::floor<chrono::seconds>(__t);
- else
- return __t;
- }
- else if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>)
+ // n.b. only acceptable chrono-spec for info is one containing
+ // only whitespaces and %%, that do not depend on formatted object.
+ if (!_M_f._M_spec._M_chrono_specs.empty()) [[unlikely]]
+ return _M_f._M_format(_ChronoData<_CharT>{}, __fc);
+
+ const size_t __padwidth = _M_f._M_spec._M_get_width(__fc);
+ if (__padwidth == 0)
+ return _M_format_to(__fc.out(), __i);
+
+ _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth);
+ _M_format_to(__sink.out(), __i);
+ return __sink._M_finish(_M_f._M_spec._M_align, _M_f._M_spec._M_fill);
+ }
+
+ private:
+ template<typename _Out>
+ _Out
+ _M_format_to(_Out __out, const chrono::sys_info& __si) const
+ {
+ using _FmtStr = _Runtime_format_string<_CharT>;
+ // n.b. only decimal separator is locale dependent for specifiers
+ // used below, as sys_info uses seconds and minutes duration, the
+ // output is locale-independent.
+ constexpr auto* __fs
+ = _GLIBCXX_WIDEN("[{0:%F %T},{1:%F %T},{2:%T},{3:%Q%q},{0:%Z}]");
+ const chrono::local_seconds __lb(__si.begin.time_since_epoch());
+ return std::format_to(std::move(__out), _FmtStr(__fs),
+ chrono::local_time_format(__lb, &__si.abbrev),
+ __si.end, __si.offset, __si.save);
+ }
+
+ template<typename _Out>
+ _Out
+ _M_format_to(_Out __out, const chrono::local_info& __li) const
+ {
+ *__out = _Separators<_CharT>::_S_squares()[0];
+ ++__out;
+ if (__li.result == chrono::local_info::unique)
+ __out = _M_format_to(std::move(__out), __li.first);
+ else
{
- if constexpr (_Tp::fractional_width != 0)
- return chrono::floor<chrono::seconds>(__t.to_duration());
+ basic_string_view<_CharT> __sv;
+ if (__li.result == chrono::local_info::nonexistent)
+ __sv =_GLIBCXX_WIDEN("nonexistent");
else
- return __t;
+ __sv = _GLIBCXX_WIDEN("ambiguous");
+ __out = __format::__write(std::move(__out), __sv);
+
+ __sv = _GLIBCXX_WIDEN(" local time between ");
+ __out = __format::__write(std::move(__out), __sv);
+ __out = _M_format_to(std::move(__out), __li.first);
+
+ __sv = _GLIBCXX_WIDEN(" and ");
+ __out = __format::__write(std::move(__out), __sv);
+ __out = _M_format_to(std::move(__out), __li.second);
}
- else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
- return _S_floor_seconds(__t._M_time);
- else
- return __t;
+ *__out = _Separators<_CharT>::_S_squares()[1];
+ ++__out;
+ return std::move(__out);
}
- // Use the formatting locale's std::time_put facet to produce
- // a locale-specific representation.
- template<typename _Iter>
- _Iter
- _M_locale_fmt(_Iter __out, const locale& __loc, const struct tm& __tm,
- char __fmt, char __mod) const
- {
- basic_ostringstream<_CharT> __os;
- __os.imbue(__loc);
- const auto& __tp = use_facet<time_put<_CharT>>(__loc);
- __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod);
- if (__os)
- __out = _M_write(std::move(__out), __loc, __os.view());
- return __out;
- }
+ __formatter_chrono<_CharT> _M_f;
};
+#endif
} // namespace __format
/// @endcond
@@ -1736,12 +2165,8 @@ namespace __format
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
{
- using namespace __format;
- auto __it = _M_f._M_parse(__pc, _Duration|_TimeOfDay);
- if constexpr (!is_floating_point_v<_Rep>)
- if (_M_f._M_spec._M_prec_kind != __format::_WP_none)
- __throw_format_error("format error: invalid precision for duration");
- return __it;
+ using enum __format::_ChronoParts;
+ return _M_f.template _M_parse<_Duration>(__pc, _EpochTime, __defSpec);
}
template<typename _Out>
@@ -1759,324 +2184,866 @@ namespace __format
using _URep = make_unsigned_t<_Rep>;
auto __ucnt = -static_cast<_URep>(__d.count());
auto __ud = chrono::duration<_URep, _Period>(__ucnt);
- return _M_f._M_format(__ud, __fc, true);
+ return _M_format(__ud, true, __fc);
}
else
- return _M_f._M_format(-__d, __fc, true);
+ return _M_format(-__d, true, __fc);
}
- return _M_f._M_format(__d, __fc, false);
+ return _M_format(__d, false, __fc);
}
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ using _Duration = chrono::duration<_Rep, _Period>;
+
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using enum __format::_ChronoParts;
+ auto __res = __format::__formatter_duration<_CharT>::
+ template _S_spec_for<_Duration>(_None);
+ __res._M_localized = !is_integral_v<_Rep>;
+ // n.b. for integral format output is the same as ostream output
+ if constexpr (is_integral_v<_Rep>)
+ {
+ __res._M_needed = _EpochUnits|_UnitSuffix;
+ __res._M_chrono_specs = _GLIBCXX_WIDEN("%Q%q");
+ }
+ return __res;
+ }();
+
+ template<typename _Rep2, typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ _M_format(const chrono::duration<_Rep2, _Period>& __d,
+ bool __is_neg,
+ basic_format_context<_Out, _CharT>& __fc) const
+ {
+ using namespace chrono;
+ using enum __format::_ChronoParts;
+ if constexpr (!is_integral_v<_Rep>)
+ if (_M_f._M_spec._M_chrono_specs.empty())
+ return _M_f._M_format_to_ostream(__d, __is_neg, __fc);
+
+ __format::_ChronoData<_CharT> __cd;
+ __cd._M_is_neg = __is_neg;
+ auto __ts = chrono::floor<chrono::seconds>(__d);
+ __cd._M_eseconds = __ts;
+ if (_M_f._M_spec._M_needs(_HoursMinutesSeconds))
+ __cd._M_fill_time(__ts);
+ return _M_f._M_format_units(__cd, __d, __d - __ts, __fc);
+ }
+
+ __format::__formatter_duration<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4400. enable_nonlocking_formatter_optimization for durations with custom rep
+ template<typename _Rep, typename _Period>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::duration<_Rep, _Period>>
+ = is_arithmetic_v<_Rep>;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::day, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Day); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Day|_WeekdayIndex, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::day& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_fill_day(__t, __defSpec._M_needed);
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_needed = _Day;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_d();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::day> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::month, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Month); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Month, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::month& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_month = __t;
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Month;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_m();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::month> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::year, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Year); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Year, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::year& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_year = __t;
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_needed = _Year;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_y();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::year> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::weekday, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Weekday); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Weekday, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::weekday& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_weekday = __t;
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Weekday;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_w();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::weekday> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::weekday_indexed, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Weekday); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _IndexedWeekday, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::weekday_indexed& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_fill_weekday(__t, __defSpec._M_needed);
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _IndexedWeekday;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_wi();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::weekday_indexed> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::weekday_last, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Weekday); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Weekday, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::weekday_last& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_weekday = __t.weekday();
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Weekday;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_wl();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::weekday_last> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::month_day, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Month|_Day|_WeekdayIndex, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::month_day& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_month = __t.month();
+ __cd._M_fill_day(__t.day(), __defSpec._M_needed);
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Month|_Day;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_md();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::month_day> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::month_day_last, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Month, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::month_day_last& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_month = __t.month();
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Month;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ml();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::month_day_last> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::month_weekday, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Month|_IndexedWeekday, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::month_weekday& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_month = __t.month();
+ __cd._M_fill_weekday(__t.weekday_indexed(), __defSpec._M_needed);
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Month|_IndexedWeekday;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_mwi();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::month_weekday> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::month_weekday_last, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Month|_Weekday, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::month_weekday_last& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_month = __t.month();
+ __cd._M_weekday = __t.weekday_last().weekday();
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Month|_Weekday;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_mwl();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::month_weekday_last> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::year_month, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Year|__format::_Month); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Year|_Month, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::year_month& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_fill_year_month(__t, __defSpec._M_needed);
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Year|_Month;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ym();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::year_month> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::year_month_day, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Date); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Date, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::year_month_day& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ auto __parts = _M_f._M_spec._M_needed;
+ __parts = __cd._M_fill_year_month(__t, __parts);
+ __parts = __cd._M_fill_day(__t.day(), __parts);
+ if (__parts == 0)
+ return _M_f._M_format(__cd, __fc);
+
+ __cd._M_fill_ldays(chrono::local_days(__t), __parts);
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_needed = _YearMonthDay;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_f();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::year_month_day> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::year_month_day_last, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Date); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Date, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::year_month_day_last& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoData<_CharT> __cd{};
+ auto __parts = _M_f._M_spec._M_needed;
+ __parts = __cd._M_fill_year_month(__t, __parts);
+ if (_M_f._M_spec._M_needs(_Day|_WeekdayIndex))
+ __parts = __cd._M_fill_day(__t.day(), __parts);
+ if (__parts == 0)
+ return _M_f._M_format(__cd, __fc);
+
+ __cd._M_fill_ldays(chrono::local_days(__t), __parts);
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Year|_Month;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_yml();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::year_month_day_last> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::year_month_weekday, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Date); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Date, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::year_month_weekday& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ auto __parts = _M_f._M_spec._M_needed;
+ __parts = __cd._M_fill_year_month(__t, __parts);
+ __parts = __cd._M_fill_weekday(__t.weekday_indexed(), __parts);
+ if (__t.index() == 0) [[unlikely]]
+ // n.b. day cannot be negative, so any 0th weekday uses
+ // value-initialized (0) day of month
+ __parts -= __format::_ChronoParts::_Day;
+ if (__parts == 0)
+ return _M_f._M_format(__cd, __fc);
+
+ chrono::local_days __ld(__t);
+ __parts = __cd._M_fill_ldays(__ld, __parts);
+ if (__parts == 0)
+ return _M_f._M_format(__cd, __fc);
+
+ auto __dom = __ld - chrono::local_days(__t.year()/__t.month()/0);
+ // n.b. weekday index is supplied by input, do not override it
+ __cd._M_day = chrono::day(__dom.count());
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Year|_Month|_IndexedWeekday;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ymwi();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::year_month_weekday> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::year_month_weekday_last, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Date); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f._M_parse(__pc, _Date, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::year_month_weekday_last& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ auto __parts = _M_f._M_spec._M_needed;
+ __parts = __cd._M_fill_year_month(__t, __parts);
+ __cd._M_weekday = __t.weekday_last().weekday();
+ __parts -= __format::_ChronoParts::_Weekday;
+ if (__parts == 0)
+ return _M_f._M_format(__cd, __fc);
+
+ chrono::local_days __ld(__t);
+ __parts = __cd._M_fill_ldays(__ld, __parts);
+ if (__parts == 0)
+ return _M_f._M_format(__cd, __fc);
+
+ auto __dom = __ld - chrono::local_days(__t.year()/__t.month()/0);
+ __cd._M_fill_day(chrono::day(__dom.count()), __parts);
+ return _M_f._M_format(__cd, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ using __format::_ChronoFormats;
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_needed = _Year|_Month|_Weekday;
+ __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ymwl();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::year_month_weekday_last> = true;
+#endif
+
template<typename _Rep, typename _Period, __format::__char _CharT>
struct formatter<chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_TimeOfDay); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f.template _M_parse<_Precision>(__pc, _Time, __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ using enum __format::_ChronoParts;
+
+ __format::_ChronoData<_CharT> __cd;
+ __cd._M_is_neg = __t.is_negative();
+ __cd._M_hours = __t.hours();
+ __cd._M_minutes = __t.minutes();
+ __cd._M_seconds = __t.seconds();
+
+ _Precision __d(0);
+ // n.b. computing total duration or total seconds may overflow,
+ // do not compute them if not requested.
+ if (_M_f._M_spec._M_needs(_EpochUnits))
+ __d = __t.to_duration();
+ if (_M_f._M_spec._M_needs(_TotalSeconds))
+ __cd._M_eseconds
+ = __cd._M_hours + __cd._M_minutes + __cd._M_seconds;
+ return _M_f._M_format_units(__cd, __d, __t.subseconds(), __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ using _Precision
+ = typename chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>::precision;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec =
+ __format::__formatter_duration<_CharT>::
+ template _S_spec_for<_Precision>(__format::_ChronoParts::_Time);
+
+ __format::__formatter_duration<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4400. enable_nonlocking_formatter_optimization for durations with custom rep
+ template<typename _Duration>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::hh_mm_ss<_Duration>>
+ = enable_nonlocking_formatter_optimization<_Duration>;
+#endif
+
#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
template<__format::__char _CharT>
struct formatter<chrono::sys_info, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ChronoParts{}); }
+ { return _M_f.parse(__pc); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::sys_info& __i,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__i, __fc); }
+ { return _M_f.format(__i, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ __format::__formatter_chrono_info<_CharT> _M_f;
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::sys_info> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<chrono::local_info, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ChronoParts{}); }
+ { return _M_f.parse(__pc); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::local_info& __i,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__i, __fc); }
+ { return _M_f.format(__i, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ __format::__formatter_chrono_info<_CharT> _M_f;
};
+
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::local_info> = true;
+#endif
#endif
template<typename _Duration, __format::__char _CharT>
@@ -2085,185 +3052,351 @@ namespace __format
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
{
- auto __next = _M_f._M_parse(__pc, __format::_ZonedDateTime);
- if constexpr (!__stream_insertable)
+ using enum __format::_ChronoParts;
+ auto __res
+ = _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec);
+ if constexpr (__defSpec._M_chrono_specs.empty())
if (_M_f._M_spec._M_chrono_specs.empty())
__format::__invalid_chrono_spec(); // chrono-specs can't be empty
- return __next;
+ return __res;
}
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::sys_time<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_fill_utc_zone();
+
+ _Duration __ed = __t.time_since_epoch();
+ __cd._M_eseconds = chrono::floor<chrono::seconds>(__ed);
+ __cd._M_lseconds = chrono::local_seconds(__cd._M_eseconds);
+ return _M_f._M_format_time_point(__cd, __ed, __fc);
+ }
private:
- static constexpr bool __stream_insertable
- = requires (basic_ostream<_CharT>& __os,
- chrono::sys_time<_Duration> __t) { __os << __t; };
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec =
+ __format::__formatter_duration<_CharT>::template _S_spec_for_tp<_Duration>();
- __format::__formatter_chrono<_CharT> _M_f;
+ __format::__formatter_duration<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4400. enable_nonlocking_formatter_optimization for durations with custom rep
+ template<typename _Duration>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::sys_time<_Duration>>
+ = enable_nonlocking_formatter_optimization<_Duration>;
+#endif
+
template<typename _Duration, __format::__char _CharT>
struct formatter<chrono::utc_time<_Duration>, _CharT>
- : __format::__formatter_chrono<_CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec);
+ }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::utc_time<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::utc_time<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
{
+ using __format::_ChronoParts;
+ using namespace chrono;
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_fill_utc_zone();
+
+ _Duration __ed = __t.time_since_epoch();
+ __cd._M_eseconds = chrono::floor<seconds>(__ed);
// Adjust by removing leap seconds to get equivalent sys_time.
// We can't just use clock_cast because we want to know if the time
// falls within a leap second insertion, and format seconds as "60".
- using chrono::__detail::__utc_leap_second;
- using chrono::seconds;
- using chrono::sys_time;
- using _CDur = common_type_t<_Duration, seconds>;
const auto __li = chrono::get_leap_second_info(__t);
- sys_time<_CDur> __s{__t.time_since_epoch() - __li.elapsed};
- if (!__li.is_leap_second) [[likely]]
- return _M_f._M_format(__s, __fc);
- else
- return _M_f._M_format(__utc_leap_second(__s), __fc);
+ __cd._M_lseconds = local_seconds(__cd._M_eseconds - __li.elapsed);
+ auto __parts = _M_f._M_spec._M_needed - _ChronoParts::_TotalSeconds;
+ if ((__parts & _ChronoParts::_DateTime) != 0)
+ {
+ __cd._M_fill_date_time(__cd._M_lseconds, __parts);
+ __cd._M_seconds += seconds(__li.is_leap_second);
+ }
+ return _M_f._M_format_units(__cd, __ed, __ed - __cd._M_eseconds, __fc);
}
private:
- friend formatter<chrono::__detail::__utc_leap_second<_Duration>, _CharT>;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec =
+ __format::__formatter_duration<_CharT>::
+ template _S_spec_for<_Duration>(__format::_ChronoParts::_DateTime);
- __format::__formatter_chrono<_CharT> _M_f;
+ __format::__formatter_duration<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4400. enable_nonlocking_formatter_optimization for durations with custom rep
+ template<typename _Duration>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::utc_time<_Duration>>
+ = enable_nonlocking_formatter_optimization<_Duration>;
+#endif
+
template<typename _Duration, __format::__char _CharT>
struct formatter<chrono::tai_time<_Duration>, _CharT>
- : __format::__formatter_chrono<_CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec);
+ }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::tai_time<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::tai_time<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
{
- // Convert to __local_time_fmt with abbrev "TAI" and offset 0s.
- // We use __local_time_fmt and not sys_time (as the standard implies)
- // because %Z for sys_time would print "UTC" and we want "TAI" here.
+ using namespace chrono;
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_fill_zone("TAI", L"TAI");
+ _Duration __ed = __t.time_since_epoch();
+ __cd._M_eseconds = chrono::floor<seconds>(__ed);
// Offset is 1970y/January/1 - 1958y/January/1
constexpr chrono::days __tai_offset = chrono::days(4383);
- using _CDur = common_type_t<_Duration, chrono::days>;
- chrono::local_time<_CDur> __lt(__t.time_since_epoch() - __tai_offset);
- const string __abbrev("TAI", 3);
- const chrono::seconds __off = 0s;
- const auto __lf = chrono::local_time_format(__lt, &__abbrev, &__off);
- return _M_f._M_format(__lf, __fc);
+ __cd._M_lseconds = local_seconds(__cd._M_eseconds - __tai_offset);
+ return _M_f._M_format_time_point(__cd, __ed, __fc);
}
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec =
+ __format::__formatter_duration<_CharT>::
+ template _S_spec_for<_Duration>(__format::_ChronoParts::_DateTime);
+
+ __format::__formatter_duration<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4400. enable_nonlocking_formatter_optimization for durations with custom rep
+ template<typename _Duration>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::tai_time<_Duration>>
+ = enable_nonlocking_formatter_optimization<_Duration>;
+#endif
+
template<typename _Duration, __format::__char _CharT>
struct formatter<chrono::gps_time<_Duration>, _CharT>
- : __format::__formatter_chrono<_CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec);
+ }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::gps_time<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::gps_time<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
{
- // Convert to __local_time_fmt with abbrev "GPS" and offset 0s.
- // We use __local_time_fmt and not sys_time (as the standard implies)
- // because %Z for sys_time would print "UTC" and we want "GPS" here.
+ using namespace chrono;
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_fill_zone("GPS", L"GPS");
+ _Duration __ed = __t.time_since_epoch();
+ __cd._M_eseconds = chrono::floor<seconds>(__ed);
// Offset is 1980y/January/Sunday[1] - 1970y/January/1
constexpr chrono::days __gps_offset = chrono::days(3657);
- using _CDur = common_type_t<_Duration, chrono::days>;
- chrono::local_time<_CDur> __lt(__t.time_since_epoch() + __gps_offset);
- const string __abbrev("GPS", 3);
- const chrono::seconds __off = 0s;
- const auto __lf = chrono::local_time_format(__lt, &__abbrev, &__off);
- return _M_f._M_format(__lf, __fc);
+ __cd._M_lseconds = local_seconds(__cd._M_eseconds + __gps_offset);
+ return _M_f._M_format_time_point(__cd, __ed, __fc);
}
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec =
+ __format::__formatter_duration<_CharT>::
+ template _S_spec_for<_Duration>(__format::_ChronoParts::_DateTime);
+
+ __format::__formatter_duration<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4400. enable_nonlocking_formatter_optimization for durations with custom rep
+ template<typename _Duration>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::gps_time<_Duration>>
+ = enable_nonlocking_formatter_optimization<_Duration>;
+#endif
+
template<typename _Duration, __format::__char _CharT>
struct formatter<chrono::file_time<_Duration>, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec);
+ }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::file_time<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::file_time<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
{
using namespace chrono;
- return _M_f._M_format(chrono::clock_cast<system_clock>(__t), __fc);
+ __format::_ChronoData<_CharT> __cd{};
+ __cd._M_fill_utc_zone();
+
+ _Duration __ed = __t.time_since_epoch();
+ __cd._M_eseconds = chrono::floor<seconds>(__ed);
+ auto __st = chrono::clock_cast<system_clock>(__t);
+ __cd._M_lseconds
+ = local_seconds(chrono::floor<seconds>(__st.time_since_epoch()));
+ return _M_f._M_format_time_point(__cd, __ed, __fc);
}
private:
- __format::__formatter_chrono<_CharT> _M_f;
- };
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec =
+ __format::__formatter_duration<_CharT>::
+ template _S_spec_for<_Duration>(__format::_ChronoParts::_DateTime);
+
+ __format::__formatter_duration<_CharT> _M_f{__defSpec};
+ };
+
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4400. enable_nonlocking_formatter_optimization for durations with custom rep
+ template<typename _Duration>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::file_time<_Duration>>
+ = enable_nonlocking_formatter_optimization<_Duration>;
+#endif
template<typename _Duration, __format::__char _CharT>
struct formatter<chrono::local_time<_Duration>, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_DateTime); }
+ {
+ using enum __format::_ChronoParts;
+ auto __res
+ = _M_f.template _M_parse<_Duration>(__pc, _DateTime, __defSpec);
+ if constexpr (__defSpec._M_chrono_specs.empty())
+ if (_M_f._M_spec._M_chrono_specs.empty())
+ __format::__invalid_chrono_spec(); // chrono-specs can't be empty
+ return __res;
+ }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::local_time<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::local_time<_Duration>& __lt,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc); }
+ {
+ __format::_ChronoData<_CharT> __cd{};
+ _Duration __ed = __lt.time_since_epoch();
+ __cd._M_lseconds = chrono::floor<chrono::seconds>(__lt);
+ __cd._M_eseconds = __cd._M_lseconds.time_since_epoch();
+ return _M_f._M_format_time_point(__cd, __ed, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec =
+ __format::__formatter_duration<_CharT>::template _S_spec_for_tp<_Duration>();
+
+ __format::__formatter_duration<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4400. enable_nonlocking_formatter_optimization for durations with custom rep
+ template<typename _Duration>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<chrono::local_time<_Duration>>
+ = enable_nonlocking_formatter_optimization<_Duration>;
+#endif
+
template<typename _Duration, __format::__char _CharT>
struct formatter<chrono::__detail::__local_time_fmt<_Duration>, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
+ {
+ using enum __format::_ChronoParts;
+ return _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec);
+ }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::__detail::__local_time_fmt<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::__detail::__local_time_fmt<_Duration>& __zt,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc, /* use %Z for {} */ true); }
+ {
+ using enum __format::_ChronoParts;
+ __format::_ChronoData<_CharT> __cd{};
+
+ if (_M_f._M_spec._M_needs(_ZoneOffset))
+ {
+ if (!__zt._M_offset_sec)
+ std::__throw_format_error("format error: no timezone available for %z");
+ __cd._M_zone_offset = *__zt._M_offset_sec;
+ }
+
+ basic_string<_CharT> __zone_store;
+ if (_M_f._M_spec._M_needs(_ZoneAbbrev))
+ {
+ if (!__zt._M_abbrev)
+ std::__throw_format_error("format error: no timezone available for %Z");
+
+ __cd._M_zone_cstr = __zt._M_abbrev->data();
+ if constexpr (is_same_v<_CharT, char>)
+ __cd._M_zone_abbrev = *__zt._M_abbrev;
+ else
+ {
+ // TODO: use resize_for_override
+ __zone_store.resize(__zt._M_abbrev->size());
+ auto& __ct = use_facet<ctype<_CharT>>(_M_f._M_locale(__fc));
+ __ct.widen(__zt._M_abbrev->data(),
+ __zt._M_abbrev->data() + __zt._M_abbrev->size(),
+ __zone_store.data());
+ __cd._M_zone_abbrev = __zone_store;
+ }
+ }
+
+ _Duration __ed = __zt._M_time.time_since_epoch();
+ __cd._M_lseconds = chrono::floor<chrono::seconds>(__zt._M_time);
+ __cd._M_eseconds = __cd._M_lseconds.time_since_epoch();
+ return _M_f._M_format_time_point(__cd, __ed, __fc);
+ }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec =
+ __format::__formatter_duration<_CharT>::
+ template _S_spec_for<_Duration>(__format::_ChronoParts::_ZonedDateTime);
+
+ __format::__formatter_duration<_CharT> _M_f{__defSpec};
};
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4400. enable_nonlocking_formatter_optimization for durations with custom rep
+ template<typename _Duration>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<
+ chrono::__detail::__local_time_fmt<_Duration>>
+ = enable_nonlocking_formatter_optimization<_Duration>;
+#endif
+
#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
template<typename _Duration, typename _TimeZonePtr, __format::__char _CharT>
struct formatter<chrono::zoned_time<_Duration, _TimeZonePtr>, _CharT>
: formatter<chrono::__detail::__local_time_fmt_for<_Duration>, _CharT>
{
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp,
basic_format_context<_Out, _CharT>& __fc) const
{
using _Ltf = chrono::__detail::__local_time_fmt_for<_Duration>;
@@ -2275,19 +3408,17 @@ namespace __format
return _Base::format(__lf, __fc);
}
};
-#endif
- // Partial specialization needed for %c formatting of __utc_leap_second.
- template<typename _Duration, __format::__char _CharT>
- struct formatter<chrono::__detail::__utc_leap_second<_Duration>, _CharT>
- : formatter<chrono::utc_time<_Duration>, _CharT>
- {
- template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::__detail::__utc_leap_second<_Duration>& __t,
- basic_format_context<_Out, _CharT>& __fc) const
- { return this->_M_f._M_format(__t, __fc); }
- };
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4400. enable_nonlocking_formatter_optimization for durations with custom rep
+ template<typename _Duration>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<
+ chrono::zoned_time<_Duration, const chrono::time_zone*>>
+ = enable_nonlocking_formatter_optimization<_Duration>;
+#endif
+#endif
namespace chrono
{
@@ -2869,10 +4000,7 @@ namespace __detail
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __i)
{
- __os << '[' << __i.begin << ',' << __i.end
- << ',' << hh_mm_ss(__i.offset) << ',' << __i.save
- << ',' << __i.abbrev << ']';
- return __os;
+ return __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{}"), __i);
}
/// Writes a local_info object to an ostream in an unspecified format.
@@ -2880,19 +4008,19 @@ namespace __detail
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __li)
{
- __os << '[';
+ __os << __format::_Separators<_CharT>::_S_squares()[0];
if (__li.result == local_info::unique)
__os << __li.first;
else
{
if (__li.result == local_info::nonexistent)
- __os << "nonexistent";
+ __os << _GLIBCXX_WIDEN("nonexistent");
else
- __os << "ambiguous";
- __os << " local time between " << __li.first;
- __os << " and " << __li.second;
+ __os << _GLIBCXX_WIDEN("ambiguous");
+ __os << _GLIBCXX_WIDEN(" local time between ") << __li.first;
+ __os << _GLIBCXX_WIDEN(" and ") << __li.second;
}
- __os << ']';
+ __os << __format::_Separators<_CharT>::_S_squares()[1];
return __os;
}
@@ -3049,8 +4177,7 @@ namespace __detail
if (!__offset)
__offset = &__off;
using __format::_ChronoParts;
- auto __need = _ChronoParts::_Year | _ChronoParts::_Month
- | _ChronoParts::_Day | _ChronoParts::_TimeOfDay;
+ auto __need = _ChronoParts::_YearMonthDay | _ChronoParts::_TimeOfDay;
__detail::_Parser_t<_Duration> __p(__need);
if (__p(__is, __fmt, __abbrev, __offset))
{
@@ -3094,6 +4221,9 @@ namespace __detail
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os,
const local_time<_Duration>& __lt)
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4257. Stream insertion for chrono::local_time should be constrained
+ requires requires(const sys_time<_Duration>& __st) { __os << __st; }
{
__os << sys_time<_Duration>{__lt.time_since_epoch()};
return __os;
@@ -3108,8 +4238,7 @@ namespace __detail
minutes* __offset = nullptr)
{
using __format::_ChronoParts;
- auto __need = _ChronoParts::_Year | _ChronoParts::_Month
- | _ChronoParts::_Day | _ChronoParts::_TimeOfDay;
+ auto __need = _ChronoParts::_YearMonthDay | _ChronoParts::_TimeOfDay;
__detail::_Parser_t<_Duration> __p(__need);
if (__p(__is, __fmt, __abbrev, __offset))
{
@@ -3362,8 +4491,8 @@ namespace __detail
minutes __tz_offset = __bad_min;
basic_string<_CharT, _Traits> __tz_abbr;
- if ((_M_need & _ChronoParts::_TimeOfDay)
- && (_M_need & _ChronoParts::_Year))
+ if ((_M_need & _ChronoParts::_TimeOfDay) != 0
+ && (_M_need & _ChronoParts::_Year) != 0)
{
// For time_points assume "00:00:00" is implicitly present,
// so we don't fail to parse if it's not (PR libstdc++/114240).
@@ -3636,7 +4765,7 @@ namespace __detail
}
else
{
- if (_M_need & _ChronoParts::_TimeOfDay)
+ if ((_M_need & _ChronoParts::_TimeOfDay) != 0)
__err |= ios_base::failbit;
break;
}
@@ -3704,7 +4833,7 @@ namespace __detail
__min = minutes(__val);
else
{
- if (_M_need & _ChronoParts::_TimeOfDay)
+ if ((_M_need & _ChronoParts::_TimeOfDay) != 0)
__err |= ios_base::failbit;
break;
}
@@ -3794,7 +4923,7 @@ namespace __detail
auto __val = __read_unsigned(2);
if (__val == -1 || __val > 23) [[unlikely]]
{
- if (_M_need & _ChronoParts::_TimeOfDay)
+ if ((_M_need & _ChronoParts::_TimeOfDay) != 0)
__err |= ios_base::failbit;
break;
}
@@ -3805,7 +4934,7 @@ namespace __detail
__val = __read_unsigned(2);
if (__val == -1 || __val > 60) [[unlikely]]
{
- if (_M_need & _ChronoParts::_TimeOfDay)
+ if ((_M_need & _ChronoParts::_TimeOfDay) != 0)
__err |= ios_base::failbit;
break;
}
@@ -3840,7 +4969,7 @@ namespace __detail
__s = seconds(__val);
else
{
- if (_M_need & _ChronoParts::_TimeOfDay)
+ if ((_M_need & _ChronoParts::_TimeOfDay) != 0)
__err |= ios_base::failbit;
break;
}
@@ -4314,23 +5443,23 @@ namespace __detail
// Whether the caller wants _M_wd.
// The _Weekday bit is only set for chrono::weekday.
- const bool __need_wday = _M_need & _ChronoParts::_Weekday;
+ const bool __need_wday = (_M_need & _ChronoParts::_Weekday) != 0;
// Whether the caller wants _M_sys_days and _M_time.
// Only true for durations and time_points.
- const bool __need_time = _M_need & _ChronoParts::_TimeOfDay;
+ const bool __need_time = (_M_need & _ChronoParts::_TimeOfDay) != 0;
if (__need_wday && __wday != __bad_wday)
_M_wd = __wday; // Caller only wants a weekday and we have one.
- else if (_M_need & _ChronoParts::_Date) // subsumes __need_wday
+ else if ((_M_need & _ChronoParts::_Date) != 0) // subsumes __need_wday
{
// Whether the caller wants _M_ymd.
// True for chrono::year etc., false for time_points.
const bool __need_ymd = !__need_wday && !__need_time;
- if ((_M_need & _ChronoParts::_Year && __y == __bad_y)
- || (_M_need & _ChronoParts::_Month && __m == __bad_mon)
- || (_M_need & _ChronoParts::_Day && __d == __bad_day))
+ if (((_M_need & _ChronoParts::_Year) != 0 && __y == __bad_y)
+ || ((_M_need & _ChronoParts::_Month) != 0 && __m == __bad_mon)
+ || ((_M_need & _ChronoParts::_Day) != 0 && __d == __bad_day))
{
// Missing at least one of y/m/d so calculate sys_days
// from the other data we have available.
@@ -4407,7 +5536,7 @@ namespace __detail
// but check that their values are in range.
// Make unwanted fields valid so that _M_ymd.ok() is true.
- if (_M_need & _ChronoParts::_Year)
+ if ((_M_need & _ChronoParts::_Year) != 0)
{
if (!__y.ok()) [[unlikely]]
__err |= ios_base::failbit;
@@ -4415,7 +5544,7 @@ namespace __detail
else if (__y == __bad_y)
__y = 1972y; // Leap year so that Feb 29 is valid.
- if (_M_need & _ChronoParts::_Month)
+ if ((_M_need & _ChronoParts::_Month) != 0)
{
if (!__m.ok()) [[unlikely]]
__err |= ios_base::failbit;
@@ -4423,7 +5552,7 @@ namespace __detail
else if (__m == __bad_mon)
__m = January;
- if (_M_need & _ChronoParts::_Day)
+ if ((_M_need & _ChronoParts::_Day) != 0)
{
if (__d < day(1) || __d > (__y/__m/last).day())
__err |= ios_base::failbit;
diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h
index b250397..e59897e 100644
--- a/libstdc++-v3/include/bits/cow_string.h
+++ b/libstdc++-v3/include/bits/cow_string.h
@@ -423,7 +423,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
{
for (; __k1 != __k2; ++__k1, (void)++__p)
- traits_type::assign(*__p, *__k1); // These types are off.
+ traits_type::assign(*__p, static_cast<_CharT>(*__k1));
}
static void
@@ -656,12 +656,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
reserve(__n);
pointer __p = _M_data();
- if constexpr (ranges::contiguous_range<_Rg>
- && is_same_v<ranges::range_value_t<_Rg>, _CharT>)
+ if constexpr (requires {
+ requires ranges::contiguous_range<_Rg>;
+ { ranges::data(std::forward<_Rg>(__rg)) }
+ -> convertible_to<const _CharT*>;
+ })
_M_copy(__p, ranges::data(std::forward<_Rg>(__rg)), __n);
else
- for (auto&& __e : __rg)
- traits_type::assign(*__p++, std::forward<decltype(__e)>(__e));
+ {
+ auto __first = ranges::begin(__rg);
+ const auto __last = ranges::end(__rg);
+ for (; __first != __last; ++__first)
+ traits_type::assign(*__p++, static_cast<_CharT>(*__first));
+ }
_M_rep()->_M_set_length_and_sharable(__n);
}
else
@@ -2912,6 +2919,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return basic_string(*this,
_M_check(__pos, "basic_string::substr"), __n); }
+#ifdef __glibcxx_string_subview // >= C++26
+ /**
+ * @brief Get a subview.
+ * @param __pos Index of first character (default 0).
+ * @param __n Number of characters in subview (default remainder).
+ * @return The subview.
+ * @throw std::out_of_range If __pos > size().
+ *
+ * Construct and return a subview using the `__n` characters starting at
+ * `__pos`. If the string is too short, use the remainder of the
+ * characters. If `__pos` is beyond the end of the string, out_of_range
+ * is thrown.
+ */
+ [[nodiscard]]
+ constexpr basic_string_view<_CharT, _Traits>
+ subview(size_type __pos = 0, size_type __n = npos) const
+ { return __sv_type(*this).subview(__pos, __n); }
+#endif
+
/**
* @brief Compare to a string.
* @param __str String to compare against.
diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index b1a6206..38cea4c 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -273,6 +273,12 @@ __INT_N(__GLIBCXX_TYPE_INT_N_2)
__INT_N(__GLIBCXX_TYPE_INT_N_3)
#endif
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+// In strict modes __GLIBCXX_TYPE_INT_N_0 is not defined for __int128,
+// but we want to always treat signed/unsigned __int128 as integral types.
+__INT_N(__int128)
+#endif
+
#undef __INT_N
//
@@ -307,6 +313,15 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
typedef __true_type __type;
};
+#ifdef _GLIBCXX_USE_FLOAT128
+ template<>
+ struct __is_floating<__float128>
+ {
+ enum { __value = 1 };
+ typedef __true_type __type;
+ };
+#endif
+
#ifdef __STDCPP_FLOAT16_T__
template<>
struct __is_floating<_Float16>
@@ -545,17 +560,6 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
{ enum { __width = __GLIBCXX_BITSIZE_INT_N_3 }; };
#endif
-#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
- // In strict modes __is_integer<__int128> is false,
- // but we want to allow memcpy between signed/unsigned __int128.
- __extension__
- template<>
- struct __memcpyable_integer<__int128> { enum { __width = 128 }; };
- __extension__
- template<>
- struct __memcpyable_integer<unsigned __int128> { enum { __width = 128 }; };
-#endif
-
#if _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 && _GLIBCXX_LDOUBLE_IS_IEEE_BINARY64
template<>
struct __memcpyable<double*, long double*> { enum { __value = true }; };
diff --git a/libstdc++-v3/include/bits/cpyfunc_impl.h b/libstdc++-v3/include/bits/cpyfunc_impl.h
new file mode 100644
index 0000000..f1918dd
--- /dev/null
+++ b/libstdc++-v3/include/bits/cpyfunc_impl.h
@@ -0,0 +1,273 @@
+// Implementation of std::copyable_function -*- 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 include/bits/cpyfunc_impl.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _GLIBCXX_MOF_CV
+# define _GLIBCXX_MOF_CV
+#endif
+
+#ifdef _GLIBCXX_MOF_REF
+# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
+#else
+# define _GLIBCXX_MOF_REF
+# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV &
+#endif
+
+#define _GLIBCXX_MOF_CV_REF _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @brief Polymorphic copyable function wrapper.
+ * @ingroup functors
+ * @since C++26
+ * @headerfile functional
+ *
+ * The `std::copyable_function` class template is a call wrapper similar
+ * to `std::function`, but it does not provide information about it's
+ * target, and preserves constness.
+ *
+ * It also supports const-qualification, ref-qualification, and
+ * no-throw guarantees. The qualifications and exception-specification
+ * of the `copyable_function::operator()` member function are respected
+ * when invoking the target function.
+ */
+ template<typename _Res, typename... _ArgTypes, bool _Noex>
+ class copyable_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
+ _GLIBCXX_MOF_REF noexcept(_Noex)>
+ : __polyfunc::_Cpy_base
+ {
+ static_assert(
+ (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...),
+ "each parameter type must be a complete class");
+
+ using _Base = __polyfunc::_Cpy_base;
+ using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
+ using _Signature = _Invoker::_Signature;
+
+ template<typename _Tp>
+ using __callable
+ = __conditional_t<_Noex,
+ is_nothrow_invocable_r<_Res, _Tp, _ArgTypes...>,
+ is_invocable_r<_Res, _Tp, _ArgTypes...>>;
+
+ // [func.wrap.copy.con]/1 is-callable-from<VT>
+ template<typename _Vt>
+ static constexpr bool __is_callable_from
+ = __and_v<__callable<_Vt _GLIBCXX_MOF_CV_REF>,
+ __callable<_Vt _GLIBCXX_MOF_INV_QUALS>>;
+
+ public:
+ using result_type = _Res;
+
+ /// Creates an empty object.
+ copyable_function() noexcept { }
+
+ /// Creates an empty object.
+ copyable_function(nullptr_t) noexcept { }
+
+ /// Moves the target object, leaving the source empty.
+ copyable_function(copyable_function&& __x) noexcept
+ : _Base(static_cast<_Base&&>(__x)),
+ _M_invoke(std::__exchange(__x._M_invoke, nullptr))
+ { }
+
+ /// Copies the target object.
+ copyable_function(copyable_function const& __x)
+ : _Base(static_cast<const _Base&>(__x)),
+ _M_invoke(__x._M_invoke)
+ { }
+
+ /// Stores a target object initialized from the argument.
+ template<typename _Fn, typename _Vt = decay_t<_Fn>>
+ requires (!is_same_v<_Vt, copyable_function>)
+ && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt>
+ copyable_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>())
+ {
+ static_assert(is_copy_constructible_v<_Vt>);
+ if constexpr (is_function_v<remove_pointer_t<_Vt>>
+ || is_member_pointer_v<_Vt>
+ || __is_polymorphic_function_v<_Vt>)
+ {
+ if (__f == nullptr)
+ return;
+ }
+
+ if constexpr (!__is_polymorphic_function_v<_Vt>
+ || !__polyfunc::__is_invoker_convertible<_Vt, copyable_function>())
+ {
+ _M_init<_Vt>(std::forward<_Fn>(__f));
+ _M_invoke = _Invoker::template _S_storage<_Vt _GLIBCXX_MOF_INV_QUALS>();
+ }
+ else if constexpr (is_lvalue_reference_v<_Fn>)
+ {
+ _M_copy(__polyfunc::__base_of(__f));
+ _M_invoke = __polyfunc::__invoker_of(__f);
+ }
+ else
+ {
+ _M_move(__polyfunc::__base_of(__f));
+ _M_invoke = std::__exchange(__polyfunc::__invoker_of(__f), nullptr);
+ }
+ }
+
+ /// Stores a target object initialized from the arguments.
+ template<typename _Tp, typename... _Args>
+ requires is_constructible_v<_Tp, _Args...>
+ && __is_callable_from<_Tp>
+ explicit
+ copyable_function(in_place_type_t<_Tp>, _Args&&... __args)
+ noexcept(_S_nothrow_init<_Tp, _Args...>())
+ : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>())
+ {
+ static_assert(is_same_v<decay_t<_Tp>, _Tp>);
+ static_assert(is_copy_constructible_v<_Tp>);
+ _M_init<_Tp>(std::forward<_Args>(__args)...);
+ }
+
+ /// Stores a target object initialized from the arguments.
+ template<typename _Tp, typename _Up, typename... _Args>
+ requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
+ && __is_callable_from<_Tp>
+ explicit
+ copyable_function(in_place_type_t<_Tp>, initializer_list<_Up> __il,
+ _Args&&... __args)
+ noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>())
+ : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>())
+ {
+ static_assert(is_same_v<decay_t<_Tp>, _Tp>);
+ static_assert(is_copy_constructible_v<_Tp>);
+ _M_init<_Tp>(__il, std::forward<_Args>(__args)...);
+ }
+
+ /// Stores a new target object, leaving `x` empty.
+ copyable_function&
+ operator=(copyable_function&& __x) noexcept
+ {
+ // Standard requires support of self assigment, by specifying it as
+ // copy and swap.
+ if (this != std::addressof(__x)) [[likely]]
+ {
+ _Base::operator=(static_cast<_Base&&>(__x));
+ _M_invoke = std::__exchange(__x._M_invoke, nullptr);
+ }
+ return *this;
+ }
+
+ /// Stores a copy of the source target object
+ copyable_function&
+ operator=(const copyable_function& __x)
+ {
+ copyable_function(__x).swap(*this);
+ return *this;
+ }
+
+ /// Destroys the target object (if any).
+ copyable_function&
+ operator=(nullptr_t) noexcept
+ {
+ _M_reset();
+ _M_invoke = nullptr;
+ return *this;
+ }
+
+ /// Stores a new target object, initialized from the argument.
+ template<typename _Fn>
+ requires is_constructible_v<copyable_function, _Fn>
+ copyable_function&
+ operator=(_Fn&& __f)
+ noexcept(is_nothrow_constructible_v<copyable_function, _Fn>)
+ {
+ copyable_function(std::forward<_Fn>(__f)).swap(*this);
+ return *this;
+ }
+
+ ~copyable_function() = default;
+
+ /// True if a target object is present, false otherwise.
+ explicit operator bool() const noexcept
+ { return _M_invoke != nullptr; }
+
+ /** Invoke the target object.
+ *
+ * The target object will be invoked using the supplied arguments,
+ * and as an lvalue or rvalue, and as const or non-const, as dictated
+ * by the template arguments of the `copyable_function` specialization.
+ *
+ * @pre Must not be empty.
+ */
+ _Res
+ operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex)
+ {
+ __glibcxx_assert(*this != nullptr);
+ return _M_invoke(this->_M_storage, std::forward<_ArgTypes>(__args)...);
+ }
+
+ /// Exchange the target objects (if any).
+ void
+ swap(copyable_function& __x) noexcept
+ {
+ _Base::swap(__x);
+ std::swap(_M_invoke, __x._M_invoke);
+ }
+
+ /// Exchange the target objects (if any).
+ friend void
+ swap(copyable_function& __x, copyable_function& __y) noexcept
+ { __x.swap(__y); }
+
+ /// Check for emptiness by comparing with `nullptr`.
+ friend bool
+ operator==(const copyable_function& __x, nullptr_t) noexcept
+ { return __x._M_invoke == nullptr; }
+
+ private:
+ typename _Invoker::__storage_func_t _M_invoke = nullptr;
+
+ template<typename _Func>
+ friend auto&
+ __polyfunc::__invoker_of(_Func&) noexcept;
+
+ template<typename _Func>
+ friend auto&
+ __polyfunc::__base_of(_Func&) noexcept;
+
+ template<typename _Dst, typename _Src>
+ friend consteval bool
+ __polyfunc::__is_invoker_convertible() noexcept;
+ };
+
+#undef _GLIBCXX_MOF_CV_REF
+#undef _GLIBCXX_MOF_CV
+#undef _GLIBCXX_MOF_REF
+#undef _GLIBCXX_MOF_INV_QUALS
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc
index dabb6ec..20b23ff 100644
--- a/libstdc++-v3/include/bits/deque.tcc
+++ b/libstdc++-v3/include/bits/deque.tcc
@@ -381,7 +381,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const difference_type __back_capacity
= (this->_M_impl._M_finish._M_last - this->_M_impl._M_finish._M_cur);
- if (__front_capacity + __back_capacity < _S_buffer_size())
+ if (size_type(__front_capacity + __back_capacity) < _S_buffer_size())
return false;
return std::__shrink_to_fit_aux<deque>::_S_do_it(*this);
@@ -664,7 +664,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
deque<_Tp, _Alloc>::
_M_emplace_aux(iterator __pos, _Args&&... __args)
{
- value_type __x_copy(std::forward<_Args>(__args)...); // XXX copy
+ // We should construct this temporary while the deque is
+ // in its current state in case something in __args...
+ // depends on that state before shuffling elements around.
+ _Temporary_value __tmp(this, std::forward<_Args>(__args)...);
#else
typename deque<_Tp, _Alloc>::iterator
deque<_Tp, _Alloc>::
@@ -695,7 +698,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__pos = this->_M_impl._M_start + __index;
_GLIBCXX_MOVE_BACKWARD3(__pos, __back2, __back1);
}
- *__pos = _GLIBCXX_MOVE(__x_copy);
+#if __cplusplus >= 201103L
+ *__pos = std::move(__tmp._M_val());
+#else
+ *__pos = __x_copy;
+#endif
return __pos;
}
diff --git a/libstdc++-v3/include/bits/formatfwd.h b/libstdc++-v3/include/bits/formatfwd.h
index a6b5ac8..883b772 100644
--- a/libstdc++-v3/include/bits/formatfwd.h
+++ b/libstdc++-v3/include/bits/formatfwd.h
@@ -37,6 +37,12 @@
// <bits/version.h> must have been included before this header:
#ifdef __glibcxx_format // C++ >= 20 && HOSTED
+#include <concepts>
+#include <type_traits>
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
+# include <bits/ranges_base.h> // input_range, range_reference_t
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -50,6 +56,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// [format.formatter], formatter
template<typename _Tp, typename _CharT = char> struct formatter;
+/// @cond undocumented
+ [[noreturn]]
+ inline void
+ __throw_format_error(const char* __what);
+
namespace __format
{
#ifdef _GLIBCXX_USE_WCHAR_T
@@ -60,10 +71,130 @@ namespace __format
concept __char = same_as<_CharT, char>;
#endif
- template<__char _CharT>
- struct __formatter_int;
+ enum class _Align : unsigned char {
+ _Align_default,
+ _Align_left,
+ _Align_right,
+ _Align_centre,
+ };
+ using enum _Align;
+
+ template<typename _CharT> struct _Spec;
+
+ template<__char _CharT> struct __formatter_str;
+ template<__char _CharT> struct __formatter_int;
+ template<__char _CharT> struct __formatter_ptr;
+
+ template<typename _Tp, typename _Context,
+ typename _Formatter
+ = typename _Context::template formatter_type<remove_const_t<_Tp>>,
+ typename _ParseContext
+ = basic_format_parse_context<typename _Context::char_type>>
+ concept __parsable_with
+ = semiregular<_Formatter>
+ && requires (_Formatter __f, _ParseContext __pc)
+ {
+ { __f.parse(__pc) } -> same_as<typename _ParseContext::iterator>;
+ };
+
+ template<typename _Tp, typename _Context,
+ typename _Formatter
+ = typename _Context::template formatter_type<remove_const_t<_Tp>>,
+ typename _ParseContext
+ = basic_format_parse_context<typename _Context::char_type>>
+ concept __formattable_with
+ = semiregular<_Formatter>
+ && requires (const _Formatter __cf, _Tp&& __t, _Context __fc)
+ {
+ { __cf.format(__t, __fc) } -> same_as<typename _Context::iterator>;
+ };
+
+ // An unspecified output iterator type used in the `formattable` concept.
+ template<typename _CharT>
+ struct _Iter_for;
+ template<typename _CharT>
+ using _Iter_for_t = typename _Iter_for<_CharT>::type;
+
+ template<typename _Tp, typename _CharT,
+ typename _Context = basic_format_context<_Iter_for_t<_CharT>, _CharT>>
+ concept __formattable_impl
+ = __parsable_with<_Tp, _Context> && __formattable_with<_Tp, _Context>;
+
+ template<typename _Formatter>
+ concept __has_debug_format = requires(_Formatter __f)
+ {
+ __f.set_debug_format();
+ };
+} // namespace __format
+/// @endcond
+
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
+ // [format.formattable], concept formattable
+ template<typename _Tp, typename _CharT>
+ concept formattable
+ = __format::__formattable_impl<remove_reference_t<_Tp>, _CharT>;
+
+ template<typename _Tp, __format::__char _CharT = char>
+ requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT>
+ class range_formatter;
+
+/// @cond undocumented
+namespace __format
+{
+ template<typename _Rg, typename _CharT>
+ concept __const_formattable_range
+ = ranges::input_range<const _Rg>
+ && formattable<ranges::range_reference_t<const _Rg>, _CharT>;
+
+ // _Rg& and const _Rg& are both formattable and use same formatter
+ // specialization for their references.
+ template<typename _Rg, typename _CharT>
+ concept __simply_formattable_range
+ = __const_formattable_range<_Rg, _CharT>
+ && same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>,
+ remove_cvref_t<ranges::range_reference_t<const _Rg>>>;
+
+ template<typename _Rg, typename _CharT>
+ using __maybe_const_range
+ = __conditional_t<__const_formattable_range<_Rg, _CharT>, const _Rg, _Rg>;
+
+ template<typename _Tp, typename _CharT>
+ using __maybe_const
+ = __conditional_t<formattable<const _Tp, _CharT>, const _Tp, _Tp>;
}
+ // [format.range], formatting of ranges
+ // [format.range.fmtkind], variable template format_kind
+ enum class range_format {
+ disabled,
+ map,
+ set,
+ sequence,
+ string,
+ debug_string
+ };
+
+ /** @brief A constant determining how a range should be formatted.
+ *
+ * The primary template of `std::format_kind` cannot be instantiated.
+ * There is a partial specialization for input ranges and you can
+ * specialize the variable template for your own cv-unqualified types
+ * that satisfy the `ranges::input_range` concept.
+ *
+ * @since C++23
+ */
+ template<typename _Rg>
+ constexpr auto format_kind = []{
+ static_assert(false, "cannot use primary template of 'std::format_kind'");
+ return type_identity<_Rg>{};
+ }();
+#endif // format_ranges
+
+#if __glibcxx_print >= 202403L
+ template<typename>
+ constexpr bool enable_nonlocking_formatter_optimization = false;
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __glibcxx_format
diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h
index 8bcfb80..459b2f6 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -1046,7 +1046,7 @@ namespace __fwdlist
void
assign(_InputIterator __first, _InputIterator __last)
{
- if constexpr (is_assignable<_Tp, decltype(*__first)>::value)
+ if constexpr (is_assignable<_Tp&, decltype(*__first)>::value)
{
auto __prev = before_begin();
auto __curr = begin();
diff --git a/libstdc++-v3/include/bits/funcref_impl.h b/libstdc++-v3/include/bits/funcref_impl.h
new file mode 100644
index 0000000..3fe2fb1
--- /dev/null
+++ b/libstdc++-v3/include/bits/funcref_impl.h
@@ -0,0 +1,202 @@
+// Implementation of std::function_ref -*- 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 include/bits/funcref_impl.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _GLIBCXX_MOF_CV
+# define _GLIBCXX_MOF_CV
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /// @cond undocumented
+ namespace __polyfunc
+ {
+ template<bool _Noex, typename _Ret, typename _Class, typename... _Args>
+ struct __skip_first_arg<_Ret(_Class::*)(_Args...) _GLIBCXX_MOF_CV
+ noexcept(_Noex)>
+ { using type = _Ret(_Args...) noexcept(_Noex); };
+
+ template<bool _Noex, typename _Ret, typename _Class, typename... _Args>
+ struct __skip_first_arg<_Ret(_Class::*)(_Args...) _GLIBCXX_MOF_CV&
+ noexcept(_Noex)>
+ { using type = _Ret(_Args...) noexcept(_Noex); };
+ } // namespace __polyfunc
+ /// @endcond
+
+ /**
+ * @brief Non-owning polymorphic function wrapper.
+ * @ingroup functors
+ * @since C++26
+ * @headerfile functional
+ *
+ * The `std::function_ref` class template is a non-owning call wrapper,
+ * that refers to a bound object. Using function_ref outside of the lifetime
+ * of the bound object has undefined behavior.
+ *
+ * It supports const-qualification and no-throw guarantees. The
+ * qualifications and exception-specification of the signature are respected
+ * when invoking the reference function.
+ */
+ template<typename _Res, typename... _ArgTypes, bool _Noex>
+ class function_ref<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
+ noexcept(_Noex)>
+ {
+ static_assert(
+ (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...),
+ "each parameter type must be a complete class");
+
+ using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
+ using _Signature = _Invoker::_Signature;
+
+ // [func.wrap.ref.ctor]/1 is-invokable-using
+ template<typename... _Tps>
+ static constexpr bool __is_invocable_using
+ = __conditional_t<_Noex,
+ is_nothrow_invocable_r<_Res, _Tps..., _ArgTypes...>,
+ is_invocable_r<_Res, _Tps..., _ArgTypes...>>::value;
+
+ public:
+ /// Target and bound object is function pointed by parameter.
+ template<typename _Fn>
+ requires is_function_v<_Fn> && __is_invocable_using<_Fn*>
+ function_ref(_Fn* __fn) noexcept
+ {
+ __glibcxx_assert(__fn != nullptr);
+ _M_invoke = _Invoker::template _S_ptrs<_Fn*>();
+ _M_init(__fn);
+ }
+
+ /// Target and bound object is object referenced by parameter.
+ template<typename _Fn, typename _Vt = remove_reference_t<_Fn>>
+ requires (!is_same_v<remove_cv_t<_Vt>, function_ref>)
+ && (!is_member_pointer_v<_Vt>)
+ // We deviate from standard by having this condition, that forces
+ // function references to use _Fn* constructors. This simplies
+ // implementation and provide better diagnostic when used in
+ // constant expression (above constructor is not constexpr).
+ && (!is_function_v<_Vt>)
+ && __is_invocable_using<_Vt _GLIBCXX_MOF_CV&>
+ constexpr
+ function_ref(_Fn&& __f) noexcept
+ {
+ _M_invoke = _Invoker::template _S_ptrs<_Vt _GLIBCXX_MOF_CV&>();
+ _M_init(std::addressof(__f));
+ }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4256. Incorrect constrains for function_ref constructors from nontype
+ /// Target object is __fn. There is no bound object.
+ template<auto __fn>
+ requires __is_invocable_using<const decltype(__fn)&>
+ constexpr
+ function_ref(nontype_t<__fn>) noexcept
+ {
+ using _Fn = remove_cv_t<decltype(__fn)>;
+ if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
+ static_assert(__fn != nullptr);
+
+ _M_invoke = &_Invoker::template _S_nttp<__fn>;
+ _M_ptrs._M_obj = nullptr;
+ }
+
+ /// Target object is equivalent to std::bind_front<_fn>(std::ref(__ref)).
+ /// Bound object is object referenced by second parameter.
+ template<auto __fn, typename _Up, typename _Td = remove_reference_t<_Up>>
+ requires (!is_rvalue_reference_v<_Up&&>)
+ && __is_invocable_using<const decltype(__fn)&, _Td _GLIBCXX_MOF_CV&>
+ constexpr
+ function_ref(nontype_t<__fn>, _Up&& __ref) noexcept
+ {
+ using _Fn = remove_cv_t<decltype(__fn)>;
+ if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
+ static_assert(__fn != nullptr);
+
+ if constexpr (is_member_pointer_v<_Fn>
+ && same_as<_Td, typename __inv_unwrap<_Td>::type>)
+ // N.B. invoking member pointer on lvalue produces the same effects,
+ // as invoking it on pointer to that lvalue.
+ _M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>;
+ else
+ _M_invoke = &_Invoker::template _S_bind_ref<__fn, _Td _GLIBCXX_MOF_CV&>;
+ _M_init(std::addressof(__ref));
+ }
+
+ /// Target object is equivalent to std::bind_front<_fn>(__ptr).
+ /// Bound object is object pointed by second parameter (if any).
+ template<auto __fn, typename _Td>
+ requires __is_invocable_using<const decltype(__fn)&, _Td _GLIBCXX_MOF_CV*>
+ constexpr
+ function_ref(nontype_t<__fn>, _Td _GLIBCXX_MOF_CV* __ptr) noexcept
+ {
+ using _Fn = remove_cv_t<decltype(__fn)>;
+ if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
+ static_assert(__fn != nullptr);
+ if constexpr (is_member_pointer_v<_Fn>)
+ __glibcxx_assert(__ptr != nullptr);
+
+ _M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>;
+ _M_init(__ptr);
+ }
+
+ template<typename _Tp>
+ requires (!is_same_v<_Tp, function_ref>)
+ && (!is_pointer_v<_Tp>) && (!__is_nontype_v<_Tp>)
+ function_ref&
+ operator=(_Tp) = delete;
+
+ /** Invoke the target object.
+ *
+ * The bound object will be invoked using the supplied arguments,
+ * and as const or non-const, as dictated by the template arguments
+ * of the `function_ref` specialization.
+ */
+ _Res
+ operator()(_ArgTypes... __args) const noexcept(_Noex)
+ { return _M_invoke(_M_ptrs, std::forward<_ArgTypes>(__args)...); }
+
+ private:
+ template<typename _Tp>
+ constexpr void
+ _M_init(_Tp* __ptr) noexcept
+ {
+ if constexpr (is_function_v<_Tp>)
+ _M_ptrs._M_func = reinterpret_cast<void(*)()>(__ptr);
+ else
+ _M_ptrs._M_obj = __ptr;
+ }
+
+ typename _Invoker::__ptrs_func_t _M_invoke;
+ __polyfunc::_Ptrs _M_ptrs;
+ };
+
+#undef _GLIBCXX_MOF_CV
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h
index e84c9ee..8456089 100644
--- a/libstdc++-v3/include/bits/functional_hash.h
+++ b/libstdc++-v3/include/bits/functional_hash.h
@@ -199,6 +199,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3 unsigned)
#endif
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+ // In strict modes __GLIBCXX_TYPE_INT_N_0 is not defined for __int128,
+ // but we want to always treat signed/unsigned __int128 as integral types.
+ __extension__
+ _Cxx_hashtable_define_trivial_hash(__int128)
+ __extension__
+ _Cxx_hashtable_define_trivial_hash(__int128 unsigned)
+#endif
+
#undef _Cxx_hashtable_define_trivial_hash
struct _Hash_impl
diff --git a/libstdc++-v3/include/bits/funcwrap.h b/libstdc++-v3/include/bits/funcwrap.h
new file mode 100644
index 0000000..67fd591
--- /dev/null
+++ b/libstdc++-v3/include/bits/funcwrap.h
@@ -0,0 +1,622 @@
+// Implementation of std::move_only_function, std::copyable_function
+// and std::function_ref -*- 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 include/bits/funcwrap.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _GLIBCXX_FUNCWRAP_H
+#define _GLIBCXX_FUNCWRAP_H 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <bits/version.h>
+
+#if __glibcxx_move_only_function || __glibcxx_copyable_function || __glibcxx_function_ref
+
+#include <bits/invoke.h>
+#include <bits/utility.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /// @cond undocumented
+ template<typename _Tp>
+ inline constexpr bool __is_polymorphic_function_v = false;
+
+ namespace __polyfunc
+ {
+ union _Ptrs
+ {
+ const void* _M_obj;
+ void (*_M_func)();
+ };
+
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ constexpr auto*
+ __cast_to(_Ptrs __ptrs) noexcept
+ {
+ using _Td = remove_reference_t<_Tp>;
+ if constexpr (is_function_v<_Td>)
+ return reinterpret_cast<_Td*>(__ptrs._M_func);
+ else if constexpr (is_const_v<_Td>)
+ return static_cast<_Td*>(__ptrs._M_obj);
+ else
+ return static_cast<_Td*>(const_cast<void*>(__ptrs._M_obj));
+ }
+
+ struct _Storage
+ {
+ void* _M_addr() noexcept { return &_M_bytes[0]; }
+ void const* _M_addr() const noexcept { return &_M_bytes[0]; }
+
+ template<typename _Tp>
+ static consteval bool
+ _S_stored_locally() noexcept
+ {
+ return sizeof(_Tp) <= sizeof(_Storage)
+ && alignof(_Tp) <= alignof(_Storage)
+ && is_nothrow_move_constructible_v<_Tp>;
+ }
+
+ template<typename _Tp, typename... _Args>
+ static consteval bool
+ _S_nothrow_init() noexcept
+ {
+ if constexpr (_S_stored_locally<_Tp>())
+ return is_nothrow_constructible_v<_Tp, _Args...>;
+ return false;
+ }
+
+ template<typename _Tp, typename... _Args>
+ void
+ _M_init(_Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>())
+ {
+ if constexpr (is_function_v<remove_pointer_t<_Tp>>)
+ {
+ static_assert( sizeof...(__args) <= 1 );
+ // __args can have up to one element, returns nullptr if empty.
+ _Tp __func = (nullptr, ..., __args);
+ _M_ptrs._M_func = reinterpret_cast<void(*)()>(__func);
+ }
+ else if constexpr (!_S_stored_locally<_Tp>())
+ _M_ptrs._M_obj = new _Tp(std::forward<_Args>(__args)...);
+ else
+ ::new (_M_addr()) _Tp(std::forward<_Args>(__args)...);
+ }
+
+ // We want to have enough space to store a simple delegate type.
+ struct _Delegate { void (_Storage::*__pfm)(); _Storage* __obj; };
+ union {
+ _Ptrs _M_ptrs;
+ alignas(_Delegate) alignas(void(*)())
+ unsigned char _M_bytes[sizeof(_Delegate)];
+ };
+ };
+
+ template<bool _Noex, typename _Ret, typename... _Args>
+ struct _Base_invoker
+ {
+ using _Signature = _Ret(*)(_Args...) noexcept(_Noex);
+
+ using __storage_func_t = _Ret(*)(const _Storage&, _Args...) noexcept(_Noex);
+ template<typename _Tp>
+ static consteval __storage_func_t
+ _S_storage()
+ { return &_S_call_storage<_Adjust_target<_Tp>>; }
+
+ using __ptrs_func_t = _Ret(*)(_Ptrs, _Args...) noexcept(_Noex);
+ template<typename _Tp>
+ static consteval __ptrs_func_t
+ _S_ptrs()
+ { return &_S_call_ptrs<_Adjust_target<_Tp>>; }
+
+#ifdef __glibcxx_function_ref // C++ >= 26
+ template<auto __fn>
+ static _Ret
+ _S_nttp(_Ptrs, _Args... __args) noexcept(_Noex)
+ { return std::__invoke_r<_Ret>(__fn, std::forward<_Args>(__args)...); }
+
+ template<auto __fn, typename _Tp>
+ static _Ret
+ _S_bind_ptr(_Ptrs __ptrs, _Args... __args) noexcept(_Noex)
+ {
+ auto* __p = __polyfunc::__cast_to<_Tp>(__ptrs);
+ return std::__invoke_r<_Ret>(__fn, __p,
+ std::forward<_Args>(__args)...);
+ }
+
+ template<auto __fn, typename _Ref>
+ static _Ret
+ _S_bind_ref(_Ptrs __ptrs, _Args... __args) noexcept(_Noex)
+ {
+ auto* __p = __polyfunc::__cast_to<_Ref>(__ptrs);
+ return std::__invoke_r<_Ret>(__fn, static_cast<_Ref>(*__p),
+ std::forward<_Args>(__args)...);
+ }
+#endif // __glibcxx_function_ref
+
+ private:
+ template<typename _Tp, typename _Td = remove_cvref_t<_Tp>>
+ using _Adjust_target =
+ __conditional_t<is_pointer_v<_Td> || is_member_pointer_v<_Td>, _Td, _Tp>;
+
+ template<typename _Tp>
+ static _Ret
+ _S_call_storage(const _Storage& __ref, _Args... __args) noexcept(_Noex)
+ {
+ _Ptrs __ptrs;
+ if constexpr (is_function_v<remove_pointer_t<_Tp>>)
+ __ptrs._M_func = __ref._M_ptrs._M_func;
+ else if constexpr (!_Storage::_S_stored_locally<remove_cvref_t<_Tp>>())
+ __ptrs._M_obj = __ref._M_ptrs._M_obj;
+ else
+ __ptrs._M_obj = __ref._M_addr();
+ return _S_call_ptrs<_Tp>(__ptrs, std::forward<_Args>(__args)...);
+ }
+
+ template<typename _Tp>
+ static _Ret
+ _S_call_ptrs(_Ptrs __ptrs, _Args... __args) noexcept(_Noex)
+ {
+ if constexpr (is_function_v<remove_pointer_t<_Tp>>)
+ return std::__invoke_r<_Ret>(reinterpret_cast<_Tp>(__ptrs._M_func),
+ std::forward<_Args>(__args)...);
+ else
+ {
+ auto* __p = __polyfunc::__cast_to<_Tp>(__ptrs);
+ return std::__invoke_r<_Ret>(static_cast<_Tp>(*__p),
+ std::forward<_Args>(__args)...);
+ }
+ }
+ };
+
+ template<typename _Tp>
+ consteval bool
+ __pass_by_value()
+ {
+ // n.b. sizeof(Incomplete&) is ill-formed for incomplete types,
+ // so we check is_reference_v first.
+ if constexpr (is_reference_v<_Tp> || is_scalar_v<_Tp>)
+ return true;
+ else
+ // n.b. we already asserted that types are complete in wrappers,
+ // avoid triggering additional errors from this function.
+ if constexpr (std::__is_complete_or_unbounded(__type_identity<_Tp>()))
+ if constexpr (sizeof(_Tp) <= 2 * sizeof(void*))
+ return is_trivially_move_constructible_v<_Tp>
+ && is_trivially_destructible_v<_Tp>;
+ return false;
+ }
+
+ template<typename _Tp>
+ using __param_t = __conditional_t<__pass_by_value<_Tp>(), _Tp, _Tp&&>;
+
+ template<bool _Noex, typename _Ret, typename... _Args>
+ using _Invoker = _Base_invoker<_Noex, remove_cv_t<_Ret>, __param_t<_Args>...>;
+
+ template<typename _Func>
+ auto&
+ __invoker_of(_Func& __f) noexcept
+ { return __f._M_invoke; }
+
+ template<typename _Func>
+ auto&
+ __base_of(_Func& __f) noexcept
+ { return static_cast<__like_t<_Func&, typename _Func::_Base>>(__f); }
+
+ template<typename _Src, typename _Dst>
+ consteval bool
+ __is_invoker_convertible() noexcept
+ {
+ if constexpr (requires { typename _Src::_Signature; })
+ return is_convertible_v<typename _Src::_Signature,
+ typename _Dst::_Signature>;
+ else
+ return false;
+ }
+
+#if __glibcxx_move_only_function || __glibcxx_copyable_function
+ struct _Manager
+ {
+ enum class _Op
+ {
+ // saves address of entity in *__src to __target._M_ptrs,
+ _Address,
+ // moves entity stored in *__src to __target, __src becomes empty
+ _Move,
+ // copies entity stored in *__src to __target, supported only if
+ // _ProvideCopy is specified.
+ _Copy,
+ // destroys entity stored in __target, __src is ignoring
+ _Destroy,
+ };
+
+ // A function that performs operation __op on the __target and possibly __src.
+ using _Func = void (*)(_Op __op, _Storage& __target, const _Storage* __src);
+
+ // The no-op manager function for objects with no target.
+ static void _S_empty(_Op, _Storage&, const _Storage*) noexcept { }
+
+ template<bool _ProvideCopy, typename _Tp>
+ consteval static auto
+ _S_select()
+ {
+ if constexpr (is_function_v<remove_pointer_t<_Tp>>)
+ return &_S_func;
+ else if constexpr (!_Storage::_S_stored_locally<_Tp>())
+ return &_S_ptr<_ProvideCopy, _Tp>;
+ else if constexpr (is_trivially_copyable_v<_Tp>)
+ return &_S_trivial;
+ else
+ return &_S_local<_ProvideCopy, _Tp>;
+ }
+
+ private:
+ static void
+ _S_func(_Op __op, _Storage& __target, const _Storage* __src) noexcept
+ {
+ switch (__op)
+ {
+ case _Op::_Address:
+ case _Op::_Move:
+ case _Op::_Copy:
+ __target._M_ptrs._M_func = __src->_M_ptrs._M_func;
+ return;
+ case _Op::_Destroy:
+ return;
+ }
+ }
+
+ static void
+ _S_trivial(_Op __op, _Storage& __target, const _Storage* __src) noexcept
+ {
+ switch (__op)
+ {
+ case _Op::_Address:
+ __target._M_ptrs._M_obj = __src->_M_addr();
+ return;
+ case _Op::_Move:
+ case _Op::_Copy:
+ // N.B. Creating _Storage starts lifetime of _M_bytes char array,
+ // that implicitly creates, amongst other, all possible trivially
+ // copyable objects, so we copy any object present in __src._M_bytes.
+ ::new (&__target) _Storage(*__src);
+ return;
+ case _Op::_Destroy:
+ return;
+ }
+ }
+
+ template<bool _Provide_copy, typename _Tp>
+ static void
+ _S_local(_Op __op, _Storage& __target, const _Storage* __src)
+ noexcept(!_Provide_copy)
+ {
+ switch (__op)
+ {
+ case _Op::_Address:
+ __target._M_ptrs._M_obj = __src->_M_addr();
+ return;
+ case _Op::_Move:
+ {
+ _Tp* __obj = static_cast<_Tp*>(const_cast<void*>(__src->_M_addr()));
+ ::new(__target._M_addr()) _Tp(std::move(*__obj));
+ __obj->~_Tp();
+ }
+ return;
+ case _Op::_Destroy:
+ static_cast<_Tp*>(__target._M_addr())->~_Tp();
+ return;
+ case _Op::_Copy:
+ if constexpr (_Provide_copy)
+ {
+ auto* __obj = static_cast<const _Tp*>(__src->_M_addr());
+ ::new (__target._M_addr()) _Tp(*__obj);
+ return;
+ }
+ __builtin_unreachable();
+ }
+ }
+
+ template<bool _Provide_copy, typename _Tp>
+ static void
+ _S_ptr(_Op __op, _Storage& __target, const _Storage* __src)
+ noexcept(!_Provide_copy)
+ {
+ switch (__op)
+ {
+ case _Op::_Address:
+ case _Op::_Move:
+ __target._M_ptrs._M_obj = __src->_M_ptrs._M_obj;
+ return;
+ case _Op::_Destroy:
+ delete static_cast<const _Tp*>(__target._M_ptrs._M_obj);
+ return;
+ case _Op::_Copy:
+ if constexpr (_Provide_copy)
+ {
+ auto* __obj = static_cast<const _Tp*>(__src->_M_ptrs._M_obj);
+ __target._M_ptrs._M_obj = new _Tp(*__obj);
+ return;
+ }
+ __builtin_unreachable();
+ }
+ }
+ };
+
+ class _Mo_base
+ {
+ protected:
+ _Mo_base() noexcept
+ : _M_manage(_Manager::_S_empty)
+ { }
+
+ _Mo_base(_Mo_base&& __x) noexcept
+ { _M_move(__x); }
+
+ template<typename _Tp, typename... _Args>
+ static consteval bool
+ _S_nothrow_init() noexcept
+ { return _Storage::_S_nothrow_init<_Tp, _Args...>(); }
+
+ template<typename _Tp, typename... _Args>
+ void
+ _M_init(_Args&&... __args)
+ noexcept(_S_nothrow_init<_Tp, _Args...>())
+ {
+ _M_storage._M_init<_Tp>(std::forward<_Args>(__args)...);
+ _M_manage = _Manager::_S_select<false, _Tp>();
+ }
+
+ void
+ _M_move(_Mo_base& __x) noexcept
+ {
+ using _Op = _Manager::_Op;
+ _M_manage = std::__exchange(__x._M_manage, _Manager::_S_empty);
+ _M_manage(_Op::_Move, _M_storage, &__x._M_storage);
+ }
+
+ _Mo_base&
+ operator=(_Mo_base&& __x) noexcept
+ {
+ _M_destroy();
+ _M_move(__x);
+ return *this;
+ }
+
+ void
+ _M_reset() noexcept
+ {
+ _M_destroy();
+ _M_manage = _Manager::_S_empty;
+ }
+
+ void _M_destroy() noexcept
+ { _M_manage(_Manager::_Op::_Destroy, _M_storage, nullptr); }
+
+ ~_Mo_base()
+ { _M_destroy(); }
+
+ void
+ swap(_Mo_base& __x) noexcept
+ {
+ using _Op = _Manager::_Op;
+ // Order of operations here is more efficient if __x is empty.
+ _Storage __s;
+ __x._M_manage(_Op::_Move, __s, &__x._M_storage);
+ _M_manage(_Op::_Move, __x._M_storage, &_M_storage);
+ __x._M_manage(_Op::_Move, _M_storage, &__s);
+ std::swap(_M_manage, __x._M_manage);
+ }
+
+ _Manager::_Func _M_manage;
+ _Storage _M_storage;
+ };
+#endif // __glibcxx_copyable_function || __glibcxx_copyable_function
+} // namespace __polyfunc
+ /// @endcond
+
+#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
+ template<typename... _Signature>
+ class move_only_function; // not defined
+
+ /// @cond undocumented
+ template<typename _Tp>
+ constexpr bool __is_polymorphic_function_v<move_only_function<_Tp>> = true;
+
+ namespace __detail::__variant
+ {
+ template<typename> struct _Never_valueless_alt; // see <variant>
+
+ // Provide the strong exception-safety guarantee when emplacing a
+ // move_only_function into a variant.
+ template<typename... _Signature>
+ struct _Never_valueless_alt<std::move_only_function<_Signature...>>
+ : true_type
+ { };
+ } // namespace __detail::__variant
+ /// @endcond
+#endif // __glibcxx_move_only_function
+
+#ifdef __glibcxx_copyable_function // C++ >= 26 && HOSTED
+ /// @cond undocumented
+ namespace __polyfunc
+ {
+ class _Cpy_base : public _Mo_base
+ {
+ protected:
+ _Cpy_base() = default;
+
+ template<typename _Tp, typename... _Args>
+ void
+ _M_init(_Args&&... __args)
+ noexcept(_S_nothrow_init<_Tp, _Args...>())
+ {
+ _M_storage._M_init<_Tp>(std::forward<_Args>(__args)...);
+ _M_manage = _Manager::_S_select<true, _Tp>();
+ }
+
+ void
+ _M_copy(_Cpy_base const& __x)
+ {
+ using _Op = _Manager::_Op;
+ __x._M_manage(_Op::_Copy, _M_storage, &__x._M_storage);
+ _M_manage = __x._M_manage;
+ }
+
+ _Cpy_base(_Cpy_base&&) = default;
+
+ _Cpy_base(_Cpy_base const& __x)
+ { _M_copy(__x); }
+
+ _Cpy_base&
+ operator=(_Cpy_base&&) = default;
+
+ _Cpy_base&
+ // Needs to use copy and swap for exception guarantees.
+ operator=(_Cpy_base const&) = delete;
+ };
+ } // namespace __polyfunc
+ /// @endcond
+
+ template<typename... _Signature>
+ class copyable_function; // not defined
+
+ template<typename _Tp>
+ constexpr bool __is_polymorphic_function_v<copyable_function<_Tp>> = true;
+
+ namespace __detail::__variant
+ {
+ template<typename> struct _Never_valueless_alt; // see <variant>
+
+ // Provide the strong exception-safety guarantee when emplacing a
+ // copyable_function into a variant.
+ template<typename... _Signature>
+ struct _Never_valueless_alt<std::copyable_function<_Signature...>>
+ : true_type
+ { };
+ } // namespace __detail::__variant
+#endif // __glibcxx_copyable_function
+
+#ifdef __glibcxx_function_ref // C++ >= 26
+ /// @cond undocumented
+ namespace __polyfunc
+ {
+ template<typename _Sig>
+ struct __skip_first_arg;
+
+ // Additional partial specializations are defined in bits/funcref_impl.h
+ template<bool _Noex, typename _Ret, typename _Arg, typename... _Args>
+ struct __skip_first_arg<_Ret(*)(_Arg, _Args...) noexcept(_Noex)>
+ { using type = _Ret(_Args...) noexcept(_Noex); };
+
+ // Returns a function pointer to signature to be used with function_ref, or void.
+ template<typename _Fn, typename _Tr>
+ consteval auto
+ __deduce_funcref()
+ {
+ if constexpr (is_member_object_pointer_v<_Fn>)
+ {
+ if constexpr (is_invocable_v<_Fn, _Tr>)
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4425. CTAD function_ref from data member pointer should produce
+ // noexcept signature
+ return static_cast<invoke_result_t<_Fn, _Tr>(*)() noexcept>(nullptr);
+ }
+ else if constexpr (requires { typename __skip_first_arg<_Fn>::type; })
+ return static_cast<__skip_first_arg<_Fn>::type*>(nullptr);
+ }
+ } // namespace __polyfunc
+ /// @endcond
+
+ template<typename... _Signature>
+ class function_ref; // not defined
+
+ template<typename _Fn>
+ requires is_function_v<_Fn>
+ function_ref(_Fn*) -> function_ref<_Fn>;
+
+ template<auto __f, class _Fn = remove_pointer_t<decltype(__f)>>
+ requires is_function_v<_Fn>
+ function_ref(nontype_t<__f>) -> function_ref<_Fn>;
+
+ template<auto __f, typename _Tp,
+ typename _SignaturePtr =
+ decltype(__polyfunc::__deduce_funcref<decltype(__f), _Tp&>())>
+ requires (!is_void_v<_SignaturePtr>)
+ function_ref(nontype_t<__f>, _Tp&&)
+ -> function_ref<remove_pointer_t<_SignaturePtr>>;
+
+#endif // __glibcxx_function_ref
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_REF &
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_REF &&
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#define _GLIBCXX_MOF_REF &
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#define _GLIBCXX_MOF_REF &&
+#include "mofunc_impl.h"
+#endif // __glibcxx_move_only_function
+
+#ifdef __glibcxx_copyable_function // C++ >= 26 && HOSTED
+#include "cpyfunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#include "cpyfunc_impl.h"
+#define _GLIBCXX_MOF_REF &
+#include "cpyfunc_impl.h"
+#define _GLIBCXX_MOF_REF &&
+#include "cpyfunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#define _GLIBCXX_MOF_REF &
+#include "cpyfunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#define _GLIBCXX_MOF_REF &&
+#include "cpyfunc_impl.h"
+#endif // __glibcxx_copyable_function
+
+#ifdef __glibcxx_function_ref // C++ >= 26
+#include "funcref_impl.h"
+#define _GLIBCXX_MOF_CV const
+#include "funcref_impl.h"
+#endif // __glibcxx_function_ref
+
+#endif // move_only_function || copyable_function || function_ref
+#endif // _GLIBCXX_FUNCWRAP_H
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 20f9bd9..06cc51a 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -38,7 +38,7 @@
#include <bits/enable_special_members.h>
#include <bits/stl_algobase.h> // fill_n, is_permutation
#include <bits/stl_function.h> // __has_is_transparent_t
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
# include <bits/node_handle.h>
#endif
@@ -349,7 +349,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using size_type = typename __hashtable_base::size_type;
using difference_type = typename __hashtable_base::difference_type;
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
using node_type = _Node_handle<_Key, _Value, __node_alloc_type>;
using insert_return_type = _Node_insert_return<iterator, node_type>;
#endif
@@ -477,15 +477,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static constexpr bool
_S_nothrow_move()
{
-#if __cplusplus <= 201402L
+#if __cpp_constexpr >= 201304 // >= C++14
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ if constexpr (_No_realloc)
+ if constexpr (is_nothrow_copy_constructible<_Hash>::value)
+ return is_nothrow_copy_constructible<_Equal>::value;
+ return false;
+# pragma GCC diagnostic pop
+#else // In C++11 a constexpr function must be a single statement.
return __and_<__bool_constant<_No_realloc>,
is_nothrow_copy_constructible<_Hash>,
is_nothrow_copy_constructible<_Equal>>::value;
-#else
- if constexpr (_No_realloc)
- if constexpr (is_nothrow_copy_constructible<_Hash>())
- return is_nothrow_copy_constructible<_Equal>();
- return false;
#endif
}
@@ -1928,7 +1931,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
-> const_iterator
{ return const_iterator(_M_locate(__k)); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Key, typename _Value, typename _Alloc,
typename _ExtractKey, typename _Equal,
typename _Hash, typename _RangeHash, typename _Unused,
@@ -1976,7 +1979,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::size_t __bkt = _M_bucket_index(__code);
return const_iterator(_M_find_node_tr(__bkt, __k, __code));
}
-#endif
+#endif // C++20 __glibcxx_generic_unordered_lookup
template<typename _Key, typename _Value, typename _Alloc,
typename _ExtractKey, typename _Equal,
@@ -2004,7 +2007,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __result;
}
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Key, typename _Value, typename _Alloc,
typename _ExtractKey, typename _Equal,
typename _Hash, typename _RangeHash, typename _Unused,
@@ -2049,7 +2052,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __result;
}
-#endif
+#endif // C++20 __glibcxx_generic_unordered_lookup
template<typename _Key, typename _Value, typename _Alloc,
typename _ExtractKey, typename _Equal,
@@ -2099,7 +2102,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return { __beg, __ite };
}
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Key, typename _Value, typename _Alloc,
typename _ExtractKey, typename _Equal,
typename _Hash, typename _RangeHash, typename _Unused,
@@ -2187,7 +2190,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return { __beg, __ite };
}
-#endif
+#endif // C++20 __glibcxx_generic_unordered_lookup
// Find the node before the one whose key compares equal to k in the bucket
// bkt. Return nullptr if no node is found.
@@ -2963,7 +2966,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#pragma GCC diagnostic pop
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
template<typename, typename, typename> class _Hash_merge_helper { };
#endif // C++17
diff --git a/libstdc++-v3/include/bits/indirect.h b/libstdc++-v3/include/bits/indirect.h
new file mode 100644
index 0000000..2df46cc
--- /dev/null
+++ b/libstdc++-v3/include/bits/indirect.h
@@ -0,0 +1,836 @@
+// Vocabulary Types for Composite Class Design -*- 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 include/bits/indirect.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{memory}
+ */
+
+#ifndef _GLIBCXX_INDIRECT_H
+#define _GLIBCXX_INDIRECT_H 1
+
+#pragma GCC system_header
+
+#include <bits/version.h>
+
+#if __glibcxx_indirect || __glibcxx_polymorphic // >= C++26
+#include <compare>
+#include <initializer_list>
+#include <bits/allocator.h>
+#include <bits/alloc_traits.h>
+#include <bits/allocated_ptr.h> // __allocate_guarded
+#include <bits/uses_allocator.h> // allocator_arg_t
+#include <bits/utility.h> // __is_in_place_type_v
+#include <bits/functional_hash.h> // hash
+#include <bits/memory_resource.h> // polymorphic_allocator
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#if __glibcxx_indirect
+ template<typename _Tp, typename _Alloc = allocator<_Tp>>
+ class indirect;
+
+ template<typename _Tp>
+ constexpr bool __is_indirect = false;
+ template<typename _Tp, typename _Alloc>
+ constexpr bool __is_indirect<indirect<_Tp, _Alloc>> = true;
+
+#if _GLIBCXX_HOSTED
+ namespace pmr
+ {
+ template<typename _Tp>
+ using indirect = indirect<_Tp, polymorphic_allocator<_Tp>>;
+ }
+#endif
+
+ // [indirect], class template indirect
+ template<typename _Tp, typename _Alloc>
+ class indirect
+ {
+ static_assert(is_object_v<_Tp>);
+ static_assert(!is_array_v<_Tp>);
+ static_assert(!is_same_v<_Tp, in_place_t>);
+ static_assert(!__is_in_place_type_v<_Tp>);
+ static_assert(!is_const_v<_Tp> && !is_volatile_v<_Tp>);
+
+ using _ATraits = allocator_traits<_Alloc>;
+ static_assert(is_same_v<_Tp, typename _ATraits::value_type>);
+
+ public:
+ using value_type = _Tp;
+ using allocator_type = _Alloc;
+ using pointer = typename allocator_traits<_Alloc>::pointer;
+ using const_pointer = typename allocator_traits<_Alloc>::const_pointer;
+
+ constexpr explicit
+ indirect() requires is_default_constructible_v<_Alloc>
+ : _M_objp(_M_make_obj_chk())
+ { }
+
+ constexpr explicit
+ indirect(allocator_arg_t, const _Alloc& __a)
+ : _M_alloc(__a), _M_objp(_M_make_obj_chk())
+ { }
+
+ constexpr
+ indirect(const indirect& __o)
+ : indirect(allocator_arg,
+ _ATraits::select_on_container_copy_construction(__o._M_alloc),
+ __o)
+ { }
+
+ constexpr
+ indirect(allocator_arg_t, const _Alloc& __a, const indirect& __other)
+ : _M_alloc(__a)
+ {
+ if (__other._M_objp)
+ _M_objp = _M_make_obj_chk(__other.__get());
+ else
+ _M_objp = nullptr;
+ }
+
+ constexpr
+ indirect(indirect&& __other) noexcept
+ : _M_alloc(std::move(__other._M_alloc)),
+ _M_objp(std::__exchange(__other._M_objp, nullptr))
+ { }
+
+ constexpr
+ indirect(allocator_arg_t, const _Alloc& __a,
+ indirect&& __other) noexcept(_ATraits::is_always_equal::value)
+ : _M_alloc(__a),
+ _M_objp(std::__exchange(__other._M_objp, nullptr))
+ {
+ if constexpr (!_ATraits::is_always_equal::value)
+ if (_M_objp && _M_alloc != __other._M_alloc)
+ {
+ static_assert(sizeof(_Tp) != 0, "must be a complete type");
+
+ // _M_alloc cannot free _M_objp, give it back to __other.
+ __other._M_objp = std::__exchange(_M_objp, nullptr);
+ // And create a new object that can be freed by _M_alloc.
+ _M_objp = _M_make_obj(std::move(*__other._M_objp));
+ }
+ }
+
+ template<typename _Up = _Tp>
+ requires (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
+ && (!is_same_v<remove_cvref_t<_Up>, indirect>)
+ && is_constructible_v<_Tp, _Up>
+ && is_default_constructible_v<_Alloc>
+ constexpr explicit
+ indirect(_Up&& __u)
+ : _M_objp(_M_make_obj(std::forward<_Up>(__u)))
+ { }
+
+ template<typename _Up = _Tp>
+ requires (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
+ && (!is_same_v<remove_cvref_t<_Up>, indirect>)
+ && is_constructible_v<_Tp, _Up>
+ constexpr explicit
+ indirect(allocator_arg_t, const _Alloc& __a, _Up&& __u)
+ : _M_alloc(__a), _M_objp(_M_make_obj(std::forward<_Up>(__u)))
+ { }
+
+ template<typename... _Us>
+ requires is_constructible_v<_Tp, _Us...>
+ && is_default_constructible_v<_Alloc>
+ constexpr explicit
+ indirect(in_place_t, _Us&&... __us)
+ : _M_objp(_M_make_obj(std::forward<_Us>(__us)...))
+ { }
+
+ template<typename... _Us>
+ requires is_constructible_v<_Tp, _Us...>
+ constexpr explicit
+ indirect(allocator_arg_t, const _Alloc& __a, in_place_t, _Us&&... __us)
+ : _M_alloc(__a),
+ _M_objp(_M_make_obj(std::forward<_Us>(__us)...))
+ { }
+
+ template<typename _Ip, typename... _Us>
+ requires is_constructible_v<_Tp, initializer_list<_Ip>&, _Us...>
+ && is_default_constructible_v<_Alloc>
+ constexpr explicit
+ indirect(in_place_t, initializer_list<_Ip> __il, _Us&&... __us)
+ : _M_objp(_M_make_obj(__il, std::forward<_Us>(__us)...))
+ { }
+
+ template<typename _Ip, typename... _Us>
+ requires is_constructible_v<_Tp, initializer_list<_Ip>&, _Us...>
+ constexpr explicit
+ indirect(allocator_arg_t, const _Alloc& __a,
+ in_place_t, initializer_list<_Ip> __il, _Us&&... __us)
+ : _M_alloc(__a),
+ _M_objp(_M_make_obj(__il, std::forward<_Us>(__us)...))
+ { }
+
+ constexpr ~indirect()
+ {
+ static_assert(sizeof(_Tp) != 0, "must be a complete type");
+ _M_reset(nullptr);
+ }
+
+ constexpr indirect&
+ operator=(const indirect& __other)
+ {
+ static_assert(is_copy_assignable_v<_Tp>);
+ static_assert(is_copy_constructible_v<_Tp>);
+
+ if (__builtin_addressof(__other) == this) [[unlikely]]
+ return *this;
+
+ constexpr bool __pocca
+ = _ATraits::propagate_on_container_copy_assignment::value;
+
+ pointer __ptr = nullptr;
+ if (__other._M_objp)
+ {
+ if (_ATraits::is_always_equal::value
+ || _M_alloc == __other._M_alloc)
+ {
+ if (_M_objp)
+ {
+ *_M_objp = __other.__get();
+ if constexpr (__pocca)
+ _M_alloc = __other._M_alloc;
+ return *this;
+ }
+ }
+ const indirect& __x = __pocca ? __other : *this;
+ __ptr = __x._M_make_obj(__other.__get());
+ }
+
+ _M_reset(__ptr);
+
+ if constexpr (__pocca)
+ _M_alloc = __other._M_alloc;
+
+ return *this;
+ }
+
+ constexpr indirect&
+ operator=(indirect&& __other)
+ noexcept(_ATraits::propagate_on_container_move_assignment::value
+ || _ATraits::is_always_equal::value)
+ {
+ // N5008 says is_copy_constructible_v<T> here, but that seems wrong.
+ // We only require move-constructible, and only for unequal allocators.
+
+ if (__builtin_addressof(__other) == this) [[unlikely]]
+ return *this;
+
+ constexpr bool __pocma
+ = _ATraits::propagate_on_container_move_assignment::value;
+
+ pointer __ptr = nullptr;
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4251. Move assignment for indirect unnecessarily requires copy construction
+ if constexpr (_ATraits::is_always_equal::value || __pocma)
+ __ptr = std::__exchange(__other._M_objp, nullptr);
+ else if (_M_alloc == __other._M_alloc)
+ __ptr = std::__exchange(__other._M_objp, nullptr);
+ else if (__other._M_objp)
+ {
+ static_assert(is_move_constructible_v<_Tp>);
+ __ptr = _M_make_obj(std::move(*__other._M_objp));
+ }
+
+ _M_reset(__ptr);
+
+ if constexpr (__pocma)
+ _M_alloc = std::move(__other._M_alloc);
+
+ return *this;
+ }
+
+ template<typename _Up = _Tp>
+ requires (!is_same_v<remove_cvref_t<_Up>, indirect>)
+ && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up>
+ constexpr indirect&
+ operator=(_Up&& __u)
+ {
+ if (_M_objp == nullptr)
+ _M_objp = _M_make_obj(std::forward<_Up>(__u));
+ else
+ *_M_objp = std::forward<_Up>(__u);
+
+ return *this;
+ }
+
+ template<typename _Self>
+ constexpr auto&&
+ operator*(this _Self&& __self) noexcept
+ {
+ // n.b. [allocator.requirements.general] p22 implies
+ // dereferencing const pointer is same as pointer
+ const indirect& __iself = (const indirect&)__self;
+ __glibcxx_assert(__iself._M_objp != nullptr);
+ return std::forward_like<_Self>(*__iself._M_objp);
+ }
+
+ constexpr const_pointer
+ operator->() const noexcept
+ {
+ // Do we want to enforce this? __glibcxx_assert(_M_objp != nullptr);
+ return _M_objp;
+ }
+
+ constexpr pointer
+ operator->() noexcept
+ {
+ // Do we want to enforce this? __glibcxx_assert(_M_objp != nullptr);
+ return _M_objp;
+ }
+
+ constexpr bool
+ valueless_after_move() const noexcept { return _M_objp == nullptr; }
+
+ constexpr allocator_type
+ get_allocator() const noexcept { return _M_alloc; }
+
+ constexpr void
+ swap(indirect& __other)
+ noexcept(_ATraits::propagate_on_container_swap::value
+ || _ATraits::is_always_equal::value)
+ {
+ using std::swap;
+ swap(_M_objp, __other._M_objp);
+ if constexpr (_ATraits::propagate_on_container_swap::value)
+ swap(_M_alloc, __other._M_alloc);
+ else if constexpr (!_ATraits::is_always_equal::value)
+ __glibcxx_assert(_M_alloc == __other._M_alloc);
+ }
+
+ friend constexpr void
+ swap(indirect& __lhs, indirect& __rhs)
+ noexcept(_ATraits::propagate_on_container_swap::value
+ || _ATraits::is_always_equal::value)
+ { __lhs.swap(__rhs); }
+
+ template<typename _Up, typename _Alloc2>
+ requires requires (const _Tp& __t, const _Up& __u) { __t == __u; }
+ friend constexpr bool
+ operator==(const indirect& __lhs, const indirect<_Up, _Alloc2>& __rhs)
+ noexcept(noexcept(*__lhs == *__rhs))
+ {
+ if (!__lhs._M_objp || !__rhs._M_objp)
+ return bool(__lhs._M_objp) == bool(__rhs._M_objp);
+ else
+ return __lhs.__get() == __rhs.__get();
+ }
+
+ template<typename _Up>
+ requires (!__is_indirect<_Up>) // See PR c++/99599
+ && requires (const _Tp& __t, const _Up& __u) { __t == __u; }
+ friend constexpr bool
+ operator==(const indirect& __lhs, const _Up& __rhs)
+ noexcept(noexcept(*__lhs == __rhs))
+ {
+ if (!__lhs._M_objp)
+ return false;
+ else
+ return __lhs.__get() == __rhs;
+ }
+
+ template<typename _Up, typename _Alloc2>
+ friend constexpr __detail::__synth3way_t<_Tp, _Up>
+ operator<=>(const indirect& __lhs, const indirect<_Up, _Alloc2>& __rhs)
+ noexcept(noexcept(__detail::__synth3way(*__lhs, *__rhs)))
+ {
+ if (!__lhs._M_objp || !__rhs._M_objp)
+ return bool(__lhs._M_objp) <=> bool(__rhs._M_objp);
+ else
+ return __detail::__synth3way(__lhs.__get(), __rhs.__get());
+ }
+
+ template<typename _Up>
+ requires (!__is_indirect<_Up>) // See PR c++/99599
+ friend constexpr __detail::__synth3way_t<_Tp, _Up>
+ operator<=>(const indirect& __lhs, const _Up& __rhs)
+ noexcept(noexcept(__detail::__synth3way(*__lhs, __rhs)))
+ {
+ if (!__lhs._M_objp)
+ return strong_ordering::less;
+ else
+ return __detail::__synth3way(__lhs.__get(), __rhs);
+ }
+
+ private:
+ template<typename, typename> friend class indirect;
+
+ constexpr void
+ _M_reset(pointer __ptr) noexcept
+ {
+ if (_M_objp)
+ {
+ _ATraits::destroy(_M_alloc, std::to_address(_M_objp));
+ _ATraits::deallocate(_M_alloc, _M_objp, 1);
+ }
+ _M_objp = __ptr;
+ }
+
+ template<typename... _Args>
+ constexpr pointer
+ _M_make_obj(_Args&&... __args) const
+ {
+ _Scoped_allocation __sa(_M_alloc, in_place,
+ std::forward<_Args>(__args)...);
+ return __sa.release();
+ }
+
+ // Enforces is_constructible check and then calls _M_make_obj.
+ template<typename... _Args>
+ [[__gnu__::__always_inline__]]
+ constexpr pointer
+ _M_make_obj_chk(_Args&&... __args) const
+ {
+ static_assert(is_constructible_v<_Tp, _Args...>);
+ return _M_make_obj(std::forward<_Args>(__args)...);
+ }
+
+ // Always-const accessor that avoids ADL for operator*.
+ // This can be preferable to using *_M_objp because that might give _Tp&.
+ // This can be preferable to using **this because that does ADL.
+ [[__gnu__::__always_inline__]]
+ constexpr const _Tp&
+ __get() const noexcept
+ { return *_M_objp; }
+
+ [[no_unique_address]] _Alloc _M_alloc = _Alloc();
+ pointer _M_objp; // Pointer to the owned object.
+ };
+
+ template<typename _Value>
+ indirect(_Value) -> indirect<_Value>;
+
+ template<typename _Alloc, typename _Value>
+ indirect(allocator_arg_t, _Alloc, _Value)
+ -> indirect<_Value, __alloc_rebind<_Alloc, _Value>>;
+
+ // [indirect.hash], hash support
+ template<typename _Tp, typename _Alloc>
+ requires is_default_constructible_v<hash<_Tp>>
+ struct hash<indirect<_Tp, _Alloc>>
+ {
+ constexpr size_t
+ operator()(const indirect<_Tp, _Alloc>& __t) const
+ noexcept(noexcept(hash<_Tp>{}(*__t)))
+ {
+ // We pick an arbitrary hash for valueless indirect objects
+ // which hopefully usual values of _Tp won't typically hash to.
+ if (__t.valueless_after_move())
+ return -4444zu;
+ return hash<_Tp>{}(*__t);
+ }
+ };
+
+ template<typename _Tp, typename _Alloc>
+ struct __is_fast_hash<hash<indirect<_Tp, _Alloc>>>
+ : __is_fast_hash<hash<_Tp>>
+ { };
+#endif // __glibcxx_indirect
+
+#if __glibcxx_polymorphic // C++26 && HOSTED
+ template<typename _Tp, typename _Alloc = allocator<_Tp>>
+ class polymorphic;
+
+ namespace pmr
+ {
+ template<typename _Tp>
+ using polymorphic = polymorphic<_Tp, polymorphic_allocator<_Tp>>;
+ }
+
+ // [polymorphic], class template polymorphic
+ template<typename _Tp, typename _Alloc>
+ class polymorphic
+ {
+ static_assert(is_object_v<_Tp>);
+ static_assert(!is_array_v<_Tp>);
+ static_assert(!is_same_v<_Tp, in_place_t>);
+ static_assert(!__is_in_place_type_v<_Tp>);
+ static_assert(!is_const_v<_Tp> && !is_volatile_v<_Tp>);
+
+ using _ATraits = allocator_traits<_Alloc>;
+ static_assert(is_same_v<_Tp, typename _ATraits::value_type>);
+
+ // The owned object is embedded within a control block which knows the
+ // dynamic type and manages cloning and destroying the owned object.
+ struct _Obj
+ {
+ typename _ATraits::pointer _M_objp{}; // pointer to the owned object.
+
+ // A pointer to this type, e.g. _Obj*
+ using pointer
+ = typename _ATraits::template rebind_traits<_Obj>::pointer;
+
+ enum class _Op { _Dispose = 1, _Copy = 2, _Move = 3 };
+
+ constexpr virtual pointer
+ _M_manage(const _Alloc&, _Op, void* = nullptr) = 0;
+ };
+
+ template<typename _Up>
+ struct _Obj_impl : _Obj
+ {
+ using _MyTraits
+ = typename _ATraits::template rebind_traits<_Obj_impl>;
+
+ using _Op = _Obj::_Op;
+
+ union _Uninitialized {
+ constexpr _Uninitialized() { }
+ constexpr ~_Uninitialized() { }
+ _Up _M_objp;
+ };
+ _Uninitialized _M_u;
+
+ template<typename... _Args>
+ constexpr
+ _Obj_impl(typename _MyTraits::allocator_type& __a,
+ _Args&&... __args)
+ {
+ using _PtrTr = pointer_traits<typename _ATraits::pointer>;
+ _MyTraits::construct(__a, __builtin_addressof(_M_u._M_objp),
+ std::forward<_Args>(__args)...);
+ this->_M_objp = _PtrTr::pointer_to(_M_u._M_objp);
+ }
+
+ constexpr virtual typename _Obj::pointer
+ _M_manage(const _Alloc& __a, _Op __op, void*) override
+ {
+
+ switch (__op)
+ {
+ case _Op::_Move:
+ return _S_make_obj<_Up>(__a, std::move(_M_u._M_objp));
+ case _Op::_Copy:
+ return _S_make_obj<_Up>(__a,
+ const_cast<const _Up&>(_M_u._M_objp));
+ case _Op::_Dispose:
+ {
+ using _PtrTr = pointer_traits<typename _MyTraits::pointer>;
+ typename _MyTraits::allocator_type __a2(__a);
+ _MyTraits::destroy(__a2, std::__addressof(_M_u._M_objp));
+ _MyTraits::deallocate(__a2, _PtrTr::pointer_to(*this), 1);
+ return nullptr;
+ }
+ }
+ __builtin_unreachable();
+ }
+ };
+
+ // TODO: the standard permits a small-object optimization where the
+ // owned object is nested within the std::polymorphic not on the heap.
+
+ public:
+
+ using value_type = _Tp;
+ using allocator_type = _Alloc;
+ using pointer = typename allocator_traits<_Alloc>::pointer;
+ using const_pointer = typename allocator_traits<_Alloc>::const_pointer;
+
+ constexpr explicit
+ polymorphic() requires is_default_constructible_v<_Alloc>
+ : polymorphic(in_place_type<_Tp>)
+ { }
+
+ constexpr explicit
+ polymorphic(allocator_arg_t, const _Alloc& __a)
+ : polymorphic(allocator_arg, __a, in_place_type<_Tp>)
+ { }
+
+ constexpr
+ polymorphic(const polymorphic& __other)
+ : polymorphic(allocator_arg,
+ _ATraits::select_on_container_copy_construction(
+ __other._M_alloc),
+ __other)
+ { }
+
+ constexpr
+ polymorphic(allocator_arg_t, const _Alloc& __a,
+ const polymorphic& __other)
+ : _M_alloc(__a)
+ {
+ if (__other._M_objp)
+ _M_objp = __other._M_objp->_M_manage(__a, _Obj::_Op::_Copy);
+ else
+ _M_objp = nullptr;
+ }
+
+ constexpr
+ polymorphic(polymorphic&& __other) noexcept
+ : _M_alloc(std::move(__other._M_alloc)),
+ _M_objp(std::__exchange(__other._M_objp, nullptr))
+ { }
+
+ constexpr
+ polymorphic(allocator_arg_t, const _Alloc& __a, polymorphic&& __other)
+ noexcept(_ATraits::is_always_equal::value)
+ : _M_alloc(__a),
+ _M_objp(std::__exchange(__other._M_objp, nullptr))
+ {
+ if constexpr (!_ATraits::is_always_equal::value)
+ if (_M_objp && _M_alloc != __other._M_alloc)
+ {
+ // _M_alloc cannot free _M_objp, give it back to __other.
+ __other._M_objp = std::__exchange(_M_objp, nullptr);
+ // And create a new object that can be freed by _M_alloc.
+ _M_objp = __other._M_objp->_M_manage(__a, _Obj::_Op::_Move);
+ }
+ }
+
+ template<typename _Up = _Tp, typename _UUp = remove_cvref_t<_Up>>
+ requires (!is_same_v<_UUp, polymorphic>)
+ && (!__is_in_place_type_v<_UUp>)
+ && derived_from<_UUp, _Tp>
+ && is_constructible_v<_UUp, _Up>
+ && is_copy_constructible_v<_UUp>
+ && is_default_constructible_v<_Alloc>
+ constexpr explicit
+ polymorphic(_Up&& __u)
+ : _M_objp(_M_make_obj<_UUp>(std::forward<_Up>(__u)))
+ { }
+
+ template<typename _Up = _Tp, typename _UUp = remove_cvref_t<_Up>>
+ requires (!is_same_v<_UUp, polymorphic>)
+ && (!__is_in_place_type_v<_UUp>)
+ && derived_from<_UUp, _Tp>
+ && is_constructible_v<_UUp, _Up>
+ && is_copy_constructible_v<_UUp>
+ constexpr explicit
+ polymorphic(allocator_arg_t, const _Alloc& __a, _Up&& __u)
+ : _M_alloc(__a), _M_objp(_M_make_obj<_UUp>(std::forward<_Up>(__u)))
+ { }
+
+ template<typename _Up, typename... _Ts>
+ requires is_same_v<remove_cvref_t<_Up>, _Up>
+ && derived_from<_Up, _Tp>
+ && is_constructible_v<_Up, _Ts...>
+ && is_copy_constructible_v<_Up>
+ && is_default_constructible_v<_Alloc>
+ constexpr explicit
+ polymorphic(in_place_type_t<_Up> __t, _Ts&&... __ts)
+ : _M_objp(_M_make_obj<_Up>(std::forward<_Ts>(__ts)...))
+ { }
+
+ template<typename _Up, typename... _Ts>
+ requires is_same_v<remove_cvref_t<_Up>, _Up>
+ && derived_from<_Up, _Tp>
+ && is_constructible_v<_Up, _Ts...>
+ && is_copy_constructible_v<_Up>
+ constexpr explicit
+ polymorphic(allocator_arg_t, const _Alloc& __a,
+ in_place_type_t<_Up>, _Ts&&... __ts)
+ : _M_alloc(__a),
+ _M_objp(_M_make_obj<_Up>(std::forward<_Ts>(__ts)...))
+ { }
+
+ template<typename _Up, typename _Ip, typename... _Us>
+ requires is_same_v<remove_cvref_t<_Up>, _Up>
+ && derived_from<_Up, _Tp>
+ && is_constructible_v<_Up, initializer_list<_Ip>&, _Us...>
+ && is_copy_constructible_v<_Up>
+ && is_default_constructible_v<_Alloc>
+ constexpr explicit
+ polymorphic(in_place_type_t<_Up>, initializer_list<_Ip> __il,
+ _Us&&... __us)
+ : _M_objp(_M_make_obj<_Up>(__il, std::forward<_Us>(__us)...))
+ { }
+
+ template<typename _Up, typename _Ip, typename... _Us>
+ requires is_same_v<remove_cvref_t<_Up>, _Up>
+ && derived_from<_Up, _Tp>
+ && is_constructible_v<_Up, initializer_list<_Ip>&, _Us...>
+ && is_copy_constructible_v<_Up>
+ constexpr explicit
+ polymorphic(allocator_arg_t, const _Alloc& __a,
+ in_place_type_t<_Up>, initializer_list<_Ip> __il,
+ _Us&&... __us)
+ : _M_alloc(__a),
+ _M_objp(_M_make_obj<_Up>(__il, std::forward<_Us>(__us)...))
+ { }
+
+ constexpr ~polymorphic()
+ {
+ static_assert(sizeof(_Tp) != 0, "must be a complete type");
+ _M_reset(nullptr);
+ }
+
+ constexpr polymorphic&
+ operator=(const polymorphic& __other)
+ {
+ static_assert(sizeof(_Tp) != 0, "must be a complete type");
+
+ if (__builtin_addressof(__other) == this) [[unlikely]]
+ return *this;
+
+ constexpr bool __pocca
+ = _ATraits::propagate_on_container_copy_assignment::value;
+
+ typename _Obj::pointer __ptr = nullptr;
+ if (__other._M_objp)
+ {
+ auto& __a = __pocca ? __other._M_alloc : _M_alloc;
+ __ptr = __other._M_objp->_M_manage(__a, _Obj::_Op::_Copy);
+ }
+
+ _M_reset(__ptr);
+
+ if constexpr (__pocca)
+ _M_alloc = __other._M_alloc;
+
+ return *this;
+ }
+
+ constexpr polymorphic&
+ operator=(polymorphic&& __other)
+ noexcept(_ATraits::propagate_on_container_move_assignment::value
+ || _ATraits::is_always_equal::value)
+ {
+ if (__builtin_addressof(__other) == this) [[unlikely]]
+ return *this;
+
+ constexpr bool __pocma
+ = _ATraits::propagate_on_container_move_assignment::value;
+
+ typename _Obj::pointer __ptr = nullptr;
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4251. Move assignment for indirect unnecessarily requires copy construction
+ if constexpr (_ATraits::is_always_equal::value || __pocma)
+ __ptr = std::__exchange(__other._M_objp, nullptr);
+ else if (_M_alloc == __other._M_alloc)
+ __ptr = std::__exchange(__other._M_objp, nullptr);
+ else if (__other._M_objp)
+ {
+ static_assert(sizeof(_Tp) != 0, "must be a complete type");
+ __ptr = __other._M_objp->_M_manage(_M_alloc, _Obj::_Op::_Move);
+ }
+
+ _M_reset(__ptr);
+
+ if constexpr (__pocma)
+ _M_alloc = std::move(__other._M_alloc);
+
+ return *this;
+ }
+
+ constexpr const _Tp&
+ operator*() const noexcept
+ {
+ __glibcxx_assert(_M_objp != nullptr);
+ return *_M_objp->_M_objp;
+ }
+
+ constexpr _Tp&
+ operator*() noexcept
+ {
+ __glibcxx_assert(_M_objp != nullptr);
+ return *_M_objp->_M_objp;
+ }
+
+ constexpr const_pointer
+ operator->() const noexcept
+ {
+ __glibcxx_assert(_M_objp != nullptr);
+ return _M_objp ? _M_objp->_M_objp : const_pointer{};
+ }
+
+ constexpr pointer
+ operator->() noexcept
+ {
+ __glibcxx_assert(_M_objp != nullptr);
+ return _M_objp ? _M_objp->_M_objp : pointer{};
+ }
+
+ constexpr bool
+ valueless_after_move() const noexcept { return _M_objp == nullptr; }
+
+ constexpr allocator_type
+ get_allocator() const noexcept { return _M_alloc; }
+
+ constexpr void
+ swap(polymorphic& __other)
+ noexcept(_ATraits::propagate_on_container_swap::value
+ || _ATraits::is_always_equal::value)
+ {
+ using std::swap;
+ swap(_M_objp, __other._M_objp);
+ if constexpr (_ATraits::propagate_on_container_swap::value)
+ swap(_M_alloc, __other._M_alloc);
+ else if constexpr (!_ATraits::is_always_equal::value)
+ __glibcxx_assert(_M_alloc == __other._M_alloc);
+ }
+
+ friend constexpr void
+ swap(polymorphic& __lhs, polymorphic& __rhs)
+ noexcept(_ATraits::propagate_on_container_swap::value
+ || _ATraits::is_always_equal::value)
+ { __lhs.swap(__rhs); }
+
+ private:
+ template<typename _Up, typename... _Args>
+ static constexpr typename _Obj::pointer
+ _S_make_obj(const _Alloc& __a, _Args&&... __args)
+ {
+ __alloc_rebind<_Alloc, _Obj_impl<_Up>> __objalloc(__a);
+ _Scoped_allocation __sa(__objalloc, in_place, __objalloc,
+ std::forward<_Args>(__args)...);
+ auto __obj = __sa.release();
+ // FIXME: We need to downcast from _Obj_impl<U>* to _Obj* but the
+ // the pointer_traits usage breaks in constexpr. PR c++/110714
+ if constexpr (is_pointer_v<typename _Obj::pointer>)
+ return __obj;
+ else
+ return pointer_traits<typename _Obj::pointer>::pointer_to(*__obj);
+ }
+
+ template<typename _Up, typename... _Args>
+ constexpr typename _Obj::pointer
+ _M_make_obj(_Args&&... __args) const
+ { return _S_make_obj<_Up>(_M_alloc, std::forward<_Args>(__args)...); }
+
+ constexpr void
+ _M_reset(typename _Obj::pointer __ptr) noexcept
+ {
+ if (_M_objp)
+ _M_objp->_M_manage(_M_alloc, _Obj::_Op::_Dispose);
+ _M_objp = __ptr;
+ }
+
+ [[no_unique_address]] _Alloc _M_alloc = _Alloc();
+ typename _Obj::pointer _M_objp;
+ };
+#endif // __glibcxx_polymorphic
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+#endif // C++26 __glibcxx_indirect || __glibcxx_polymorphic
+
+#endif // _GLIBCXX_INDIRECT_H
diff --git a/libstdc++-v3/include/bits/intcmp.h b/libstdc++-v3/include/bits/intcmp.h
new file mode 100644
index 0000000..bb9c7f2
--- /dev/null
+++ b/libstdc++-v3/include/bits/intcmp.h
@@ -0,0 +1,120 @@
+// Integer comparison functions -*- C++ -*-
+
+// Copyright (C) 2020-2025 Free Software Foundation, Inc.
+//
+// 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 bits/intcmp.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{utility}
+ */
+
+#ifndef _GLIBCXX_INTCMP_H
+#define _GLIBCXX_INTCMP_H 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <bits/version.h>
+
+#ifdef __glibcxx_integer_comparison_functions // C++ >= 20
+
+#include <type_traits>
+#include <ext/numeric_traits.h> // __int_traits
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_equal(_Tp __t, _Up __u) noexcept
+ {
+ static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
+ static_assert(__is_signed_or_unsigned_integer<_Up>::value);
+
+ if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
+ return __t == __u;
+ else if constexpr (is_signed_v<_Tp>)
+ return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u;
+ else
+ return __u >= 0 && __t == make_unsigned_t<_Up>(__u);
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_not_equal(_Tp __t, _Up __u) noexcept
+ { return !std::cmp_equal(__t, __u); }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_less(_Tp __t, _Up __u) noexcept
+ {
+ static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
+ static_assert(__is_signed_or_unsigned_integer<_Up>::value);
+
+ if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
+ return __t < __u;
+ else if constexpr (is_signed_v<_Tp>)
+ return __t < 0 || make_unsigned_t<_Tp>(__t) < __u;
+ else
+ return __u >= 0 && __t < make_unsigned_t<_Up>(__u);
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_greater(_Tp __t, _Up __u) noexcept
+ { return std::cmp_less(__u, __t); }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_less_equal(_Tp __t, _Up __u) noexcept
+ { return !std::cmp_less(__u, __t); }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_greater_equal(_Tp __t, _Up __u) noexcept
+ { return !std::cmp_less(__t, __u); }
+
+ template<typename _Res, typename _Tp>
+ constexpr bool
+ in_range(_Tp __t) noexcept
+ {
+ static_assert(__is_signed_or_unsigned_integer<_Res>::value);
+ static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
+ using __gnu_cxx::__int_traits;
+
+ if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>)
+ return __int_traits<_Res>::__min <= __t
+ && __t <= __int_traits<_Res>::__max;
+ else if constexpr (is_signed_v<_Tp>)
+ return __t >= 0
+ && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max;
+ else
+ return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max);
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif // __glibcxx_integer_comparison_functions
+#endif // _GLIBCXX_INTCMP_H
diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h
index b94b2cd..adc2982 100644
--- a/libstdc++-v3/include/bits/ios_base.h
+++ b/libstdc++-v3/include/bits/ios_base.h
@@ -56,7 +56,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// as permitted (but not required) in the standard, in order to provide
// better type safety in iostream calls. A side effect is that in C++98
// expressions involving them are not compile-time constants.
- enum _Ios_Fmtflags
+ enum __attribute__((__flag_enum__)) _Ios_Fmtflags
{
_S_boolalpha = 1L << 0,
_S_dec = 1L << 1,
@@ -76,9 +76,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_adjustfield = _S_left | _S_right | _S_internal,
_S_basefield = _S_dec | _S_oct | _S_hex,
_S_floatfield = _S_scientific | _S_fixed,
- _S_ios_fmtflags_end = 1L << 16,
- _S_ios_fmtflags_max = __INT_MAX__,
- _S_ios_fmtflags_min = ~__INT_MAX__
+ _S_ios_fmtflags_end __attribute__((__unused__)) = 1L << 16,
+ _S_ios_fmtflags_max __attribute__((__unused__)) = __INT_MAX__,
+ _S_ios_fmtflags_min __attribute__((__unused__)) = ~__INT_MAX__
};
_GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
@@ -176,15 +176,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __a = __a ^ __b; }
- enum _Ios_Iostate
+ enum __attribute__((__flag_enum__)) _Ios_Iostate
{
_S_goodbit = 0,
_S_badbit = 1L << 0,
_S_eofbit = 1L << 1,
_S_failbit = 1L << 2,
- _S_ios_iostate_end = 1L << 16,
- _S_ios_iostate_max = __INT_MAX__,
- _S_ios_iostate_min = ~__INT_MAX__
+ _S_ios_iostate_end __attribute__((__unused__)) = 1L << 16,
+ _S_ios_iostate_max __attribute__((__unused__)) = __INT_MAX__,
+ _S_ios_iostate_min __attribute__((__unused__)) = ~__INT_MAX__
};
_GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
@@ -228,7 +228,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_beg = 0,
_S_cur = _GLIBCXX_STDIO_SEEK_CUR,
_S_end = _GLIBCXX_STDIO_SEEK_END,
- _S_ios_seekdir_end = 1L << 16
+ _S_ios_seekdir_end __attribute__((__unused__)) = 1L << 16
};
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index e36556d..40ac808 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -39,9 +39,6 @@
#include <bits/ptr_traits.h> // to_address
#include <bits/ranges_cmp.h> // identity, ranges::less
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpedantic" // __int128
-
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -148,7 +145,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
template<typename _Tp>
- static constexpr bool
+ static consteval bool
_S_noexcept()
{
if constexpr (__adl_imove<_Tp>)
@@ -214,17 +211,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
= make_signed_t<decltype(std::declval<_Tp>() - std::declval<_Tp>())>;
};
-#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
- // __int128 is incrementable even if !integral<__int128>
- template<>
- struct incrementable_traits<__int128>
- { using difference_type = __int128; };
-
- template<>
- struct incrementable_traits<unsigned __int128>
- { using difference_type = __int128; };
-#endif
-
namespace __detail
{
// An iterator such that iterator_traits<_Iter> names a specialization
@@ -611,24 +597,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class __max_diff_type;
class __max_size_type;
- __extension__
- template<typename _Tp>
- concept __is_signed_int128
-#if __SIZEOF_INT128__
- = same_as<_Tp, __int128>;
-#else
- = false;
-#endif
-
- __extension__
- template<typename _Tp>
- concept __is_unsigned_int128
-#if __SIZEOF_INT128__
- = same_as<_Tp, unsigned __int128>;
-#else
- = false;
-#endif
-
template<typename _Tp>
concept __cv_bool = same_as<const volatile _Tp, const volatile bool>;
@@ -636,16 +604,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
concept __integral_nonbool = integral<_Tp> && !__cv_bool<_Tp>;
template<typename _Tp>
- concept __is_int128 = __is_signed_int128<_Tp> || __is_unsigned_int128<_Tp>;
-
- template<typename _Tp>
concept __is_integer_like = __integral_nonbool<_Tp>
- || __is_int128<_Tp>
|| same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>;
template<typename _Tp>
concept __is_signed_integer_like = signed_integral<_Tp>
- || __is_signed_int128<_Tp>
|| same_as<_Tp, __max_diff_type>;
} // namespace ranges::__detail
@@ -829,11 +792,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using __projected_Proj = _Proj;
};
};
-
- // Optimize the common case of the projection being std::identity.
- template<typename _Iter>
- struct __projected<_Iter, identity>
- { using __type = _Iter; };
} // namespace __detail
/// [projected], projected
@@ -923,7 +881,7 @@ namespace ranges
{
private:
template<typename _Tp, typename _Up>
- static constexpr bool
+ static consteval bool
_S_noexcept()
{
if constexpr (__adl_iswap<_Tp, _Up>)
@@ -1027,19 +985,10 @@ namespace ranges
{
using std::__detail::__class_or_enum;
- struct _Decay_copy final
- {
- template<typename _Tp>
- constexpr decay_t<_Tp>
- operator()(_Tp&& __t) const
- noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>)
- { return std::forward<_Tp>(__t); }
- } inline constexpr __decay_copy{};
-
template<typename _Tp>
concept __member_begin = requires(_Tp& __t)
{
- { __decay_copy(__t.begin()) } -> input_or_output_iterator;
+ { _GLIBCXX_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
};
// Poison pill so that unqualified lookup doesn't find std::begin.
@@ -1049,7 +998,7 @@ namespace ranges
concept __adl_begin = __class_or_enum<remove_reference_t<_Tp>>
&& requires(_Tp& __t)
{
- { __decay_copy(begin(__t)) } -> input_or_output_iterator;
+ { _GLIBCXX_AUTO_CAST(begin(__t)) } -> input_or_output_iterator;
};
// Simplified version of std::ranges::begin that only supports lvalues,
@@ -1080,6 +1029,5 @@ namespace ranges
#endif // C++20 library concepts
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
-#pragma GCC diagnostic pop
#endif // C++20
#endif // _ITERATOR_CONCEPTS_H
diff --git a/libstdc++-v3/include/bits/locale_conv.h b/libstdc++-v3/include/bits/locale_conv.h
index 076e14f..b08795d 100644
--- a/libstdc++-v3/include/bits/locale_conv.h
+++ b/libstdc++-v3/include/bits/locale_conv.h
@@ -85,16 +85,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return false;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
// The codecvt facet will only return noconv when the types are
// the same, so avoid instantiating basic_string::assign otherwise
- if _GLIBCXX17_CONSTEXPR (is_same<typename _Codecvt::intern_type,
- typename _Codecvt::extern_type>())
+ if constexpr (is_same<typename _Codecvt::intern_type,
+ typename _Codecvt::extern_type>::value)
if (__result == codecvt_base::noconv)
{
__outstr.assign(__first, __last);
__count = __last - __first;
return true;
}
+#pragma GCC diagnostic pop
__outstr.resize(__outchars);
__count = __next - __first;
diff --git a/libstdc++-v3/include/bits/max_size_type.h b/libstdc++-v3/include/bits/max_size_type.h
index 5bec0b5..537acee 100644
--- a/libstdc++-v3/include/bits/max_size_type.h
+++ b/libstdc++-v3/include/bits/max_size_type.h
@@ -36,16 +36,16 @@
#if __cplusplus > 201703L && __cpp_lib_concepts
#include <ext/numeric_traits.h>
+#include <bit> // __bit_width
#include <numbers>
+#include <limits> // __glibcxx_integral_traps
// This header implements unsigned and signed integer-class types (as per
// [iterator.concept.winc]) that are one bit wider than the widest supported
// integer type.
//
-// The set of integer types we consider includes __int128 and unsigned __int128
-// (when they exist), even though they are really integer types only in GNU
-// mode. This is to obtain a consistent ABI for these integer-class types
-// across strict mode and GNU mode.
+// The set of integer types we consider includes the extended integer types
+// __int128 and unsigned __int128 (when they exist).
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -63,7 +63,7 @@ namespace ranges
public:
__max_size_type() = default;
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
constexpr
__max_size_type(_Tp __i) noexcept
: _M_val(__i), _M_msb(__i < 0)
@@ -72,7 +72,7 @@ namespace ranges
constexpr explicit
__max_size_type(const __max_diff_type& __d) noexcept;
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
constexpr explicit
operator _Tp() const noexcept
{ return _M_val; }
@@ -258,52 +258,52 @@ namespace ranges
return *this;
}
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator+=(_Tp& __a, const __max_size_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a + __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator-=(_Tp& __a, const __max_size_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a - __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator*=(_Tp& __a, const __max_size_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a * __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator/=(_Tp& __a, const __max_size_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a / __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator%=(_Tp& __a, const __max_size_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a % __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator&=(_Tp& __a, const __max_size_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a & __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator|=(_Tp& __a, const __max_size_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a | __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator^=(_Tp& __a, const __max_size_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a ^ __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator<<=(_Tp& __a, const __max_size_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a << __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator>>=(_Tp& __a, const __max_size_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a >> __b)); }
@@ -425,10 +425,11 @@ namespace ranges
using __rep = unsigned long long;
#endif
static constexpr size_t _S_rep_bits = sizeof(__rep) * __CHAR_BIT__;
- private:
+
__rep _M_val = 0;
unsigned _M_msb:1 = 0;
+ private:
constexpr explicit
__max_size_type(__rep __val, int __msb) noexcept
: _M_val(__val), _M_msb(__msb)
@@ -444,7 +445,7 @@ namespace ranges
public:
__max_diff_type() = default;
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
constexpr
__max_diff_type(_Tp __i) noexcept
: _M_rep(__i)
@@ -455,7 +456,7 @@ namespace ranges
: _M_rep(__d)
{ }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
constexpr explicit
operator _Tp() const noexcept
{ return static_cast<_Tp>(_M_rep); }
@@ -588,52 +589,52 @@ namespace ranges
return *this;
}
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator+=(_Tp& __a, const __max_diff_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a + __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator-=(_Tp& __a, const __max_diff_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a - __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator*=(_Tp& __a, const __max_diff_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a * __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator/=(_Tp& __a, const __max_diff_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a / __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator%=(_Tp& __a, const __max_diff_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a % __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator&=(_Tp& __a, const __max_diff_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a & __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator|=(_Tp& __a, const __max_diff_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a | __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator^=(_Tp& __a, const __max_diff_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a ^ __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator<<=(_Tp& __a, const __max_diff_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a << __b)); }
- template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp>
+ template<typename _Tp> requires integral<_Tp>
friend constexpr _Tp&
operator>>=(_Tp& __a, const __max_diff_type& __b) noexcept
{ return (__a = static_cast<_Tp>(__a >> __b)); }
@@ -752,7 +753,6 @@ namespace ranges
{ return !(__l < __r); }
#endif
- private:
__max_size_type _M_rep = 0;
friend class __max_size_type;
@@ -774,10 +774,27 @@ namespace ranges
static constexpr bool is_signed = false;
static constexpr bool is_integer = true;
static constexpr bool is_exact = true;
+ static constexpr bool is_bounded = true;
+ static constexpr bool is_modulo = true;
+ static constexpr bool traps = __glibcxx_integral_traps;
+ static constexpr int radix = 2;
static constexpr int digits
= __gnu_cxx::__int_traits<_Sp::__rep>::__digits + 1;
static constexpr int digits10
= static_cast<int>(digits * numbers::ln2 / numbers::ln10);
+ static constexpr int max_digits10 = 0;
+ static constexpr int min_exponent = 0;
+ static constexpr int min_exponent10 = 0;
+ static constexpr int max_exponent = 0;
+ static constexpr int max_exponent10 = 0;
+ static constexpr bool is_iec559 = false;
+ static constexpr bool has_infinity = false;
+ static constexpr bool has_quiet_NaN = false;
+ static constexpr bool has_signaling_NaN = false;
+ static constexpr bool has_denorm_loss = false;
+ static constexpr bool tinyness_before = false;
+ static constexpr float_denorm_style has_denorm = denorm_absent;
+ static constexpr float_round_style round_style = round_toward_zero;
static constexpr _Sp
min() noexcept
@@ -790,6 +807,30 @@ namespace ranges
static constexpr _Sp
lowest() noexcept
{ return min(); }
+
+ static constexpr _Sp
+ denorm_min() noexcept
+ { return 0; }
+
+ static constexpr _Sp
+ epsilon() noexcept
+ { return 0; }
+
+ static constexpr _Sp
+ round_error() noexcept
+ { return 0; }
+
+ static constexpr _Sp
+ infinity() noexcept
+ { return 0; }
+
+ static constexpr _Sp
+ quiet_NaN() noexcept
+ { return 0; }
+
+ static constexpr _Sp
+ signaling_NaN() noexcept
+ { return 0; }
};
template<>
@@ -801,9 +842,26 @@ namespace ranges
static constexpr bool is_signed = true;
static constexpr bool is_integer = true;
static constexpr bool is_exact = true;
+ static constexpr bool is_bounded = true;
+ static constexpr bool is_modulo = false;
+ static constexpr bool traps = __glibcxx_integral_traps;
+ static constexpr int radix = 2;
static constexpr int digits = numeric_limits<_Sp>::digits - 1;
static constexpr int digits10
= static_cast<int>(digits * numbers::ln2 / numbers::ln10);
+ static constexpr int max_digits10 = 0;
+ static constexpr int min_exponent = 0;
+ static constexpr int min_exponent10 = 0;
+ static constexpr int max_exponent = 0;
+ static constexpr int max_exponent10 = 0;
+ static constexpr bool is_iec559 = false;
+ static constexpr bool has_infinity = false;
+ static constexpr bool has_quiet_NaN = false;
+ static constexpr bool has_signaling_NaN = false;
+ static constexpr bool has_denorm_loss = false;
+ static constexpr bool tinyness_before = false;
+ static constexpr float_denorm_style has_denorm = denorm_absent;
+ static constexpr float_round_style round_style = round_toward_zero;
static constexpr _Dp
min() noexcept
@@ -816,8 +874,42 @@ namespace ranges
static constexpr _Dp
lowest() noexcept
{ return min(); }
+
+ static constexpr _Dp
+ denorm_min() noexcept
+ { return 0; }
+
+ static constexpr _Dp
+ epsilon() noexcept
+ { return 0; }
+
+ static constexpr _Dp
+ round_error() noexcept
+ { return 0; }
+
+ static constexpr _Dp
+ infinity() noexcept
+ { return 0; }
+
+ static constexpr _Dp
+ quiet_NaN() noexcept
+ { return 0; }
+
+ static constexpr _Dp
+ signaling_NaN() noexcept
+ { return 0; }
};
+ template<>
+ inline constexpr int
+ __bit_width(ranges::__detail::__max_size_type __x) noexcept
+ {
+ if (__x._M_msb)
+ return numeric_limits<ranges::__detail::__max_size_type>::digits;
+ else
+ return std::__bit_width(__x._M_val);
+ }
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/bits/mofunc_impl.h b/libstdc++-v3/include/bits/mofunc_impl.h
index 318a55e..468e685 100644
--- a/libstdc++-v3/include/bits/mofunc_impl.h
+++ b/libstdc++-v3/include/bits/mofunc_impl.h
@@ -62,8 +62,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Res, typename... _ArgTypes, bool _Noex>
class move_only_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
_GLIBCXX_MOF_REF noexcept(_Noex)>
- : _Mofunc_base
+ : __polyfunc::_Mo_base
{
+ static_assert(
+ (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...),
+ "each parameter type must be a complete class");
+
+ using _Base = __polyfunc::_Mo_base;
+ using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
+ using _Signature = _Invoker::_Signature;
+
template<typename _Tp>
using __callable
= __conditional_t<_Noex,
@@ -87,7 +95,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Moves the target object, leaving the source empty.
move_only_function(move_only_function&& __x) noexcept
- : _Mofunc_base(static_cast<_Mofunc_base&&>(__x)),
+ : _Base(static_cast<_Base&&>(__x)),
_M_invoke(std::__exchange(__x._M_invoke, nullptr))
{ }
@@ -97,15 +105,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt>
move_only_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>())
{
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4255. move_only_function constructor should recognize empty
+ // copyable_functions
if constexpr (is_function_v<remove_pointer_t<_Vt>>
|| is_member_pointer_v<_Vt>
- || __is_move_only_function_v<_Vt>)
+ || __is_polymorphic_function_v<_Vt>)
{
if (__f == nullptr)
return;
}
- _M_init<_Vt>(std::forward<_Fn>(__f));
- _M_invoke = &_S_invoke<_Vt>;
+
+ if constexpr (__is_polymorphic_function_v<_Vt>
+ && __polyfunc::__is_invoker_convertible<_Vt, move_only_function>())
+ {
+ // Handle cases where _Fn is const reference to copyable_function,
+ // by firstly creating temporary and moving from it.
+ _Vt __tmp(std::forward<_Fn>(__f));
+ _M_move(__polyfunc::__base_of(__tmp));
+ _M_invoke = std::__exchange(__polyfunc::__invoker_of(__tmp), nullptr);
+ }
+ else
+ {
+ _M_init<_Vt>(std::forward<_Fn>(__f));
+ _M_invoke = _Invoker::template _S_storage<_Vt _GLIBCXX_MOF_INV_QUALS>();
+ }
}
/// Stores a target object initialized from the arguments.
@@ -115,7 +139,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit
move_only_function(in_place_type_t<_Tp>, _Args&&... __args)
noexcept(_S_nothrow_init<_Tp, _Args...>())
- : _M_invoke(&_S_invoke<_Tp>)
+ : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>())
{
static_assert(is_same_v<decay_t<_Tp>, _Tp>);
_M_init<_Tp>(std::forward<_Args>(__args)...);
@@ -129,7 +153,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il,
_Args&&... __args)
noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>())
- : _M_invoke(&_S_invoke<_Tp>)
+ : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>())
{
static_assert(is_same_v<decay_t<_Tp>, _Tp>);
_M_init<_Tp>(__il, std::forward<_Args>(__args)...);
@@ -139,8 +163,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
move_only_function&
operator=(move_only_function&& __x) noexcept
{
- _Mofunc_base::operator=(static_cast<_Mofunc_base&&>(__x));
- _M_invoke = std::__exchange(__x._M_invoke, nullptr);
+ // Standard requires support of self assigment, by specifying it as
+ // copy and swap.
+ if (this != std::addressof(__x)) [[likely]]
+ {
+ _Base::operator=(static_cast<_Base&&>(__x));
+ _M_invoke = std::__exchange(__x._M_invoke, nullptr);
+ }
return *this;
}
@@ -148,7 +177,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
move_only_function&
operator=(nullptr_t) noexcept
{
- _Mofunc_base::operator=(nullptr);
+ _M_reset();
_M_invoke = nullptr;
return *this;
}
@@ -167,7 +196,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~move_only_function() = default;
/// True if a target object is present, false otherwise.
- explicit operator bool() const noexcept { return _M_invoke != nullptr; }
+ explicit operator bool() const noexcept
+ { return _M_invoke != nullptr; }
/** Invoke the target object.
*
@@ -181,14 +211,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex)
{
__glibcxx_assert(*this != nullptr);
- return _M_invoke(this, std::forward<_ArgTypes>(__args)...);
+ return _M_invoke(this->_M_storage, std::forward<_ArgTypes>(__args)...);
}
/// Exchange the target objects (if any).
void
swap(move_only_function& __x) noexcept
{
- _Mofunc_base::swap(__x);
+ _Base::swap(__x);
std::swap(_M_invoke, __x._M_invoke);
}
@@ -203,25 +233,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __x._M_invoke == nullptr; }
private:
- template<typename _Tp>
- using __param_t = __conditional_t<is_scalar_v<_Tp>, _Tp, _Tp&&>;
+ typename _Invoker::__storage_func_t _M_invoke = nullptr;
- using _Invoker = _Res (*)(_Mofunc_base _GLIBCXX_MOF_CV*,
- __param_t<_ArgTypes>...) noexcept(_Noex);
+ template<typename _Func>
+ friend auto&
+ __polyfunc::__invoker_of(_Func&) noexcept;
- template<typename _Tp>
- static _Res
- _S_invoke(_Mofunc_base _GLIBCXX_MOF_CV* __self,
- __param_t<_ArgTypes>... __args) noexcept(_Noex)
- {
- using _TpCv = _Tp _GLIBCXX_MOF_CV;
- using _TpInv = _Tp _GLIBCXX_MOF_INV_QUALS;
- return std::__invoke_r<_Res>(
- std::forward<_TpInv>(*_S_access<_TpCv>(__self)),
- std::forward<__param_t<_ArgTypes>>(__args)...);
- }
+ template<typename _Func>
+ friend auto&
+ __polyfunc::__base_of(_Func&) noexcept;
- _Invoker _M_invoke = nullptr;
+ template<typename _Dst, typename _Src>
+ friend consteval bool
+ __polyfunc::__is_invoker_convertible() noexcept;
};
#undef _GLIBCXX_MOF_CV_REF
diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h
index e91b003..8c4f461 100644
--- a/libstdc++-v3/include/bits/move.h
+++ b/libstdc++-v3/include/bits/move.h
@@ -89,7 +89,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return static_cast<_Tp&&>(__t);
}
-#if __glibcxx_forward_like // C++ >= 23
template<typename _Tp, typename _Up>
struct __like_impl; // _Tp must be a reference and _Up an lvalue reference
@@ -112,6 +111,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Up>
using __like_t = typename __like_impl<_Tp&&, _Up&>::type;
+#if __glibcxx_forward_like // C++ >= 23
/** @brief Forward with the cv-qualifiers and value category of another type.
* @tparam _Tp An lvalue reference or rvalue reference.
* @tparam _Up An lvalue reference type deduced from the function argument.
@@ -174,7 +174,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[__nodiscard__,__gnu__::__always_inline__]]
inline _GLIBCXX17_CONSTEXPR _Tp*
addressof(_Tp& __r) noexcept
- { return std::__addressof(__r); }
+ { return __builtin_addressof(__r); }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2598. addressof works on temporaries
@@ -215,14 +215,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @return Nothing.
*/
template<typename _Tp>
- _GLIBCXX20_CONSTEXPR
- inline
-#if __cplusplus >= 201103L
- typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
- is_move_constructible<_Tp>,
- is_move_assignable<_Tp>>::value>::type
+#if __glibcxx_concepts // >= C++20
+ requires (! __is_tuple_like<_Tp>::value)
+ && is_move_constructible_v<_Tp>
+ && is_move_assignable_v<_Tp>
+ constexpr void
+#elif __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR inline
+ __enable_if_t<__and_<__not_<__is_tuple_like<_Tp>>,
+ is_move_constructible<_Tp>,
+ is_move_assignable<_Tp>>::value>
#else
- void
+ inline void
#endif
swap(_Tp& __a, _Tp& __b)
_GLIBCXX_NOEXCEPT_IF(__and_<is_nothrow_move_constructible<_Tp>,
@@ -241,12 +245,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// DR 809. std::swap should be overloaded for array types.
/// Swap the contents of two arrays.
template<typename _Tp, size_t _Nm>
- _GLIBCXX20_CONSTEXPR
- inline
-#if __cplusplus >= 201103L
- typename enable_if<__is_swappable<_Tp>::value>::type
+#if __glibcxx_concepts // >= C++20
+ requires is_swappable_v<_Tp>
+ constexpr void
+#elif __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR inline
+ __enable_if_t<__is_swappable<_Tp>::value>
#else
- void
+ inline void
#endif
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
_GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Tp>::value)
diff --git a/libstdc++-v3/include/bits/move_only_function.h b/libstdc++-v3/include/bits/move_only_function.h
deleted file mode 100644
index 42b33d0..0000000
--- a/libstdc++-v3/include/bits/move_only_function.h
+++ /dev/null
@@ -1,218 +0,0 @@
-// Implementation of std::move_only_function -*- 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 include/bits/move_only_function.h
- * This is an internal header file, included by other library headers.
- * Do not attempt to use it directly. @headername{functional}
- */
-
-#ifndef _GLIBCXX_MOVE_ONLY_FUNCTION_H
-#define _GLIBCXX_MOVE_ONLY_FUNCTION_H 1
-
-#ifdef _GLIBCXX_SYSHDR
-#pragma GCC system_header
-#endif
-
-#include <bits/version.h>
-
-#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
-
-#include <bits/invoke.h>
-#include <bits/utility.h>
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- template<typename... _Signature>
- class move_only_function; // not defined
-
- /// @cond undocumented
- class _Mofunc_base
- {
- protected:
- _Mofunc_base() noexcept
- : _M_manage(_S_empty)
- { }
-
- _Mofunc_base(_Mofunc_base&& __x) noexcept
- {
- _M_manage = std::__exchange(__x._M_manage, _S_empty);
- _M_manage(_M_storage, &__x._M_storage);
- }
-
- template<typename _Tp, typename... _Args>
- static constexpr bool
- _S_nothrow_init() noexcept
- {
- if constexpr (__stored_locally<_Tp>)
- return is_nothrow_constructible_v<_Tp, _Args...>;
- return false;
- }
-
- template<typename _Tp, typename... _Args>
- void
- _M_init(_Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>())
- {
- if constexpr (__stored_locally<_Tp>)
- ::new (_M_storage._M_addr()) _Tp(std::forward<_Args>(__args)...);
- else
- _M_storage._M_p = new _Tp(std::forward<_Args>(__args)...);
-
- _M_manage = &_S_manage<_Tp>;
- }
-
- _Mofunc_base&
- operator=(_Mofunc_base&& __x) noexcept
- {
- _M_manage(_M_storage, nullptr);
- _M_manage = std::__exchange(__x._M_manage, _S_empty);
- _M_manage(_M_storage, &__x._M_storage);
- return *this;
- }
-
- _Mofunc_base&
- operator=(nullptr_t) noexcept
- {
- _M_manage(_M_storage, nullptr);
- _M_manage = _S_empty;
- return *this;
- }
-
- ~_Mofunc_base() { _M_manage(_M_storage, nullptr); }
-
- void
- swap(_Mofunc_base& __x) noexcept
- {
- // Order of operations here is more efficient if __x is empty.
- _Storage __s;
- __x._M_manage(__s, &__x._M_storage);
- _M_manage(__x._M_storage, &_M_storage);
- __x._M_manage(_M_storage, &__s);
- std::swap(_M_manage, __x._M_manage);
- }
-
- template<typename _Tp, typename _Self>
- static _Tp*
- _S_access(_Self* __self) noexcept
- {
- if constexpr (__stored_locally<remove_const_t<_Tp>>)
- return static_cast<_Tp*>(__self->_M_storage._M_addr());
- else
- return static_cast<_Tp*>(__self->_M_storage._M_p);
- }
-
- private:
- struct _Storage
- {
- void* _M_addr() noexcept { return &_M_bytes[0]; }
- const void* _M_addr() const noexcept { return &_M_bytes[0]; }
-
- // We want to have enough space to store a simple delegate type.
- struct _Delegate { void (_Storage::*__pfm)(); _Storage* __obj; };
- union {
- void* _M_p;
- alignas(_Delegate) alignas(void(*)())
- unsigned char _M_bytes[sizeof(_Delegate)];
- };
- };
-
- template<typename _Tp>
- static constexpr bool __stored_locally
- = sizeof(_Tp) <= sizeof(_Storage) && alignof(_Tp) <= alignof(_Storage)
- && is_nothrow_move_constructible_v<_Tp>;
-
- // A function that either destroys the target object stored in __target,
- // or moves the target object from *__src to __target.
- using _Manager = void (*)(_Storage& __target, _Storage* __src) noexcept;
-
- // The no-op manager function for objects with no target.
- static void _S_empty(_Storage&, _Storage*) noexcept { }
-
- // The real manager function for a target object of type _Tp.
- template<typename _Tp>
- static void
- _S_manage(_Storage& __target, _Storage* __src) noexcept
- {
- if constexpr (__stored_locally<_Tp>)
- {
- if (__src)
- {
- _Tp* __rval = static_cast<_Tp*>(__src->_M_addr());
- ::new (__target._M_addr()) _Tp(std::move(*__rval));
- __rval->~_Tp();
- }
- else
- static_cast<_Tp*>(__target._M_addr())->~_Tp();
- }
- else
- {
- if (__src)
- __target._M_p = __src->_M_p;
- else
- delete static_cast<_Tp*>(__target._M_p);
- }
- }
-
- _Storage _M_storage;
- _Manager _M_manage;
- };
-
- template<typename _Tp>
- inline constexpr bool __is_move_only_function_v = false;
- template<typename _Tp>
- constexpr bool __is_move_only_function_v<move_only_function<_Tp>> = true;
- /// @endcond
-
- namespace __detail::__variant
- {
- template<typename> struct _Never_valueless_alt; // see <variant>
-
- // Provide the strong exception-safety guarantee when emplacing a
- // move_only_function into a variant.
- template<typename... _Signature>
- struct _Never_valueless_alt<std::move_only_function<_Signature...>>
- : true_type
- { };
- } // namespace __detail::__variant
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace std
-
-#include "mofunc_impl.h"
-#define _GLIBCXX_MOF_CV const
-#include "mofunc_impl.h"
-#define _GLIBCXX_MOF_REF &
-#include "mofunc_impl.h"
-#define _GLIBCXX_MOF_REF &&
-#include "mofunc_impl.h"
-#define _GLIBCXX_MOF_CV const
-#define _GLIBCXX_MOF_REF &
-#include "mofunc_impl.h"
-#define _GLIBCXX_MOF_CV const
-#define _GLIBCXX_MOF_REF &&
-#include "mofunc_impl.h"
-
-#endif // __glibcxx_move_only_function
-#endif // _GLIBCXX_MOVE_ONLY_FUNCTION_H
diff --git a/libstdc++-v3/include/bits/ostream.h b/libstdc++-v3/include/bits/ostream.h
index d19a76a..caa47be 100644
--- a/libstdc++-v3/include/bits/ostream.h
+++ b/libstdc++-v3/include/bits/ostream.h
@@ -499,9 +499,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
__sign = __builtin_signbit(__f) ? _To(-1.0) : _To(+1.0);
- if _GLIBCXX17_CONSTEXPR (__is_same(_To, double))
+ if _GLIBCXX_CONSTEXPR (__is_same(_To, double))
__d = __builtin_copysign(__d, __sign);
- else if _GLIBCXX17_CONSTEXPR (__is_same(_To, long double))
+ else if _GLIBCXX_CONSTEXPR (__is_same(_To, long double))
__d = __builtin_copysignl(__d, __sign);
#endif
return __d;
diff --git a/libstdc++-v3/include/bits/predefined_ops.h b/libstdc++-v3/include/bits/predefined_ops.h
index 5759ebd..d75b5c2 100644
--- a/libstdc++-v3/include/bits/predefined_ops.h
+++ b/libstdc++-v3/include/bits/predefined_ops.h
@@ -30,376 +30,178 @@
#ifndef _GLIBCXX_PREDEFINED_OPS_H
#define _GLIBCXX_PREDEFINED_OPS_H 1
-#include <bits/move.h>
+#include <bits/stl_function.h> // less<void>, equal_to<void>
+#if __cplusplus >= 201103L
+# include <type_traits> // is_empty, is_scalar, __conditional_t, __or_
+#else
+# include <ext/type_traits.h> // __conditional_type
+#endif
namespace __gnu_cxx
{
namespace __ops
{
- struct _Iter_less_iter
- {
- template<typename _Iterator1, typename _Iterator2>
- _GLIBCXX14_CONSTEXPR
- bool
- operator()(_Iterator1 __it1, _Iterator2 __it2) const
- { return *__it1 < *__it2; }
- };
-
- _GLIBCXX14_CONSTEXPR
- inline _Iter_less_iter
- __iter_less_iter()
- { return _Iter_less_iter(); }
-
- struct _Iter_less_val
- {
-#if __cplusplus >= 201103L
- constexpr _Iter_less_val() = default;
-#else
- _Iter_less_val() { }
-#endif
+ // These two explicit specializations are always defined by libstdc++,
+ // even when __cpp_lib_transparent_operators is not defined.
+ typedef std::equal_to<void> equal_to;
+ typedef std::less<void> less;
- _GLIBCXX20_CONSTEXPR
- explicit
- _Iter_less_val(_Iter_less_iter) { }
-
- template<typename _Iterator, typename _Value>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Iterator __it, _Value& __val) const
- { return *__it < __val; }
- };
-
- _GLIBCXX20_CONSTEXPR
- inline _Iter_less_val
- __iter_less_val()
- { return _Iter_less_val(); }
-
- _GLIBCXX20_CONSTEXPR
- inline _Iter_less_val
- __iter_comp_val(_Iter_less_iter)
- { return _Iter_less_val(); }
-
- struct _Val_less_iter
- {
#if __cplusplus >= 201103L
- constexpr _Val_less_iter() = default;
-#else
- _Val_less_iter() { }
-#endif
- _GLIBCXX20_CONSTEXPR
- explicit
- _Val_less_iter(_Iter_less_iter) { }
-
- template<typename _Value, typename _Iterator>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Value& __val, _Iterator __it) const
- { return __val < *__it; }
- };
-
- _GLIBCXX20_CONSTEXPR
- inline _Val_less_iter
- __val_less_iter()
- { return _Val_less_iter(); }
-
- _GLIBCXX20_CONSTEXPR
- inline _Val_less_iter
- __val_comp_iter(_Iter_less_iter)
- { return _Val_less_iter(); }
-
- struct _Iter_equal_to_iter
- {
- template<typename _Iterator1, typename _Iterator2>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Iterator1 __it1, _Iterator2 __it2) const
- { return *__it1 == *__it2; }
- };
-
- _GLIBCXX20_CONSTEXPR
- inline _Iter_equal_to_iter
- __iter_equal_to_iter()
- { return _Iter_equal_to_iter(); }
-
- struct _Iter_equal_to_val
- {
- template<typename _Iterator, typename _Value>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Iterator __it, _Value& __val) const
- { return *__it == __val; }
- };
-
- _GLIBCXX20_CONSTEXPR
- inline _Iter_equal_to_val
- __iter_equal_to_val()
- { return _Iter_equal_to_val(); }
-
- _GLIBCXX20_CONSTEXPR
- inline _Iter_equal_to_val
- __iter_comp_val(_Iter_equal_to_iter)
- { return _Iter_equal_to_val(); }
-
- template<typename _Compare>
- struct _Iter_comp_iter
- {
- _Compare _M_comp;
-
- explicit _GLIBCXX14_CONSTEXPR
- _Iter_comp_iter(_Compare __comp)
- : _M_comp(_GLIBCXX_MOVE(__comp))
- { }
-
- template<typename _Iterator1, typename _Iterator2>
- _GLIBCXX14_CONSTEXPR
- bool
- operator()(_Iterator1 __it1, _Iterator2 __it2)
- { return bool(_M_comp(*__it1, *__it2)); }
- };
+ template<typename _Fn>
+ using __by_ref_or_value_fn
+ = std::__conditional_t<std::__or_<std::is_empty<_Fn>,
+ std::is_scalar<_Fn>>::value,
+ _Fn, _Fn&>;
- template<typename _Compare>
- _GLIBCXX14_CONSTEXPR
- inline _Iter_comp_iter<_Compare>
- __iter_comp_iter(_Compare __comp)
- { return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
+ // More generic replacements for the deprecated utilities
+ // std::bind1st, std::bind2nd, and std::not1.
+ // These aren't fully "transparent" like std::less<void> because they
+ // do not use perfect forwarding, everything is treated as an lvalue.
- template<typename _Compare>
- struct _Iter_comp_val
+ template<typename _Func, typename _Value, bool _Val_2nd = false>
+ struct _Comp_with_val
{
- _Compare _M_comp;
-
- _GLIBCXX20_CONSTEXPR
- explicit
- _Iter_comp_val(_Compare __comp)
- : _M_comp(_GLIBCXX_MOVE(__comp))
- { }
-
- _GLIBCXX20_CONSTEXPR
- explicit
- _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp)
- : _M_comp(__comp._M_comp)
- { }
-
-#if __cplusplus >= 201103L
- _GLIBCXX20_CONSTEXPR
- explicit
- _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp)
- : _M_comp(std::move(__comp._M_comp))
- { }
-#endif
-
- template<typename _Iterator, typename _Value>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Iterator __it, _Value& __val)
- { return bool(_M_comp(*__it, __val)); }
+ using _Fn = __by_ref_or_value_fn<_Func>;
+
+ explicit constexpr
+ _Comp_with_val(_Fn __f, const _Value& __v)
+ : _M_f(__f), _M_val(__v) { }
+
+ [[__no_unique_address__]] _Fn _M_f;
+ const _Value& _M_val;
+
+ template<typename _Tp>
+ _GLIBCXX14_CONSTEXPR bool
+ operator()(_Tp&& __arg)
+ {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions"
+ if constexpr (_Val_2nd)
+ return _M_f(__arg, _M_val);
+ else
+ return _M_f(_M_val, __arg);
+#pragma GCC diagnostic pop
+ }
};
- template<typename _Compare>
- _GLIBCXX20_CONSTEXPR
- inline _Iter_comp_val<_Compare>
- __iter_comp_val(_Compare __comp)
- { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); }
-
- template<typename _Compare>
- _GLIBCXX20_CONSTEXPR
- inline _Iter_comp_val<_Compare>
- __iter_comp_val(_Iter_comp_iter<_Compare> __comp)
- { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); }
+ template<typename _Func, typename _Value>
+ using _Comp_with_val_1st = _Comp_with_val<_Func, _Value, false>;
+ template<typename _Func, typename _Value>
+ using _Comp_with_val_2nd = _Comp_with_val<_Func, _Value, true>;
- template<typename _Compare>
- struct _Val_comp_iter
+ template<typename _Func>
+ struct _Unary_negate
{
- _Compare _M_comp;
+ using _Fn = __by_ref_or_value_fn<_Func>;
- _GLIBCXX20_CONSTEXPR
- explicit
- _Val_comp_iter(_Compare __comp)
- : _M_comp(_GLIBCXX_MOVE(__comp))
- { }
-
- _GLIBCXX20_CONSTEXPR
- explicit
- _Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp)
- : _M_comp(__comp._M_comp)
- { }
+ explicit constexpr
+ _Unary_negate(_Fn __f) : _M_f(__f) { }
-#if __cplusplus >= 201103L
- _GLIBCXX20_CONSTEXPR
- explicit
- _Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp)
- : _M_comp(std::move(__comp._M_comp))
- { }
-#endif
+ [[__no_unique_address__]] _Fn _M_f;
- template<typename _Value, typename _Iterator>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Value& __val, _Iterator __it)
- { return bool(_M_comp(__val, *__it)); }
+ template<typename _Tp>
+ _GLIBCXX14_CONSTEXPR bool
+ operator()(_Tp&& __arg) { return !_M_f(__arg); }
};
- template<typename _Compare>
- _GLIBCXX20_CONSTEXPR
- inline _Val_comp_iter<_Compare>
- __val_comp_iter(_Compare __comp)
- { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
+ template<typename _Func>
+ constexpr _Unary_negate<_Func>
+ not1(_Func& __f)
+ { return _Unary_negate<_Func>(__f); }
- template<typename _Compare>
- _GLIBCXX20_CONSTEXPR
- inline _Val_comp_iter<_Compare>
- __val_comp_iter(_Iter_comp_iter<_Compare> __comp)
- { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
+#else // <= C++11
- template<typename _Value>
- struct _Iter_equals_val
- {
- _Value& _M_value;
+ template<typename _Fn>
+ struct __by_ref_or_value_fn
+ : __conditional_type<__is_empty(_Fn), _Fn, _Fn&>
+ { };
- _GLIBCXX20_CONSTEXPR
- explicit
- _Iter_equals_val(_Value& __value)
- : _M_value(__value)
- { }
-
- template<typename _Iterator>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Iterator __it)
- { return *__it == _M_value; }
- };
+ template<typename _Fn>
+ struct __by_ref_or_value_fn<_Fn*>
+ { typedef _Fn* __type; };
- template<typename _Value>
- _GLIBCXX20_CONSTEXPR
- inline _Iter_equals_val<_Value>
- __iter_equals_val(_Value& __val)
- { return _Iter_equals_val<_Value>(__val); }
+ // We don't use std::binder1st, std::binder2nd, or std::unary_negate here
+ // because they require adaptable function objects, i.e. types with nested
+ // result_type and argument_type/first_argument_type/second_argument_type.
- template<typename _Iterator1>
- struct _Iter_equals_iter
+ template<typename _Func, typename _Value>
+ struct _Comp_with_val_1st
{
- _Iterator1 _M_it1;
+ typedef typename __by_ref_or_value_fn<_Func>::__type _Fn;
- _GLIBCXX20_CONSTEXPR
explicit
- _Iter_equals_iter(_Iterator1 __it1)
- : _M_it1(__it1)
- { }
+ _Comp_with_val_1st(_Fn __f, const _Value& __v)
+ : _M_f(__f), _M_val(__v) { }
- template<typename _Iterator2>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Iterator2 __it2)
- { return *__it2 == *_M_it1; }
- };
+ _Fn _M_f;
+ const _Value& _M_val;
- template<typename _Iterator>
- _GLIBCXX20_CONSTEXPR
- inline _Iter_equals_iter<_Iterator>
- __iter_comp_iter(_Iter_equal_to_iter, _Iterator __it)
- { return _Iter_equals_iter<_Iterator>(__it); }
+ template<typename _Tp>
+ bool operator()(_Tp& __arg) { return _M_f(_M_val, __arg); }
+ template<typename _Tp>
+ bool operator()(const _Tp& __arg) { return _M_f(_M_val, __arg); }
+ };
- template<typename _Predicate>
- struct _Iter_pred
+ template<typename _Func, typename _Value>
+ struct _Comp_with_val_2nd
{
- _Predicate _M_pred;
+ typedef typename __by_ref_or_value_fn<_Func>::__type _Fn;
- _GLIBCXX20_CONSTEXPR
explicit
- _Iter_pred(_Predicate __pred)
- : _M_pred(_GLIBCXX_MOVE(__pred))
- { }
-
- template<typename _Iterator>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Iterator __it)
- { return bool(_M_pred(*__it)); }
- };
+ _Comp_with_val_2nd(_Fn __f, const _Value& __v)
+ : _M_f(__f), _M_val(__v) { }
- template<typename _Predicate>
- _GLIBCXX20_CONSTEXPR
- inline _Iter_pred<_Predicate>
- __pred_iter(_Predicate __pred)
- { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); }
+ _Fn _M_f;
+ const _Value& _M_val;
- template<typename _Compare, typename _Value>
- struct _Iter_comp_to_val
- {
- _Compare _M_comp;
- _Value& _M_value;
-
- _GLIBCXX20_CONSTEXPR
- _Iter_comp_to_val(_Compare __comp, _Value& __value)
- : _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value)
- { }
-
- template<typename _Iterator>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Iterator __it)
- { return bool(_M_comp(*__it, _M_value)); }
+ template<typename _Tp>
+ bool operator()(_Tp& __arg) { return _M_f(__arg, _M_val); }
+ template<typename _Tp>
+ bool operator()(const _Tp& __arg) { return _M_f(__arg, _M_val); }
};
- template<typename _Compare, typename _Value>
- _Iter_comp_to_val<_Compare, _Value>
- _GLIBCXX20_CONSTEXPR
- __iter_comp_val(_Compare __comp, _Value &__val)
+ template<typename _Func>
+ struct _Unary_negate_1 // N.B. different name for C++98 to satisfy ODR
{
- return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp), __val);
- }
+ typedef typename __by_ref_or_value_fn<_Func>::__type _Fn;
- template<typename _Compare, typename _Iterator1>
- struct _Iter_comp_to_iter
- {
- _Compare _M_comp;
- _Iterator1 _M_it1;
+ explicit _Unary_negate_1(_Fn __f) : _M_f(__f) { }
- _GLIBCXX20_CONSTEXPR
- _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1)
- : _M_comp(_GLIBCXX_MOVE(__comp)), _M_it1(__it1)
- { }
+ _Fn _M_f;
- template<typename _Iterator2>
- _GLIBCXX20_CONSTEXPR
+ template<typename _Tp>
+ bool
+ operator()(_Tp& __arg) { return !_M_f(__arg); }
+ template<typename _Tp>
bool
- operator()(_Iterator2 __it2)
- { return bool(_M_comp(*__it2, *_M_it1)); }
+ operator()(const _Tp& __arg) { return !_M_f(__arg); }
};
- template<typename _Compare, typename _Iterator>
- _GLIBCXX20_CONSTEXPR
- inline _Iter_comp_to_iter<_Compare, _Iterator>
- __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it)
- {
- return _Iter_comp_to_iter<_Compare, _Iterator>(
- _GLIBCXX_MOVE(__comp._M_comp), __it);
- }
+ template<typename _Func>
+ inline _Unary_negate_1<_Func>
+ not1(_Func& __f)
+ { return _Unary_negate_1<_Func>(__f); }
+#endif
- template<typename _Predicate>
- struct _Iter_negate
- {
- _Predicate _M_pred;
+ // N.B. these functions take lvalue references because we want to avoid
+ // returning a call wrapper that has a dangling reference to a prvalue.
- _GLIBCXX20_CONSTEXPR
- explicit
- _Iter_negate(_Predicate __pred)
- : _M_pred(_GLIBCXX_MOVE(__pred))
- { }
+ template<typename _Func, typename _Value>
+ _GLIBCXX_CONSTEXPR inline _Comp_with_val_1st<_Func, _Value>
+ bind1st(_Func& __f, const _Value& __val)
+ { return _Comp_with_val_1st<_Func, _Value>(__f, __val); }
- template<typename _Iterator>
- _GLIBCXX20_CONSTEXPR
- bool
- operator()(_Iterator __it)
- { return !bool(_M_pred(*__it)); }
- };
+ template<typename _Func, typename _Value>
+ _GLIBCXX_CONSTEXPR inline _Comp_with_val_2nd<_Func, _Value>
+ bind2nd(_Func& __f, const _Value& __val)
+ { return _Comp_with_val_2nd<_Func, _Value>(__f, __val); }
- template<typename _Predicate>
- _GLIBCXX20_CONSTEXPR
- inline _Iter_negate<_Predicate>
- __negate(_Iter_pred<_Predicate> __pred)
- { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); }
+ // Equivalent to bind2nd(equal_to{}, val)
+ template<typename _Value>
+ _GLIBCXX_CONSTEXPR inline _Comp_with_val_2nd<equal_to, _Value>
+ __equal_to(const _Value& __val)
+ { return _Comp_with_val_2nd<equal_to, _Value>(equal_to(), __val); }
} // namespace __ops
} // namespace __gnu_cxx
diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h
index d3c1765..91da88b 100644
--- a/libstdc++-v3/include/bits/ptr_traits.h
+++ b/libstdc++-v3/include/bits/ptr_traits.h
@@ -36,7 +36,7 @@
#if __cplusplus > 201703L
#include <concepts>
-namespace __gnu_debug { struct _Safe_iterator_base; }
+namespace __gnu_debug { class _Safe_iterator_base; }
#endif
namespace std _GLIBCXX_VISIBILITY(default)
@@ -223,7 +223,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/**
* @brief Obtain address referenced by a pointer to an object
* @param __ptr A pointer to an object
- * @return @c __ptr
+ * @return `__ptr`
* @ingroup pointer_abstractions
*/
template<typename _Tp>
@@ -239,8 +239,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/**
* @brief Obtain address referenced by a pointer to an object
* @param __ptr A pointer to an object
- * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is
- well-formed, otherwise @c to_address(__ptr.operator->())
+ * @return `pointer_traits<_Ptr>::to_address(__ptr)` if that expression is
+ * well-formed, otherwise `to_address(__ptr.operator->())`.
* @ingroup pointer_abstractions
*/
template<typename _Ptr>
diff --git a/libstdc++-v3/include/bits/quoted_string.h b/libstdc++-v3/include/bits/quoted_string.h
index 3a828d5..9a51aa3 100644
--- a/libstdc++-v3/include/bits/quoted_string.h
+++ b/libstdc++-v3/include/bits/quoted_string.h
@@ -61,6 +61,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Quoted_string&
operator=(_Quoted_string&) = delete;
+ // Friends for ADL with module std.
+ template<typename _CharT2, typename _Traits>
+ friend std::basic_ostream<_CharT2, _Traits>&
+ operator<<(std::basic_ostream<_CharT2, _Traits>& __os,
+ const _Quoted_string<const _CharT2*, _CharT2>& __str);
+
+ template<typename _CharT2, typename _Traits, typename _String2>
+ friend std::basic_ostream<_CharT2, _Traits>&
+ operator<<(std::basic_ostream<_CharT2, _Traits>& __os,
+ const _Quoted_string<_String2, _CharT2>& __str);
+
+ template<typename _CharT2, typename _Traits, typename _Alloc>
+ friend std::basic_istream<_CharT2, _Traits>&
+ operator>>(std::basic_istream<_CharT2, _Traits>& __is,
+ const _Quoted_string<basic_string<_CharT2, _Traits, _Alloc>&,
+ _CharT2>& __str);
+
_String _M_string;
_CharT _M_delim;
_CharT _M_escape;
@@ -78,6 +95,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Quoted_string&
operator=(_Quoted_string&) = delete;
+ // Friend for ADL with module std.
+ template<typename _CharT2, typename _Traits2, typename _String2>
+ friend std::basic_ostream<_CharT2, _Traits2>&
+ operator<<(std::basic_ostream<_CharT2, _Traits2>& __os,
+ const _Quoted_string<_String2, _CharT2>& __str);
+
basic_string_view<_CharT, _Traits> _M_string;
_CharT _M_delim;
_CharT _M_escape;
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
index 1fdaf51..ebc863e 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -32,6 +32,7 @@
#define _RANDOM_H 1
#include <vector>
+#include <bits/ios_base.h>
#include <bits/uniform_int_dist.h>
namespace std _GLIBCXX_VISIBILITY(default)
@@ -1688,6 +1689,263 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return !(__lhs == __rhs); }
#endif
+#if __glibcxx_philox_engine // >= C++26
+ /**
+ * @brief A discrete pseudorandom number generator with weak cryptographic
+ * properties
+ *
+ * This algorithm was designed to be used for highly parallel random number
+ * generation, and is capable of immensely long periods. It provides
+ * "Crush-resistance", denoting an ability to pass the TestU01 Suite's
+ * "Big Crush" test, demonstrating significant apparent entropy.
+ *
+ * It is not intended for cryptographic use and should not be used for such,
+ * despite being based on cryptographic primitives.
+ *
+ * The typedefs `philox4x32` and `philox4x64` are provided as suitable
+ * defaults for most use cases, providing high-quality random numbers
+ * with reasonable performance.
+ *
+ * This algorithm was created by John Salmon, Mark Moraes, Ron Dror, and
+ * David Shaw as a product of D.E. Shaw Research.
+ *
+ * @tparam __w Word size
+ * @tparam __n Buffer size
+ * @tparam __r Rounds
+ * @tparam __consts Multiplication and round constant pack, ordered as
+ * M_{0}, C_{0}, M_{1}, C_{1}, ... , M_{N/2-1}, C_{N/2-1}
+ *
+ * @headerfile random
+ * @since C++26
+ */
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
+ class philox_engine
+ {
+ static_assert(__n == 2 || __n == 4,
+ "template argument N must be either 2 or 4");
+ static_assert(sizeof...(__consts) == __n,
+ "length of consts array must match specified N");
+ static_assert(0 < __r, "a number of rounds must be specified");
+ static_assert((0 < __w && __w <= numeric_limits<_UIntType>::digits),
+ "specified bitlength must match input type");
+
+ template<typename _Sseq>
+ static constexpr bool __is_seed_seq = requires {
+ typename __detail::_If_seed_seq_for<_Sseq, philox_engine, _UIntType>;
+ };
+
+ template <size_t __ind0, size_t __ind1>
+ static constexpr
+ array<_UIntType, __n / 2>
+ _S_popArray()
+ {
+ if constexpr (__n == 4)
+ return {__consts...[__ind0], __consts...[__ind1]};
+ else
+ return {__consts...[__ind0]};
+ }
+
+ public:
+ using result_type = _UIntType;
+ // public members
+ static constexpr size_t word_size = __w;
+ static constexpr size_t word_count = __n;
+ static constexpr size_t round_count = __r;
+ static constexpr array<result_type, __n / 2> multipliers
+ = _S_popArray<0,2>();
+ static constexpr array<result_type, __n / 2> round_consts
+ = _S_popArray<1,3>();
+
+ /// The minimum value that this engine can return
+ static constexpr result_type
+ min()
+ { return 0; }
+
+ /// The maximum value that this engine can return
+ static constexpr result_type
+ max()
+ {
+ return ((1ull << (__w - 1)) | ((1ull << (__w - 1)) - 1));
+ }
+ // default key value
+ static constexpr result_type default_seed = 20111115u;
+
+ // constructors
+ philox_engine()
+ : philox_engine(default_seed)
+ { }
+
+ explicit
+ philox_engine(result_type __value)
+ : _M_x{}, _M_k{}, _M_y{}, _M_i(__n - 1)
+ { _M_k[0] = __value & max(); }
+
+ /** @brief seed sequence constructor for %philox_engine
+ *
+ * @param __q the seed sequence
+ */
+ template<typename _Sseq> requires __is_seed_seq<_Sseq>
+ explicit
+ philox_engine(_Sseq& __q)
+ {
+ seed(__q);
+ }
+
+ void
+ seed(result_type __value = default_seed)
+ {
+ _M_x = {};
+ _M_y = {};
+ _M_k = {};
+ _M_k[0] = __value & max();
+ _M_i = __n - 1;
+ }
+
+ /** @brief seeds %philox_engine by seed sequence
+ *
+ * @param __q the seed sequence
+ */
+ template<typename _Sseq>
+ void
+ seed(_Sseq& __q) requires __is_seed_seq<_Sseq>;
+
+ /** @brief sets the internal counter "cleartext"
+ *
+ * @param __counter std::array of len N
+ */
+ void
+ set_counter(const array<result_type, __n>& __counter)
+ {
+ for (size_t __j = 0; __j < __n; ++__j)
+ _M_x[__j] = __counter[__n - 1 - __j] & max();
+ _M_i = __n - 1;
+ }
+
+ /** @brief compares two %philox_engine objects
+ *
+ * @returns true if the objects will produce an identical stream,
+ * false otherwise
+ */
+ friend bool
+ operator==(const philox_engine&, const philox_engine&) = default;
+
+ /** @brief outputs a single w-bit number and handles state advancement
+ *
+ * @returns return_type
+ */
+ result_type
+ operator()()
+ {
+ _M_transition();
+ return _M_y[_M_i];
+ }
+
+ /** @brief discards __z numbers
+ *
+ * @param __z number of iterations to discard
+ */
+ void
+ discard(unsigned long long __z)
+ {
+ while (__z--)
+ _M_transition();
+ }
+
+ /** @brief outputs the state of the generator
+ *
+ * @param __os An output stream.
+ * @param __x A %philox_engine object reference
+ *
+ * @returns the state of the Philox Engine in __os
+ */
+ template<typename _CharT, typename _Traits>
+ friend basic_ostream<_CharT, _Traits>&
+ operator<<(basic_ostream<_CharT, _Traits>& __os,
+ const philox_engine& __x)
+ {
+ const typename ios_base::fmtflags __flags = __os.flags();
+ const _CharT __fill = __os.fill();
+ __os.flags(ios_base::dec | ios_base::left);
+ _CharT __space = __os.widen(' ');
+ __os.fill(__space);
+ for (auto& __subkey : __x._M_k)
+ __os << __subkey << __space;
+ for (auto& __ctr : __x._M_x)
+ __os << __ctr << __space;
+ __os << __x._M_i;
+ __os.flags(__flags);
+ __os.fill(__fill);
+ return __os;
+ }
+
+ /** @brief takes input to set the state of the %philox_engine object
+ *
+ * @param __is An input stream.
+ * @param __x A %philox_engine object reference
+ *
+ * @returns %philox_engine object is set with values from instream
+ */
+ template <typename _CharT, typename _Traits>
+ friend basic_istream<_CharT, _Traits>&
+ operator>>(basic_istream<_CharT, _Traits>& __is,
+ philox_engine& __x)
+ {
+ const typename ios_base::fmtflags __flags = __is.flags();
+ __is.flags(ios_base::dec | ios_base::skipws);
+ for (auto& __subkey : __x._M_k)
+ __is >> __subkey;
+ for (auto& __ctr : __x._M_x)
+ __is >> __ctr;
+ array<_UIntType, __n> __tmpCtr = __x._M_x;
+ unsigned char __setIndex = 0;
+ for (size_t __j = 0; __j < __x._M_x.size(); ++__j)
+ {
+ if (__x._M_x[__j] > 0)
+ {
+ __setIndex = __j;
+ break;
+ }
+ }
+ for (size_t __j = 0; __j <= __setIndex; ++__j)
+ {
+ if (__j != __setIndex)
+ __x._M_x[__j] = max();
+ else
+ --__x._M_x[__j];
+ }
+ __x._M_philox();
+ __x._M_x = __tmpCtr;
+ __is >> __x._M_i;
+ __is.flags(__flags);
+ return __is;
+ }
+
+ private:
+ // private state variables
+ array<_UIntType, __n> _M_x;
+ array<_UIntType, __n / 2> _M_k;
+ array<_UIntType, __n> _M_y;
+ unsigned long long _M_i = 0;
+
+ // The high W bits of the product of __a and __b
+ static _UIntType
+ _S_mulhi(_UIntType __a, _UIntType __b); // (A*B)/2^W
+
+ // The low W bits of the product of __a and __b
+ static _UIntType
+ _S_mullo(_UIntType __a, _UIntType __b); // (A*B)%2^W
+
+ // An R-round substitution/Feistel Network hybrid for philox_engine
+ void
+ _M_philox();
+
+ // The transition function
+ void
+ _M_transition();
+ };
+#endif
+
/**
* The classic Minimum Standard rand0 of Lewis, Goodman, and Miller.
*/
@@ -1742,6 +2000,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef minstd_rand0 default_random_engine;
+#if __glibcxx_philox_engine
+
+ /// 32-bit four-word Philox engine.
+ typedef philox_engine<
+ uint_fast32_t,
+ 32, 4, 10,
+ 0xCD9E8D57, 0x9E3779B9,
+ 0xD2511F53, 0xBB67AE85> philox4x32;
+
+ /// 64-bit four-word Philox engine.
+ typedef philox_engine<
+ uint_fast64_t,
+ 64, 4, 10,
+ 0xCA5A826395121157, 0x9E3779B97F4A7C15,
+ 0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B> philox4x64;
+#endif
+
/**
* A standard interface to a platform-specific non-deterministic
* random number generator (if any are available).
diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc
index 752d707..b4273f0 100644
--- a/libstdc++-v3/include/bits/random.tcc
+++ b/libstdc++-v3/include/bits/random.tcc
@@ -83,7 +83,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__normalize(_InputIterator __first, _InputIterator __last,
_OutputIterator __result, const _Tp& __factor)
{
- for (; __first != __last; ++__first, ++__result)
+ for (; __first != __last; ++__first, (void) ++__result)
*__result = *__first / __factor;
return __result;
}
@@ -849,11 +849,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr result_type __range = max() - min();
size_t __j = __k;
const result_type __y = _M_y - min();
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
// Avoid using slower long double arithmetic if possible.
- if _GLIBCXX17_CONSTEXPR (__detail::__p1_representable_as_double(__range))
+ if constexpr (__detail::__p1_representable_as_double(__range))
__j *= __y / (__range + 1.0);
else
__j *= __y / (__range + 1.0L);
+#pragma GCC diagnostic pop
_M_y = _M_v[__j];
_M_v[__j] = _M_b();
@@ -904,6 +907,129 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __is;
}
+#if __glibcxx_philox_engine // >= C++26
+
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
+ _UIntType
+ philox_engine<_UIntType, __w, __n, __r, __consts...>::
+ _S_mulhi(_UIntType __a, _UIntType __b)
+ {
+ const __uint128_t __num =
+ static_cast<__uint128_t>(__a) * static_cast<__uint128_t>(__b);
+ return static_cast<_UIntType>((__num >> __w) & max());
+ }
+
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
+ _UIntType
+ philox_engine<_UIntType, __w, __n, __r, __consts...>::
+ _S_mullo(_UIntType __a, _UIntType __b)
+ {
+ return static_cast<_UIntType>((__a * __b) & max());
+ }
+
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
+ void
+ philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_transition()
+ {
+ ++_M_i;
+ if (_M_i != __n)
+ return;
+
+ _M_philox();
+ if constexpr (__n == 4)
+ {
+ __uint128_t __uh =
+ (static_cast<__uint128_t>(_M_x[1]) << __w)
+ | (static_cast<__uint128_t>(_M_x[0]) + 1);
+ __uint128_t __lh =
+ ((static_cast<__uint128_t>(_M_x[3]) << __w)
+ | (_M_x[2]));
+ __uint128_t __bigMask =
+ (static_cast<__uint128_t>(1) << ((2 * __w) - 1))
+ | ((static_cast<__uint128_t>(1) << ((2 * __w) - 1)) - 1);
+ if ((__uh & __bigMask) == 0)
+ {
+ ++__lh;
+ __uh = 0;
+ }
+ _M_x[0] = __uh & max();
+ _M_x[1] = (__uh >> (__w)) & max();
+ _M_x[2] = __lh & max();
+ _M_x[3] = (__lh >> (__w)) & max();
+ }
+ else
+ {
+ __uint128_t __num =
+ (static_cast<__uint128_t>(_M_x[1]) << __w)
+ | (static_cast<__uint128_t>(_M_x[0]) + 1);
+ _M_x[0] = __num & max();
+ _M_x[1] = (__num >> __w) & max();
+ }
+ _M_i = 0;
+ }
+
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
+ void
+ philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_philox()
+ {
+ array<_UIntType, __n> __outputSeq = _M_x;
+ for (size_t __j = 0; __j < __r; ++__j)
+ {
+ array<_UIntType, __n> __intermedSeq{};
+ if constexpr (__n == 4)
+ {
+ __intermedSeq[0] = __outputSeq[2];
+ __intermedSeq[1] = __outputSeq[1];
+ __intermedSeq[2] = __outputSeq[0];
+ __intermedSeq[3] = __outputSeq[3];
+ }
+ else
+ {
+ __intermedSeq[0] = __outputSeq[0];
+ __intermedSeq[1] = __outputSeq[1];
+ }
+ for (unsigned long __k = 0; __k < (__n/2); ++__k)
+ {
+ __outputSeq[2*__k]
+ = _S_mulhi(__intermedSeq[2*__k], multipliers[__k])
+ ^ (((_M_k[__k] + (__j * round_consts[__k])) & max()))
+ ^ __intermedSeq[2*__k+1];
+
+ __outputSeq[(2*__k)+1]
+ = _S_mullo(__intermedSeq[2*__k], multipliers[__k]);
+ }
+ }
+ _M_y = __outputSeq;
+ }
+
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
+ template<typename _Sseq>
+ void
+ philox_engine<_UIntType, __w, __n, __r, __consts...>::seed(_Sseq& __q)
+ requires __is_seed_seq<_Sseq>
+ {
+ seed(0);
+
+ const unsigned __p = 1 + ((__w - 1) / 32);
+ uint_least32_t __tmpArr[(__n/2) * __p];
+ __q.generate(__tmpArr + 0, __tmpArr + ((__n/2) * __p));
+ for (unsigned __k = 0; __k < (__n/2); ++__k)
+ {
+ unsigned long long __precalc = 0;
+ for (unsigned __j = 0; __j < __p; ++__j)
+ {
+ unsigned long long __multiplicand = (1ull << (32 * __j));
+ __precalc += (__tmpArr[__k * __p + __j] * __multiplicand) & max();
+ }
+ _M_k[__k] = __precalc;
+ }
+ }
+#endif // philox_engine
template<typename _IntType, typename _CharT, typename _Traits>
std::basic_ostream<_CharT, _Traits>&
@@ -3075,7 +3201,7 @@ namespace __detail
_InputIteratorW __wbegin)
: _M_int(), _M_den(), _M_cp(), _M_m()
{
- for (; __bbegin != __bend; ++__bbegin, ++__wbegin)
+ for (; __bbegin != __bend; ++__bbegin, (void) ++__wbegin)
{
_M_int.push_back(*__bbegin);
_M_den.push_back(*__wbegin);
@@ -3244,8 +3370,11 @@ namespace __detail
template<typename _InputIterator>
seed_seq::seed_seq(_InputIterator __begin, _InputIterator __end)
{
- if _GLIBCXX17_CONSTEXPR (__is_random_access_iter<_InputIterator>::value)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ if constexpr (__is_random_access_iter<_InputIterator>::value)
_M_v.reserve(std::distance(__begin, __end));
+#pragma GCC diagnostic pop
for (_InputIterator __iter = __begin; __iter != __end; ++__iter)
_M_v.push_back(__detail::__mod<result_type,
diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index f36e7dd..5c9fe62 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -32,6 +32,7 @@
#if __cplusplus > 201703L
+#include <bit> // __bit_width
#if __cplusplus > 202002L
#include <optional>
#endif
@@ -47,28 +48,60 @@ namespace ranges
{
namespace __detail
{
+ template<typename _Fp>
+ using __by_ref_or_value_fn
+ = __conditional_t<is_scalar_v<_Fp> || is_empty_v<_Fp>, _Fp, _Fp&>;
+
template<typename _Comp, typename _Proj>
- constexpr auto
+ struct _Comp_proj
+ {
+ [[no_unique_address]] __by_ref_or_value_fn<_Comp> _M_comp;
+ [[no_unique_address]] __by_ref_or_value_fn<_Proj> _M_proj;
+
+ constexpr
+ _Comp_proj(_Comp& __comp, _Proj& __proj)
+ : _M_comp(__comp), _M_proj(__proj)
+ { }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ operator()(_Tp&& __x, _Up&& __y)
+ {
+ return std::__invoke(_M_comp,
+ std::__invoke(_M_proj, std::forward<_Tp>(__x)),
+ std::__invoke(_M_proj, std::forward<_Up>(__y)));
+ }
+ };
+
+ template<typename _Comp, typename _Proj>
+ constexpr _Comp_proj<_Comp, _Proj>
__make_comp_proj(_Comp& __comp, _Proj& __proj)
+ { return {__comp, __proj}; }
+
+ template<typename _Pred, typename _Proj>
+ struct _Pred_proj
{
- return [&] (auto&& __lhs, auto&& __rhs) -> bool {
- using _TL = decltype(__lhs);
- using _TR = decltype(__rhs);
- return std::__invoke(__comp,
- std::__invoke(__proj, std::forward<_TL>(__lhs)),
- std::__invoke(__proj, std::forward<_TR>(__rhs)));
- };
- }
+ [[no_unique_address]] __by_ref_or_value_fn<_Pred> _M_pred;
+ [[no_unique_address]] __by_ref_or_value_fn<_Proj> _M_proj;
+
+ constexpr
+ _Pred_proj(_Pred& __pred, _Proj& __proj)
+ : _M_pred(__pred), _M_proj(__proj)
+ { }
+
+ template<typename _Tp>
+ constexpr bool
+ operator()(_Tp&& __x)
+ {
+ return std::__invoke(_M_pred,
+ std::__invoke(_M_proj, std::forward<_Tp>(__x)));
+ }
+ };
template<typename _Pred, typename _Proj>
- constexpr auto
+ constexpr _Pred_proj<_Pred, _Proj>
__make_pred_proj(_Pred& __pred, _Proj& __proj)
- {
- return [&] <typename _Tp> (_Tp&& __arg) -> bool {
- return std::__invoke(__pred,
- std::__invoke(__proj, std::forward<_Tp>(__arg)));
- };
- }
+ { return {__pred, __proj}; }
} // namespace __detail
struct __all_of_fn
@@ -76,7 +109,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -89,7 +122,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -104,7 +137,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -117,7 +150,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -132,7 +165,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -145,7 +178,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -246,7 +279,7 @@ namespace ranges
typename _Pred = ranges::equal_to,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
- constexpr _Iter1
+ [[nodiscard]] constexpr _Iter1
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -265,7 +298,7 @@ namespace ranges
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
_Pred, _Proj1, _Proj2>
- constexpr borrowed_iterator_t<_Range1>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range1>
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -286,7 +319,7 @@ namespace ranges
requires indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>,
const _Tp*>
- constexpr iter_difference_t<_Iter>
+ [[nodiscard]] constexpr iter_difference_t<_Iter>
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Proj __proj = {}) const
{
@@ -303,7 +336,7 @@ namespace ranges
requires indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp*>
- constexpr range_difference_t<_Range>
+ [[nodiscard]] constexpr range_difference_t<_Range>
operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -438,6 +471,254 @@ namespace ranges
inline constexpr __search_n_fn search_n{};
+#if __glibcxx_ranges_starts_ends_with // C++ >= 23
+ struct __starts_with_fn
+ {
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
+ constexpr bool
+ operator()(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
+ {
+ iter_difference_t<_Iter1> __n1 = -1;
+ iter_difference_t<_Iter2> __n2 = -1;
+ if constexpr (sized_sentinel_for<_Sent1, _Iter1>)
+ __n1 = __last1 - __first1;
+ if constexpr (sized_sentinel_for<_Sent2, _Iter2>)
+ __n2 = __last2 - __first2;
+ return _S_impl(std::move(__first1), __last1, __n1,
+ std::move(__first2), __last2, __n2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<input_range _Range1, input_range _Range2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
+ _Pred, _Proj1, _Proj2>
+ constexpr bool
+ operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
+ {
+ range_difference_t<_Range1> __n1 = -1;
+ range_difference_t<_Range2> __n2 = -1;
+ if constexpr (sized_range<_Range1>)
+ __n1 = ranges::size(__r1);
+ if constexpr (sized_range<_Range2>)
+ __n2 = ranges::size(__r2);
+ return _S_impl(ranges::begin(__r1), ranges::end(__r1), __n1,
+ ranges::begin(__r2), ranges::end(__r2), __n2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ private:
+ template<typename _Iter1, typename _Sent1, typename _Iter2, typename _Sent2,
+ typename _Pred,
+ typename _Proj1, typename _Proj2>
+ static constexpr bool
+ _S_impl(_Iter1 __first1, _Sent1 __last1, iter_difference_t<_Iter1> __n1,
+ _Iter2 __first2, _Sent2 __last2, iter_difference_t<_Iter2> __n2,
+ _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
+ {
+ if (__first2 == __last2) [[unlikely]]
+ return true;
+ else if (__n1 == -1 || __n2 == -1)
+ return ranges::mismatch(std::move(__first1), __last1,
+ std::move(__first2), __last2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2)).in2 == __last2;
+ else if (__n1 < __n2)
+ return false;
+ else if constexpr (random_access_iterator<_Iter1>)
+ return ranges::equal(__first1, __first1 + iter_difference_t<_Iter1>(__n2),
+ std::move(__first2), __last2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ else
+ return ranges::equal(counted_iterator(std::move(__first1),
+ iter_difference_t<_Iter1>(__n2)),
+ default_sentinel,
+ std::move(__first2), __last2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ friend struct __ends_with_fn;
+ };
+
+ inline constexpr __starts_with_fn starts_with{};
+
+ struct __ends_with_fn
+ {
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires (forward_iterator<_Iter1> || sized_sentinel_for<_Sent1, _Iter1>)
+ && (forward_iterator<_Iter2> || sized_sentinel_for<_Sent2, _Iter2>)
+ && indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
+ constexpr bool
+ operator()(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
+ {
+ iter_difference_t<_Iter1> __n1 = -1;
+ iter_difference_t<_Iter2> __n2 = -1;
+ if constexpr (sized_sentinel_for<_Sent1, _Iter1>)
+ __n1 = __last1 - __first1;
+ if constexpr (sized_sentinel_for<_Sent2, _Iter2>)
+ __n2 = __last2 - __first2;
+ return _S_impl(std::move(__first1), __last1, __n1,
+ std::move(__first2), __last2, __n2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<input_range _Range1, input_range _Range2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires (forward_range<_Range1> || sized_range<_Range1>)
+ && (forward_range<_Range2> || sized_range<_Range2>)
+ && indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
+ _Pred, _Proj1, _Proj2>
+ constexpr bool
+ operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
+ {
+ range_difference_t<_Range1> __n1 = -1;
+ range_difference_t<_Range2> __n2 = -1;
+ if constexpr (sized_range<_Range1>)
+ __n1 = ranges::size(__r1);
+ if constexpr (sized_range<_Range2>)
+ __n2 = ranges::size(__r2);
+ return _S_impl(ranges::begin(__r1), ranges::end(__r1), __n1,
+ ranges::begin(__r2), ranges::end(__r2), __n2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ private:
+ template<typename _Iter1, typename _Sent1,
+ typename _Iter2, typename _Sent2,
+ typename _Pred,
+ typename _Proj1, typename _Proj2>
+ static constexpr bool
+ _S_impl(_Iter1 __first1, _Sent1 __last1, iter_difference_t<_Iter1> __n1,
+ _Iter2 __first2, _Sent2 __last2, iter_difference_t<_Iter2> __n2,
+ _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
+ {
+ if constexpr (!random_access_iterator<_Iter1>
+ && bidirectional_iterator<_Iter1> && same_as<_Iter1, _Sent1>
+ && bidirectional_iterator<_Iter2> && same_as<_Iter2, _Sent2>)
+ return starts_with._S_impl(std::make_reverse_iterator(__last1),
+ std::make_reverse_iterator(__first1),
+ __n1,
+ std::make_reverse_iterator(__last2),
+ std::make_reverse_iterator(__first2),
+ __n2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+
+ if (__first2 == __last2) [[unlikely]]
+ return true;
+
+ if constexpr (forward_iterator<_Iter2>)
+ if (__n2 == -1)
+ __n2 = ranges::distance(__first2, __last2);
+
+ // __glibcxx_assert(__n2 != -1);
+
+ if (__n1 != -1)
+ {
+ if (__n1 < __n2)
+ return false;
+ auto __shift = __n1 - iter_difference_t<_Iter1>(__n2);
+ if (random_access_iterator<_Iter1>
+ || !bidirectional_iterator<_Iter1>
+ || !same_as<_Iter1, _Sent1>
+ || __shift < __n2)
+ {
+ ranges::advance(__first1, __shift);
+ return ranges::equal(std::move(__first1), __last1,
+ std::move(__first2), __last2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+ }
+
+ if constexpr (bidirectional_iterator<_Iter1> && same_as<_Iter1, _Sent1>)
+ {
+ _Iter1 __it1 = __last1;
+ if (__n1 != -1)
+ ranges::advance(__it1, -iter_difference_t<_Iter1>(__n2));
+ else
+ {
+ // We can't use ranges::advance if the haystack size is
+ // unknown, since we need to detect and return false if
+ // it's smaller than the needle.
+ iter_difference_t<_Iter2> __m = __n2;
+ while (__m != 0 && __it1 != __first1)
+ {
+ --__m;
+ --__it1;
+ }
+ if (__m != 0)
+ return false;
+ }
+ return ranges::equal(__it1, __last1,
+ std::move(__first2), __last2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+ else if constexpr (forward_iterator<_Iter1>)
+ {
+ // __glibcxx_assert(__n1 == -1);
+ _Iter1 __prev_first1;
+ __n1 = 0;
+ while (true)
+ {
+ iter_difference_t<_Iter2> __m = __n2;
+ _Iter1 __it1 = __first1;
+ while (__m != 0 && __it1 != __last1)
+ {
+ ++__n1;
+ --__m;
+ ++__it1;
+ }
+ if (__m != 0)
+ {
+ // __glibcxx_assert(__it1 == __last1);
+ if (__n1 < __n2)
+ return false;
+ __first1 = ranges::next(__prev_first1,
+ iter_difference_t<_Iter1>(__n2 - __m));
+ break;
+ }
+ __prev_first1 = __first1;
+ __first1 = __it1;
+ }
+ return ranges::equal(__first1, __last1,
+ std::move(__first2), __last2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+ else
+ // If the haystack is non-forward then it must be sized, in which case
+ // we already returned via the __n1 != 1 case.
+ __builtin_unreachable();
+ }
+
+ };
+
+ inline constexpr __ends_with_fn ends_with{};
+#endif // __glibcxx_ranges_starts_ends_with
+
struct __find_end_fn
{
template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
@@ -445,7 +726,7 @@ namespace ranges
typename _Pred = ranges::equal_to,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
- constexpr subrange<_Iter1>
+ [[nodiscard]] constexpr subrange<_Iter1>
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -502,7 +783,7 @@ namespace ranges
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
_Pred, _Proj1, _Proj2>
- constexpr borrowed_subrange_t<_Range1>
+ [[nodiscard]] constexpr borrowed_subrange_t<_Range1>
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -525,7 +806,7 @@ namespace ranges
indirect_equivalence_relation<projected<_Iter1, _Proj1>,
projected<_Iter2, _Proj2>> _Pred
= ranges::equal_to>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -594,7 +875,7 @@ namespace ranges
indirect_equivalence_relation<
projected<iterator_t<_Range1>, _Proj1>,
projected<iterator_t<_Range2>, _Proj2>> _Pred = ranges::equal_to>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -1000,7 +1281,7 @@ namespace ranges
template<permutable _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- constexpr subrange<_Iter>
+ [[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -1013,7 +1294,7 @@ namespace ranges
for (; __first != __last; ++__first)
if (!std::__invoke(__pred, std::__invoke(__proj, *__first)))
{
- *__result = std::move(*__first);
+ *__result = ranges::iter_move(__first);
++__result;
}
@@ -1024,7 +1305,7 @@ namespace ranges
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
requires permutable<iterator_t<_Range>>
- constexpr borrowed_subrange_t<_Range>
+ [[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -1042,7 +1323,7 @@ namespace ranges
requires indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>,
const _Tp*>
- constexpr subrange<_Iter>
+ [[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Proj __proj = {}) const
{
@@ -1060,7 +1341,7 @@ namespace ranges
&& indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp*>
- constexpr borrowed_subrange_t<_Range>
+ [[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -1159,7 +1440,7 @@ namespace ranges
typename _Proj = identity,
indirect_equivalence_relation<
projected<_Iter, _Proj>> _Comp = ranges::equal_to>
- constexpr subrange<_Iter>
+ [[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -1173,7 +1454,7 @@ namespace ranges
if (!std::__invoke(__comp,
std::__invoke(__proj, *__dest),
std::__invoke(__proj, *__first)))
- *++__dest = std::move(*__first);
+ *++__dest = ranges::iter_move(__first);
return {++__dest, __first};
}
@@ -1181,7 +1462,7 @@ namespace ranges
indirect_equivalence_relation<
projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
requires permutable<iterator_t<_Range>>
- constexpr borrowed_subrange_t<_Range>
+ [[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -1218,6 +1499,9 @@ namespace ranges
if (__first == __last)
return {std::move(__first), std::move(__result)};
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4269. unique_copy passes arguments to its predicate backwards
+
// TODO: perform a closer comparison with reference implementations
if constexpr (forward_iterator<_Iter>)
{
@@ -1245,13 +1529,13 @@ namespace ranges
}
else // indirectly_copyable_storable<_Iter, _Out>
{
- auto __value = *__first;
+ iter_value_t<_Iter> __value(*__first);
*__result = __value;
while (++__first != __last)
{
if (!(bool)std::__invoke(__comp,
- std::__invoke(__proj, *__first),
- std::__invoke(__proj, __value)))
+ std::__invoke(__proj, __value),
+ std::__invoke(__proj, *__first)))
{
__value = *__first;
*++__result = __value;
@@ -1399,9 +1683,11 @@ namespace ranges
if constexpr (__is_pod(iter_value_t<_Iter>))
if (__k == 1)
{
- auto __t = std::move(*__p);
- ranges::move(__p + 1, __p + __n, __p);
- *(__p + __n - 1) = std::move(__t);
+ auto __mid = ranges::next(__p, __n - 1);
+ auto __end = ranges::next(__mid);
+ iter_value_t<_Iter> __t(ranges::iter_move(__p));
+ ranges::move(ranges::next(__p), __end, __p);
+ *__mid = std::move(__t);
return {std::move(__ret), std::move(__lasti)};
}
auto __q = __p + __k;
@@ -1425,8 +1711,10 @@ namespace ranges
if constexpr (__is_pod(iter_value_t<_Iter>))
if (__k == 1)
{
- auto __t = std::move(*(__p + __n - 1));
- ranges::move_backward(__p, __p + __n - 1, __p + __n);
+ auto __mid = ranges::next(__p, __n - 1);
+ auto __end = ranges::next(__mid);
+ iter_value_t<_Iter> __t(ranges::iter_move(__mid));
+ ranges::move_backward(__p, __mid, __end);
*__p = std::move(__t);
return {std::move(__ret), std::move(__lasti)};
}
@@ -1555,14 +1843,70 @@ namespace ranges
operator()(_Iter __first, _Sent __last, _Out __out,
iter_difference_t<_Iter> __n, _Gen&& __g) const
{
+ // FIXME: Correctly handle integer-class difference types.
if constexpr (forward_iterator<_Iter>)
{
- // FIXME: Forwarding to std::sample here requires computing __lasti
- // which may take linear time.
- auto __lasti = ranges::next(__first, __last);
- return _GLIBCXX_STD_A::
- sample(std::move(__first), std::move(__lasti), std::move(__out),
- __n, std::forward<_Gen>(__g));
+ using _Size = iter_difference_t<_Iter>;
+ using __distrib_type = uniform_int_distribution<_Size>;
+ using __param_type = typename __distrib_type::param_type;
+ using _USize = __detail::__make_unsigned_like_t<_Size>;
+ using __uc_type
+ = common_type_t<typename remove_reference_t<_Gen>::result_type, _USize>;
+
+ if (__first == __last)
+ return __out;
+
+ __distrib_type __d{};
+ _Size __unsampled_sz = ranges::distance(__first, __last);
+ __n = std::min(__n, __unsampled_sz);
+
+ // If possible, we use __gen_two_uniform_ints to efficiently produce
+ // two random numbers using a single distribution invocation:
+
+ const __uc_type __urngrange = __g.max() - __g.min();
+ if (__urngrange / __uc_type(__unsampled_sz) >= __uc_type(__unsampled_sz))
+ // I.e. (__urngrange >= __unsampled_sz * __unsampled_sz) but without
+ // wrapping issues.
+ {
+ while (__n != 0 && __unsampled_sz >= 2)
+ {
+ const pair<_Size, _Size> __p =
+ __gen_two_uniform_ints(__unsampled_sz, __unsampled_sz - 1, __g);
+
+ --__unsampled_sz;
+ if (__p.first < __n)
+ {
+ *__out = *__first;
+ ++__out;
+ --__n;
+ }
+
+ ++__first;
+
+ if (__n == 0) break;
+
+ --__unsampled_sz;
+ if (__p.second < __n)
+ {
+ *__out = *__first;
+ ++__out;
+ --__n;
+ }
+
+ ++__first;
+ }
+ }
+
+ // The loop above is otherwise equivalent to this one-at-a-time version:
+
+ for (; __n != 0; ++__first)
+ if (__d(__g, __param_type{0, --__unsampled_sz}) < __n)
+ {
+ *__out = *__first;
+ ++__out;
+ --__n;
+ }
+ return __out;
}
else
{
@@ -1583,7 +1927,7 @@ namespace ranges
if (__k < __n)
__out[__k] = *__first;
}
- return __out + __sample_sz;
+ return __out + iter_difference_t<_Out>(__sample_sz);
}
}
@@ -1612,9 +1956,66 @@ namespace ranges
_Iter
operator()(_Iter __first, _Sent __last, _Gen&& __g) const
{
- auto __lasti = ranges::next(__first, __last);
- std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g));
- return __lasti;
+ // FIXME: Correctly handle integer-class difference types.
+ if (__first == __last)
+ return __first;
+
+ using _DistanceType = iter_difference_t<_Iter>;
+ using __ud_type = __detail::__make_unsigned_like_t<_DistanceType>;
+ using __distr_type = std::uniform_int_distribution<__ud_type>;
+ using __p_type = typename __distr_type::param_type;
+
+ using __uc_type
+ = common_type_t<typename remove_reference_t<_Gen>::result_type, __ud_type>;
+
+ if constexpr (sized_sentinel_for<_Sent, _Iter>)
+ {
+ const __uc_type __urngrange = __g.max() - __g.min();
+ const __uc_type __urange = __uc_type(__last - __first);
+
+ if (__urngrange / __urange >= __urange)
+ // I.e. (__urngrange >= __urange * __urange) but without wrap issues.
+ {
+ _Iter __i = ranges::next(__first);
+
+ // Since we know the range isn't empty, an even number of elements
+ // means an uneven number of elements /to swap/, in which case we
+ // do the first one up front:
+
+ if ((__urange % 2) == 0)
+ {
+ __distr_type __d{0, 1};
+ ranges::iter_swap(__i++, ranges::next(__first, __d(__g)));
+ }
+
+ // Now we know that __last - __i is even, so we do the rest in pairs,
+ // using a single distribution invocation to produce swap positions
+ // for two successive elements at a time:
+
+ while (__i != __last)
+ {
+ const __uc_type __swap_range = __uc_type(__i - __first) + 1;
+
+ const pair<_DistanceType, _DistanceType> __pospos =
+ __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g);
+
+ ranges::iter_swap(__i++, ranges::next(__first, __pospos.first));
+ ranges::iter_swap(__i++, ranges::next(__first, __pospos.second));
+ }
+
+ return __i;
+ }
+ }
+
+ __distr_type __d;
+
+ _Iter __i = ranges::next(__first);
+ for (; __i != __last; ++__i)
+ ranges::iter_swap(__i,
+ ranges::next(__first,
+ __d(__g, __p_type(0, __i - __first))));
+
+ return __i;
}
template<random_access_range _Range, typename _Gen>
@@ -1623,13 +2024,42 @@ namespace ranges
borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Gen&& __g) const
{
- return (*this)(ranges::begin(__r), ranges::end(__r),
- std::forward<_Gen>(__g));
+ if constexpr (sized_range<_Range>
+ && !sized_sentinel_for<sentinel_t<_Range>,
+ iterator_t<_Range>>)
+ return (*this)(ranges::begin(__r),
+ ranges::begin(__r) + ranges::distance(__r),
+ std::forward<_Gen>(__g));
+ else
+ return (*this)(ranges::begin(__r), ranges::end(__r),
+ std::forward<_Gen>(__g));
}
};
inline constexpr __shuffle_fn shuffle{};
+ namespace __detail
+ {
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __push_heap(_Iter __first,
+ iter_difference_t<_Iter> __holeIndex,
+ iter_difference_t<_Iter> __topIndex,
+ iter_value_t<_Iter> __value,
+ _Comp __comp)
+ {
+ auto __parent = (__holeIndex - 1) / 2;
+ while (__holeIndex > __topIndex
+ && __comp(*(__first + __parent), __value))
+ {
+ *(__first + __holeIndex) = ranges::iter_move(__first + __parent);
+ __holeIndex = __parent;
+ __parent = (__holeIndex - 1) / 2;
+ }
+ *(__first + __holeIndex) = std::move(__value);
+ }
+ } // namespace __detail
+
struct __push_heap_fn
{
template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -1639,10 +2069,17 @@ namespace ranges
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
- auto __lasti = ranges::next(__first, __last);
- std::push_heap(__first, __lasti,
- __detail::__make_comp_proj(__comp, __proj));
- return __lasti;
+ if constexpr (!same_as<_Iter, _Sent>)
+ return (*this)(__first, ranges::next(__first, __last),
+ std::move(__comp), std::move(__proj));
+ else
+ {
+ auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
+ iter_value_t<_Iter> __value(ranges::iter_move(ranges::prev(__last)));
+ __detail::__push_heap(__first, (__last - __first) - 1,
+ 0, std::move(__value), __comp_proj);
+ return __last;
+ }
}
template<random_access_range _Range,
@@ -1658,6 +2095,48 @@ namespace ranges
inline constexpr __push_heap_fn push_heap{};
+ namespace __detail
+ {
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __adjust_heap(_Iter __first,
+ iter_difference_t<_Iter> __holeIndex,
+ iter_difference_t<_Iter> __len,
+ iter_value_t<_Iter> __value,
+ _Comp __comp)
+ {
+ auto __topIndex = __holeIndex;
+ auto __secondChild = __holeIndex;
+ while (__secondChild < (__len - 1) / 2)
+ {
+ __secondChild = 2 * (__secondChild + 1);
+ if (__comp(*(__first + __secondChild),
+ *(__first + (__secondChild - 1))))
+ __secondChild--;
+ *(__first + __holeIndex) = ranges::iter_move(__first + __secondChild);
+ __holeIndex = __secondChild;
+ }
+ if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
+ {
+ __secondChild = 2 * (__secondChild + 1);
+ *(__first + __holeIndex) = ranges::iter_move(__first + (__secondChild - 1));
+ __holeIndex = __secondChild - 1;
+ }
+ __detail::__push_heap(__first, __holeIndex, __topIndex,
+ std::move(__value), __comp);
+ }
+
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __pop_heap(_Iter __first, _Iter __last, _Iter __result, _Comp __comp)
+ {
+ iter_value_t<_Iter> __value = ranges::iter_move(__result);
+ *__result = ranges::iter_move(__first);
+ __detail::__adjust_heap(__first, 0, __last - __first,
+ std::move(__value), __comp);
+ }
+ } // namespace __detail
+
struct __pop_heap_fn
{
template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -1667,10 +2146,19 @@ namespace ranges
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
- auto __lasti = ranges::next(__first, __last);
- std::pop_heap(__first, __lasti,
- __detail::__make_comp_proj(__comp, __proj));
- return __lasti;
+ if constexpr (!same_as<_Iter, _Sent>)
+ return (*this)(__first, ranges::next(__first, __last),
+ std::move(__comp), std::move(__proj));
+ else
+ {
+ if (__last - __first > 1)
+ {
+ auto __back = ranges::prev(__last);
+ auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
+ __detail::__pop_heap(__first, __back, __back, __comp_proj);
+ }
+ return __last;
+ }
}
template<random_access_range _Range,
@@ -1695,10 +2183,29 @@ namespace ranges
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
- auto __lasti = ranges::next(__first, __last);
- std::make_heap(__first, __lasti,
- __detail::__make_comp_proj(__comp, __proj));
- return __lasti;
+ if constexpr (!same_as<_Iter, _Sent>)
+ return (*this)(__first, ranges::next(__first, __last),
+ std::move(__comp), std::move(__proj));
+ else
+ {
+ const auto __len = __last - __first;
+ if (__len < 2)
+ return __last;
+
+ auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
+ auto __parent = (__len - 2) / 2;
+ while (true)
+ {
+ iter_value_t<_Iter> __value = ranges::iter_move(__first + __parent);
+ __detail::__adjust_heap(__first, __parent, __len,
+ std::move(__value),
+ __comp_proj);
+ if (__parent == 0)
+ break;
+ __parent--;
+ }
+ return __last;
+ }
}
template<random_access_range _Range,
@@ -1723,10 +2230,20 @@ namespace ranges
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
- auto __lasti = ranges::next(__first, __last);
- std::sort_heap(__first, __lasti,
- __detail::__make_comp_proj(__comp, __proj));
- return __lasti;
+ if constexpr (!same_as<_Iter, _Sent>)
+ return (*this)(__first, ranges::next(__first, __last),
+ std::move(__comp), std::move(__proj));
+ else
+ {
+ auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
+ _Iter __ret = __last;
+ while (__last - __first > 1)
+ {
+ --__last;
+ __detail::__pop_heap(__first, __last, __last, __comp_proj);
+ }
+ return __ret;
+ }
}
template<random_access_range _Range,
@@ -1809,6 +2326,157 @@ namespace ranges
inline constexpr __is_heap_fn is_heap{};
+ namespace __detail
+ {
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __move_median_to_first(_Iter __result, _Iter __a, _Iter __b, _Iter __c,
+ _Comp __comp)
+ {
+ if (__comp(*__a, *__b))
+ {
+ if (__comp(*__b, *__c))
+ ranges::iter_swap(__result, __b);
+ else if (__comp(*__a, *__c))
+ ranges::iter_swap(__result, __c);
+ else
+ ranges::iter_swap(__result, __a);
+ }
+ else if (__comp(*__a, *__c))
+ ranges::iter_swap(__result, __a);
+ else if (__comp(*__b, *__c))
+ ranges::iter_swap(__result, __c);
+ else
+ ranges::iter_swap(__result, __b);
+ }
+
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __unguarded_linear_insert(_Iter __last, _Comp __comp)
+ {
+ iter_value_t<_Iter> __val = ranges::iter_move(__last);
+ _Iter __next = __last;
+ --__next;
+ while (__comp(__val, *__next))
+ {
+ *__last = ranges::iter_move(__next);
+ __last = __next;
+ --__next;
+ }
+ *__last = std::move(__val);
+ }
+
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __insertion_sort(_Iter __first, _Iter __last, _Comp __comp)
+ {
+ if (__first == __last)
+ return;
+
+ for (_Iter __i = ranges::next(__first); __i != __last; ++__i)
+ {
+ if (__comp(*__i, *__first))
+ {
+ iter_value_t<_Iter> __val = ranges::iter_move(__i);
+ ranges::move_backward(__first, __i, ranges::next(__i));
+ *__first = std::move(__val);
+ }
+ else
+ __detail::__unguarded_linear_insert(__i, __comp);
+ }
+ }
+
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __unguarded_insertion_sort(_Iter __first, _Iter __last, _Comp __comp)
+ {
+ for (_Iter __i = __first; __i != __last; ++__i)
+ __detail::__unguarded_linear_insert(__i, __comp);
+ }
+
+ inline constexpr int __sort_threshold = 16;
+
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __final_insertion_sort(_Iter __first, _Iter __last, _Comp __comp)
+ {
+ constexpr iter_difference_t<_Iter> __threshold = __sort_threshold;
+ if (__last - __first > __threshold)
+ {
+ __detail::__insertion_sort(__first, __first + __threshold, __comp);
+ __detail::__unguarded_insertion_sort(__first + __threshold, __last,
+ __comp);
+ }
+ else
+ __detail::__insertion_sort(__first, __last, __comp);
+ }
+
+ template<typename _Iter, typename _Comp>
+ constexpr _Iter
+ __unguarded_partition(_Iter __first, _Iter __last, _Iter __pivot, _Comp __comp)
+ {
+ while (true)
+ {
+ while (__comp(*__first, *__pivot))
+ ++__first;
+ --__last;
+ while (__comp(*__pivot, *__last))
+ --__last;
+ if (!(__first < __last))
+ return __first;
+ ranges::iter_swap(__first, __last);
+ ++__first;
+ }
+ }
+
+ template<typename _Iter, typename _Comp>
+ constexpr _Iter
+ __unguarded_partition_pivot(_Iter __first, _Iter __last, _Comp __comp)
+ {
+ _Iter __mid = __first + (__last - __first) / 2;
+ __detail::__move_median_to_first(__first, ranges::next(__first), __mid,
+ ranges::prev(__last), __comp);
+ return __detail::__unguarded_partition(ranges::next(__first), __last,
+ __first, __comp);
+ }
+
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __heap_select(_Iter __first, _Iter __middle, _Iter __last, _Comp __comp)
+ {
+ ranges::make_heap(__first, __middle, __comp);
+ for (_Iter __i = __middle; __i < __last; ++__i)
+ if (__comp(*__i, *__first))
+ __detail::__pop_heap(__first, __middle, __i, __comp);
+ }
+
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __partial_sort(_Iter __first, _Iter __middle, _Iter __last, _Comp __comp)
+ {
+ __detail::__heap_select(__first, __middle, __last, __comp);
+ ranges::sort_heap(__first, __middle, __comp);
+ }
+
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __introsort_loop(_Iter __first, _Iter __last, unsigned __depth_limit, _Comp __comp)
+ {
+ while (__last - __first > __sort_threshold)
+ {
+ if (__depth_limit == 0)
+ {
+ __detail::__partial_sort(__first, __last, __last, __comp);
+ return;
+ }
+ --__depth_limit;
+ _Iter __cut = __detail::__unguarded_partition_pivot(__first, __last, __comp);
+ __detail::__introsort_loop(__cut, __last, __depth_limit, __comp);
+ __last = __cut;
+ }
+ }
+ } // namespace __detail
+
struct __sort_fn
{
template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -1818,10 +2486,21 @@ namespace ranges
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
- auto __lasti = ranges::next(__first, __last);
- _GLIBCXX_STD_A::sort(std::move(__first), __lasti,
- __detail::__make_comp_proj(__comp, __proj));
- return __lasti;
+ if constexpr (!same_as<_Iter, _Sent>)
+ return (*this)(__first, ranges::next(__first, __last),
+ std::move(__comp), std::move(__proj));
+ else
+ {
+ if (__first != __last)
+ {
+ auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
+ auto __n = __detail::__to_unsigned_like(__last - __first);
+ unsigned __depth_limit = (std::__bit_width(__n) - 1) * 2;
+ __detail::__introsort_loop(__first, __last, __depth_limit, __comp_proj);
+ __detail::__final_insertion_sort(__first, __last, __comp_proj);
+ }
+ return __last;
+ }
}
template<random_access_range _Range,
@@ -1837,6 +2516,169 @@ namespace ranges
inline constexpr __sort_fn sort{};
+ namespace __detail
+ {
+ // This is a helper function for the __merge_sort_loop routines.
+ template<typename _Iter, typename _Out, typename _Comp>
+ _Out
+ __move_merge(_Iter __first1, _Iter __last1,
+ _Iter __first2, _Iter __last2,
+ _Out __result, _Comp __comp)
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ {
+ if (__comp(*__first2, *__first1))
+ {
+ *__result = ranges::iter_move(__first2);
+ ++__first2;
+ }
+ else
+ {
+ *__result = ranges::iter_move(__first1);
+ ++__first1;
+ }
+ ++__result;
+ }
+ return ranges::move(__first2, __last2,
+ ranges::move(__first1, __last1, __result).out).out;
+ }
+
+ template<typename _Iter, typename _Out, typename _Distance, typename _Comp>
+ void
+ __merge_sort_loop(_Iter __first, _Iter __last, _Out __result,
+ _Distance __step_size, _Comp __comp)
+ {
+ const _Distance __two_step = 2 * __step_size;
+
+ while (__last - __first >= __two_step)
+ {
+ __result = __detail::__move_merge(__first, __first + __step_size,
+ __first + __step_size,
+ __first + __two_step,
+ __result, __comp);
+ __first += __two_step;
+ }
+ __step_size = ranges::min(_Distance(__last - __first), __step_size);
+
+ __detail::__move_merge(__first, __first + __step_size,
+ __first + __step_size, __last, __result, __comp);
+ }
+
+ template<typename _Iter, typename _Distance, typename _Compare>
+ constexpr void
+ __chunk_insertion_sort(_Iter __first, _Iter __last,
+ _Distance __chunk_size, _Compare __comp)
+ {
+ while (__last - __first >= __chunk_size)
+ {
+ __detail::__insertion_sort(__first, __first + __chunk_size, __comp);
+ __first += __chunk_size;
+ }
+ __detail::__insertion_sort(__first, __last, __comp);
+ }
+
+ template<typename _Iter, typename _Pointer, typename _Comp>
+ void
+ __merge_sort_with_buffer(_Iter __first, _Iter __last,
+ _Pointer __buffer, _Comp __comp)
+ {
+ using _Distance = iter_difference_t<_Iter>;
+
+ const _Distance __len = __last - __first;
+ const _Pointer __buffer_last = __buffer + ptrdiff_t(__len);
+
+ constexpr int __chunk_size = 7;
+ _Distance __step_size = __chunk_size;
+ __detail::__chunk_insertion_sort(__first, __last, __step_size, __comp);
+
+ while (__step_size < __len)
+ {
+ __detail::__merge_sort_loop(__first, __last, __buffer,
+ __step_size, __comp);
+ __step_size *= 2;
+ __detail::__merge_sort_loop(__buffer, __buffer_last, __first,
+ ptrdiff_t(__step_size), __comp);
+ __step_size *= 2;
+ }
+ }
+
+ template<typename _Iter, typename _Pointer, typename _Comp>
+ void
+ __merge_adaptive(_Iter __first, _Iter __middle, _Iter __last,
+ iter_difference_t<_Iter> __len1,
+ iter_difference_t<_Iter> __len2,
+ _Pointer __buffer, _Comp __comp); // defined near inplace_merge
+
+ template<typename _Iter, typename _Distance, typename _Pointer, typename _Comp>
+ void
+ __merge_adaptive_resize(_Iter __first, _Iter __middle, _Iter __last,
+ _Distance __len1, _Distance __len2,
+ _Pointer __buffer, _Distance __buffer_size,
+ _Comp __comp); // defined near inplace_merge
+
+ template<typename _Iter, typename _Distance, typename _Comp>
+ constexpr void
+ __merge_without_buffer(_Iter __first, _Iter __middle, _Iter __last,
+ _Distance __len1, _Distance __len2,
+ _Comp __comp); // defined near inplace_merge
+
+ template<typename _Iter, typename _Pointer, typename _Comp>
+ void
+ __stable_sort_adaptive(_Iter __first, _Iter __middle, _Iter __last,
+ _Pointer __buffer, _Comp __comp)
+ {
+ __detail::__merge_sort_with_buffer(__first, __middle, __buffer, __comp);
+ __detail::__merge_sort_with_buffer(__middle, __last, __buffer, __comp);
+
+ __detail::__merge_adaptive(__first, __middle, __last,
+ __middle - __first, __last - __middle,
+ __buffer, __comp);
+ }
+
+ template<typename _Iter, typename _Pointer, typename _Distance, typename _Comp>
+ void
+ __stable_sort_adaptive_resize(_Iter __first, _Iter __last,
+ _Pointer __buffer, _Distance __buffer_size,
+ _Comp __comp)
+ {
+ const _Distance __len = (__last - __first + 1) / 2;
+ const _Iter __middle = __first + __len;
+ if (__len > __buffer_size)
+ {
+ __detail::__stable_sort_adaptive_resize(__first, __middle, __buffer,
+ __buffer_size, __comp);
+ __detail::__stable_sort_adaptive_resize(__middle, __last, __buffer,
+ __buffer_size, __comp);
+ __detail::__merge_adaptive_resize(__first, __middle, __last,
+ _Distance(__middle - __first),
+ _Distance(__last - __middle),
+ __buffer, __buffer_size,
+ __comp);
+ }
+ else
+ __detail::__stable_sort_adaptive(__first, __middle, __last,
+ __buffer, __comp);
+ }
+
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __inplace_stable_sort(_Iter __first, _Iter __last, _Comp __comp)
+ {
+ if (__last - __first < 15)
+ {
+ __detail::__insertion_sort(__first, __last, __comp);
+ return;
+ }
+ _Iter __middle = __first + (__last - __first) / 2;
+ __detail::__inplace_stable_sort(__first, __middle, __comp);
+ __detail::__inplace_stable_sort(__middle, __last, __comp);
+ __detail::__merge_without_buffer(__first, __middle, __last,
+ __middle - __first,
+ __last - __middle,
+ __comp);
+ }
+ } // namespace __detail
+
struct __stable_sort_fn
{
template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -1847,10 +2689,46 @@ namespace ranges
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
- auto __lasti = ranges::next(__first, __last);
- std::stable_sort(std::move(__first), __lasti,
- __detail::__make_comp_proj(__comp, __proj));
- return __lasti;
+ if constexpr (!same_as<_Iter, _Sent>)
+ return (*this)(__first, ranges::next(__first, __last),
+ std::move(__comp), std::move(__proj));
+ else
+ {
+ using _DistanceType = iter_difference_t<_Iter>;
+
+ if (__first == __last)
+ return __last;
+
+ auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
+
+#if _GLIBCXX_HOSTED
+# if __glibcxx_constexpr_algorithms >= 202306L // >= C++26
+ if consteval {
+ __detail::__inplace_stable_sort(__first, __last, __comp_proj);
+ return __last;
+ }
+# endif
+
+ typedef _Temporary_buffer<_Iter, iter_value_t<_Iter>> _TmpBuf;
+ // __stable_sort_adaptive sorts the range in two halves,
+ // so the buffer only needs to fit half the range at once.
+ _TmpBuf __buf(__first, ptrdiff_t((__last - __first + 1) / 2));
+
+ if (__buf._M_requested_size() == __buf.size()) [[likely]]
+ __detail::__stable_sort_adaptive(__first,
+ __first + _DistanceType(__buf.size()),
+ __last, __buf.begin(), __comp_proj);
+ else if (__buf.begin()) [[unlikely]]
+ __detail::__inplace_stable_sort(__first, __last, __comp_proj);
+ else
+ __detail::__stable_sort_adaptive_resize(__first, __last, __buf.begin(),
+ _DistanceType(__buf.size()),
+ __comp_proj);
+#else
+ __detail::__inplace_stable_sort(__first, __last, __comp_proj);
+#endif
+ return __last;
+ }
}
template<random_access_range _Range,
@@ -1887,7 +2765,7 @@ namespace ranges
std::__invoke(__proj, *__first)))
{
ranges::pop_heap(__first, __middle, __comp, __proj);
- ranges::iter_swap(__middle-1, __i);
+ ranges::iter_swap(std::prev(__middle), __i);
ranges::push_heap(__first, __middle, __comp, __proj);
}
ranges::sort_heap(__first, __middle, __comp, __proj);
@@ -1954,7 +2832,7 @@ namespace ranges
{
ranges::pop_heap(__result_first, __result_real_last,
__comp, __proj2);
- *(__result_real_last-1) = *__first;
+ *ranges::prev(__result_real_last) = *__first;
ranges::push_heap(__result_first, __result_real_last,
__comp, __proj2);
}
@@ -1991,7 +2869,7 @@ namespace ranges
typename _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>>
_Comp = ranges::less>
- constexpr _Iter
+ [[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2010,7 +2888,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
- constexpr borrowed_iterator_t<_Range>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -2026,7 +2904,7 @@ namespace ranges
typename _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>>
_Comp = ranges::less>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2045,7 +2923,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -2055,6 +2933,34 @@ namespace ranges
inline constexpr __is_sorted_fn is_sorted{};
+ namespace __detail
+ {
+ template<typename _Iter, typename _Comp>
+ constexpr void
+ __introselect(_Iter __first, _Iter __nth, _Iter __last,
+ iter_difference_t<_Iter> __depth_limit, _Comp __comp)
+ {
+ while (__last - __first > 3)
+ {
+ if (__depth_limit == 0)
+ {
+ __detail::__heap_select(__first, ranges::next(__nth), __last,
+ __comp);
+ // Place the nth largest element in its final position.
+ ranges::iter_swap(__first, __nth);
+ return;
+ }
+ --__depth_limit;
+ _Iter __cut = __detail::__unguarded_partition_pivot(__first, __last, __comp);
+ if (__cut <= __nth)
+ __first = __cut;
+ else
+ __last = __cut;
+ }
+ __detail::__insertion_sort(__first, __last, __comp);
+ }
+ } // namespace __detail
+
struct __nth_element_fn
{
template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -2064,11 +2970,21 @@ namespace ranges
operator()(_Iter __first, _Iter __nth, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
- auto __lasti = ranges::next(__first, __last);
- _GLIBCXX_STD_A::nth_element(std::move(__first), std::move(__nth),
- __lasti,
- __detail::__make_comp_proj(__comp, __proj));
- return __lasti;
+ if constexpr (!same_as<_Iter, _Sent>)
+ return (*this)(__first, __nth, ranges::next(__first, __last),
+ std::move(__comp), std::move(__proj));
+ else
+ {
+ if (__first == __last || __nth == __last)
+ return __last;
+
+ auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
+ auto __n = __detail::__to_unsigned_like(__last - __first);
+ __detail::__introselect(__first, __nth, __last,
+ std::__bit_width(__n) * 2,
+ __comp_proj);
+ return __last;
+ }
}
template<random_access_range _Range,
@@ -2092,7 +3008,7 @@ namespace ranges
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
- constexpr _Iter
+ [[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2122,7 +3038,7 @@ namespace ranges
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
- constexpr borrowed_iterator_t<_Range>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2140,7 +3056,7 @@ namespace ranges
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
- constexpr _Iter
+ [[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2170,7 +3086,7 @@ namespace ranges
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
- constexpr borrowed_iterator_t<_Range>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2188,7 +3104,7 @@ namespace ranges
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
- constexpr subrange<_Iter>
+ [[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2233,7 +3149,7 @@ namespace ranges
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
- constexpr borrowed_subrange_t<_Range>
+ [[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, const _Tp& __value,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2251,7 +3167,7 @@ namespace ranges
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2269,7 +3185,7 @@ namespace ranges
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {},
_Proj __proj = {}) const
{
@@ -2285,7 +3201,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -2301,7 +3217,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -2383,6 +3299,80 @@ namespace ranges
inline constexpr __partition_fn partition{};
#if _GLIBCXX_HOSTED
+ namespace __detail
+ {
+ // Like find_if_not(), but uses and updates a count of the
+ // remaining range length instead of comparing against an end
+ // iterator.
+ template<typename _Iter, typename _Pred, typename _Distance>
+ constexpr _Iter
+ __find_if_not_n(_Iter __first, _Distance& __len, _Pred __pred)
+ {
+ for (; __len; --__len, (void) ++__first)
+ if (!__pred(*__first))
+ break;
+ return __first;
+ }
+
+ template<typename _Iter, typename _Sent, typename _Pointer,
+ typename _Pred, typename _Distance>
+ constexpr subrange<_Iter>
+ __stable_partition_adaptive(_Iter __first, _Sent __last,
+ _Pred __pred, _Distance __len,
+ _Pointer __buffer,
+ _Distance __buffer_size)
+ {
+ if (__len == 1)
+ return {__first, ranges::next(__first, 1)};
+
+ if (__len <= __buffer_size)
+ {
+ _Iter __result1 = __first;
+ _Pointer __result2 = __buffer;
+
+ // The precondition guarantees that !__pred(__first), so
+ // move that element to the buffer before starting the loop.
+ // This ensures that we only call __pred once per element.
+ *__result2 = ranges::iter_move(__first);
+ ++__result2;
+ ++__first;
+ for (; __first != __last; ++__first)
+ if (__pred(*__first))
+ {
+ *__result1 = ranges::iter_move(__first);
+ ++__result1;
+ }
+ else
+ {
+ *__result2 = ranges::iter_move(__first);
+ ++__result2;
+ }
+
+ ranges::move(__buffer, __result2, __result1);
+ return {__result1, __first};
+ }
+
+ _Iter __middle = __first;
+ ranges::advance(__middle, __len / 2);
+ _Iter __left_split
+ = __detail::__stable_partition_adaptive(__first, __middle, __pred,
+ __len / 2, __buffer,
+ __buffer_size).begin();
+
+ // Advance past true-predicate values to satisfy this
+ // function's preconditions.
+ _Distance __right_len = __len - __len / 2;
+ _Iter __right_split = __detail::__find_if_not_n(__middle, __right_len, __pred);
+
+ if (__right_len)
+ __right_split
+ = __detail::__stable_partition_adaptive(__right_split, __last, __pred,
+ __right_len, __buffer, __buffer_size).begin();
+
+ return ranges::rotate(__left_split, __middle, __right_split);
+ }
+ } // namespace __detail
+
struct __stable_partition_fn
{
template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -2394,11 +3384,33 @@ namespace ranges
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
- auto __lasti = ranges::next(__first, __last);
- auto __middle
- = std::stable_partition(std::move(__first), __lasti,
- __detail::__make_pred_proj(__pred, __proj));
- return {std::move(__middle), std::move(__lasti)};
+ __first = ranges::find_if_not(__first, __last, __pred, __proj);
+
+ if (__first == __last)
+ return {__first, __first};
+
+ using _DistanceType = iter_difference_t<_Iter>;
+ const _DistanceType __len = ranges::distance(__first, __last);
+
+ auto __pred_proj = __detail::__make_pred_proj(__pred, __proj);
+
+#if __glibcxx_constexpr_algorithms >= 202306L // >= C++26
+ if consteval {
+ // Simulate a _Temporary_buffer of length 1:
+ iter_value_t<_Iter> __buf = ranges::iter_move(__first);
+ *__first = std::move(__buf);
+ return __detail::__stable_partition_adaptive(__first, __last,
+ __pred_proj,
+ __len, &__buf,
+ _DistanceType(1));
+ }
+#endif
+
+ _Temporary_buffer<_Iter, iter_value_t<_Iter>> __buf(__first, ptrdiff_t(__len));
+ return __detail::__stable_partition_adaptive(__first, __last,
+ __pred_proj,
+ __len, __buf.begin(),
+ _DistanceType(__buf.size()));
}
template<bidirectional_range _Range, typename _Proj = identity,
@@ -2497,7 +3509,7 @@ namespace ranges
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- constexpr _Iter
+ [[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -2523,7 +3535,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
- constexpr borrowed_iterator_t<_Range>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -2594,6 +3606,215 @@ namespace ranges
inline constexpr __merge_fn merge{};
+ namespace __detail
+ {
+ template<typename _Iter1, typename _Iter2, typename _Out, typename _Comp>
+ void
+ __move_merge_adaptive(_Iter1 __first1, _Iter1 __last1,
+ _Iter2 __first2, _Iter2 __last2,
+ _Out __result, _Comp __comp)
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ {
+ if (__comp(*__first2, *__first1))
+ {
+ *__result = ranges::iter_move(__first2);
+ ++__first2;
+ }
+ else
+ {
+ *__result = ranges::iter_move(__first1);
+ ++__first1;
+ }
+ ++__result;
+ }
+ if (__first1 != __last1)
+ ranges::move(__first1, __last1, __result);
+ }
+
+ template<typename _Iter1, typename _Iter2, typename _Iter3, typename _Comp>
+ void
+ __move_merge_adaptive_backward(_Iter1 __first1, _Iter1 __last1,
+ _Iter2 __first2, _Iter2 __last2,
+ _Iter3 __result, _Comp __comp)
+ {
+ if (__first1 == __last1)
+ {
+ ranges::move_backward(__first2, __last2, __result);
+ return;
+ }
+ else if (__first2 == __last2)
+ return;
+
+ --__last1;
+ --__last2;
+ while (true)
+ {
+ if (__comp(*__last2, *__last1))
+ {
+ *--__result = ranges::iter_move(__last1);
+ if (__first1 == __last1)
+ {
+ ranges::move_backward(__first2, ++__last2, __result);
+ return;
+ }
+ --__last1;
+ }
+ else
+ {
+ *--__result = ranges::iter_move(__last2);
+ if (__first2 == __last2)
+ return;
+ --__last2;
+ }
+ }
+ }
+
+ template<typename _Iter1, typename _Iter2>
+ _Iter1
+ __rotate_adaptive(_Iter1 __first, _Iter1 __middle, _Iter1 __last,
+ iter_difference_t<_Iter1> __len1,
+ iter_difference_t<_Iter1> __len2,
+ _Iter2 __buffer,
+ iter_difference_t<_Iter1> __buffer_size)
+ {
+ _Iter2 __buffer_end;
+ if (__len1 > __len2 && __len2 <= __buffer_size)
+ {
+ if (__len2)
+ {
+ __buffer_end = ranges::move(__middle, __last, __buffer).out;
+ ranges::move_backward(__first, __middle, __last);
+ return ranges::move(__buffer, __buffer_end, __first).out;
+ }
+ else
+ return __first;
+ }
+ else if (__len1 <= __buffer_size)
+ {
+ if (__len1)
+ {
+ __buffer_end = ranges::move(__first, __middle, __buffer).out;
+ ranges::move(__middle, __last, __first);
+ return ranges::move_backward(__buffer, __buffer_end, __last).out;
+ }
+ else
+ return __last;
+ }
+ else
+ return ranges::rotate(__first, __middle, __last).begin();
+ }
+
+ template<typename _Iter, typename _Pointer, typename _Comp>
+ void
+ __merge_adaptive(_Iter __first, _Iter __middle, _Iter __last,
+ iter_difference_t<_Iter> __len1,
+ iter_difference_t<_Iter> __len2,
+ _Pointer __buffer, _Comp __comp)
+ {
+ if (__len1 <= __len2)
+ {
+ _Pointer __buffer_end = ranges::move(__first, __middle, __buffer).out;
+ __detail::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last,
+ __first, __comp);
+ }
+ else
+ {
+ _Pointer __buffer_end = ranges::move(__middle, __last, __buffer).out;
+ __detail::__move_merge_adaptive_backward(__first, __middle, __buffer,
+ __buffer_end, __last, __comp);
+ }
+ }
+
+ template<typename _Iter, typename _Distance, typename _Pointer, typename _Comp>
+ void
+ __merge_adaptive_resize(_Iter __first, _Iter __middle, _Iter __last,
+ _Distance __len1, _Distance __len2,
+ _Pointer __buffer, _Distance __buffer_size,
+ _Comp __comp)
+ {
+ if (__len1 <= __buffer_size || __len2 <= __buffer_size)
+ __detail::__merge_adaptive(__first, __middle, __last,
+ __len1, __len2, __buffer, __comp);
+ else
+ {
+ _Iter __first_cut = __first;
+ _Iter __second_cut = __middle;
+ _Distance __len11 = 0;
+ _Distance __len22 = 0;
+ if (__len1 > __len2)
+ {
+ __len11 = __len1 / 2;
+ ranges::advance(__first_cut, __len11);
+ __second_cut = ranges::lower_bound(__middle, __last, *__first_cut,
+ __comp);
+ __len22 = ranges::distance(__middle, __second_cut);
+ }
+ else
+ {
+ __len22 = __len2 / 2;
+ ranges::advance(__second_cut, __len22);
+ __first_cut = ranges::upper_bound(__first, __middle, *__second_cut,
+ __comp);
+ __len11 = ranges::distance(__first, __first_cut);
+ }
+
+ _Iter __new_middle
+ = __detail::__rotate_adaptive(__first_cut, __middle, __second_cut,
+ _Distance(__len1 - __len11), __len22,
+ __buffer, __buffer_size);
+ __detail::__merge_adaptive_resize(__first, __first_cut, __new_middle,
+ __len11, __len22,
+ __buffer, __buffer_size, __comp);
+ __detail::__merge_adaptive_resize(__new_middle, __second_cut, __last,
+ _Distance(__len1 - __len11),
+ _Distance(__len2 - __len22),
+ __buffer, __buffer_size, __comp);
+ }
+ }
+
+ template<typename _Iter, typename _Distance, typename _Comp>
+ constexpr void
+ __merge_without_buffer(_Iter __first, _Iter __middle, _Iter __last,
+ _Distance __len1, _Distance __len2, _Comp __comp)
+ {
+ if (__len1 == 0 || __len2 == 0)
+ return;
+
+ if (__len1 + __len2 == 2)
+ {
+ if (__comp(*__middle, *__first))
+ ranges::iter_swap(__first, __middle);
+ return;
+ }
+
+ _Iter __first_cut = __first;
+ _Iter __second_cut = __middle;
+ _Distance __len11 = 0;
+ _Distance __len22 = 0;
+ if (__len1 > __len2)
+ {
+ __len11 = __len1 / 2;
+ ranges::advance(__first_cut, __len11);
+ __second_cut = ranges::lower_bound(__middle, __last, *__first_cut, __comp);
+ __len22 = ranges::distance(__middle, __second_cut);
+ }
+ else
+ {
+ __len22 = __len2 / 2;
+ ranges::advance(__second_cut, __len22);
+ __first_cut = ranges::upper_bound(__first, __middle, *__second_cut, __comp);
+ __len11 = ranges::distance(__first, __first_cut);
+ }
+
+ _Iter __new_middle = ranges::rotate(__first_cut, __middle, __second_cut).begin();
+ __detail::__merge_without_buffer(__first, __first_cut, __new_middle,
+ __len11, __len22, __comp);
+ __detail::__merge_without_buffer(__new_middle, __second_cut, __last,
+ __len1 - __len11, __len2 - __len22, __comp);
+ }
+ } // namespace __detail
+
struct __inplace_merge_fn
{
template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -2605,10 +3826,50 @@ namespace ranges
operator()(_Iter __first, _Iter __middle, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
- auto __lasti = ranges::next(__first, __last);
- std::inplace_merge(std::move(__first), std::move(__middle), __lasti,
- __detail::__make_comp_proj(__comp, __proj));
- return __lasti;
+ if constexpr (!same_as<_Iter, _Sent>)
+ return (*this)(__first, __middle, ranges::next(__middle, __last),
+ std::move(__comp), std::move(__proj));
+ else
+ {
+ using _DistanceType = iter_difference_t<_Iter>;
+
+ if (__first == __middle || __middle == __last)
+ return __last;
+
+ const _DistanceType __len1 = ranges::distance(__first, __middle);
+ const _DistanceType __len2 = ranges::distance(__middle, __last);
+
+ auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
+
+#if _GLIBCXX_HOSTED
+# if __glibcxx_constexpr_algorithms >= 202306L // >= C++26
+ if consteval {
+ __detail::__merge_without_buffer(__first, __middle, __last,
+ __len1, __len2, __comp_proj);
+ return __last;
+ }
+# endif
+ using _TmpBuf = _Temporary_buffer<_Iter, iter_value_t<_Iter>>;
+ // __merge_adaptive will use a buffer for the smaller of
+ // [first,middle) and [middle,last).
+ _TmpBuf __buf(__first, ptrdiff_t(ranges::min(__len1, __len2)));
+
+ if (__buf.size() == __buf._M_requested_size()) [[likely]]
+ __detail::__merge_adaptive
+ (__first, __middle, __last, __len1, __len2, __buf.begin(), __comp_proj);
+ else if (__buf.begin() == 0) [[unlikely]]
+ __detail::__merge_without_buffer
+ (__first, __middle, __last, __len1, __len2, __comp_proj);
+ else
+ __detail::__merge_adaptive_resize
+ (__first, __middle, __last, __len1, __len2, __buf.begin(),
+ _DistanceType(__buf.size()), __comp_proj);
+#else
+ __detail::__merge_without_buffer
+ (__first, __middle, __last, __len1, __len2, __comp_proj);
+#endif
+ return __last;
+ }
}
template<bidirectional_range _Range,
@@ -2635,7 +3896,7 @@ namespace ranges
indirect_strict_weak_order<projected<_Iter1, _Proj1>,
projected<_Iter2, _Proj2>>
_Comp = ranges::less>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Comp __comp = {},
@@ -2664,7 +3925,7 @@ namespace ranges
indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
projected<iterator_t<_Range2>, _Proj2>>
_Comp = ranges::less>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -2935,7 +4196,7 @@ namespace ranges
template<typename _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
- constexpr const _Tp&
+ [[nodiscard]] constexpr const _Tp&
operator()(const _Tp& __a, const _Tp& __b,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2952,13 +4213,13 @@ namespace ranges
_Comp = ranges::less>
requires indirectly_copyable_storable<iterator_t<_Range>,
range_value_t<_Range>*>
- constexpr range_value_t<_Range>
+ [[nodiscard]] constexpr range_value_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
auto __first = ranges::begin(__r);
auto __last = ranges::end(__r);
__glibcxx_assert(__first != __last);
- auto __result = *__first;
+ range_value_t<_Range> __result(*__first);
while (++__first != __last)
{
auto&& __tmp = *__first;
@@ -2973,7 +4234,7 @@ namespace ranges
template<copyable _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
- constexpr _Tp
+ [[nodiscard]] constexpr _Tp
operator()(initializer_list<_Tp> __r,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2989,7 +4250,7 @@ namespace ranges
template<typename _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp
= ranges::less>
- constexpr const _Tp&
+ [[nodiscard]] constexpr const _Tp&
operator()(const _Tp& __val, const _Tp& __lo, const _Tp& __hi,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3039,7 +4300,7 @@ namespace ranges
template<typename _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
- constexpr minmax_result<const _Tp&>
+ [[nodiscard]] constexpr minmax_result<const _Tp&>
operator()(const _Tp& __a, const _Tp& __b,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3055,7 +4316,7 @@ namespace ranges
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
requires indirectly_copyable_storable<iterator_t<_Range>, range_value_t<_Range>*>
- constexpr minmax_result<range_value_t<_Range>>
+ [[nodiscard]] constexpr minmax_result<range_value_t<_Range>>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
auto __first = ranges::begin(__r);
@@ -3114,7 +4375,7 @@ namespace ranges
template<copyable _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
- constexpr minmax_result<_Tp>
+ [[nodiscard]] constexpr minmax_result<_Tp>
operator()(initializer_list<_Tp> __r,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3131,7 +4392,7 @@ namespace ranges
typename _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>>
_Comp = ranges::less>
- constexpr _Iter
+ [[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3152,7 +4413,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
- constexpr borrowed_iterator_t<_Range>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -3168,7 +4429,7 @@ namespace ranges
typename _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>>
_Comp = ranges::less>
- constexpr _Iter
+ [[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3189,7 +4450,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
- constexpr borrowed_iterator_t<_Range>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -3208,7 +4469,7 @@ namespace ranges
typename _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>>
_Comp = ranges::less>
- constexpr minmax_element_result<_Iter>
+ [[nodiscard]] constexpr minmax_element_result<_Iter>
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3263,7 +4524,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
- constexpr minmax_element_result<borrowed_iterator_t<_Range>>
+ [[nodiscard]] constexpr minmax_element_result<borrowed_iterator_t<_Range>>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -3281,7 +4542,7 @@ namespace ranges
indirect_strict_weak_order<projected<_Iter1, _Proj1>,
projected<_Iter2, _Proj2>>
_Comp = ranges::less>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Comp __comp = {},
@@ -3367,7 +4628,7 @@ namespace ranges
indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
projected<iterator_t<_Range2>, _Proj2>>
_Comp = ranges::less>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -3596,7 +4857,7 @@ namespace ranges
typename _Proj = identity,
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*>
- constexpr subrange<_Iter>
+ [[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const
{
if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>)
@@ -3629,7 +4890,7 @@ namespace ranges
typename _Tp
_GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj)>
requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp*>
- constexpr borrowed_subrange_t<_Range>
+ [[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
{ return (*this)(ranges::begin(__r), ranges::end(__r), __value, std::move(__proj)); }
};
@@ -3640,7 +4901,7 @@ namespace ranges
{
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- constexpr subrange<_Iter>
+ [[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const
{
if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>)
@@ -3671,7 +4932,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
- constexpr borrowed_subrange_t<_Range>
+ [[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{ return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__pred), std::move(__proj)); }
};
@@ -3682,7 +4943,7 @@ namespace ranges
{
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- constexpr subrange<_Iter>
+ [[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const
{
if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>)
@@ -3713,7 +4974,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
- constexpr borrowed_subrange_t<_Range>
+ [[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{ return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__pred), std::move(__proj)); }
};
@@ -3978,6 +5239,7 @@ namespace ranges
#endif // __glibcxx_ranges_fold
} // namespace ranges
+#if __glibcxx_shift >= 201806L // C++ >= 20
template<typename _ForwardIterator>
constexpr _ForwardIterator
shift_left(_ForwardIterator __first, _ForwardIterator __last,
@@ -4068,6 +5330,120 @@ namespace ranges
}
}
}
+#endif
+
+namespace ranges
+{
+#if __glibcxx_shift >= 202202L // C++ >= 23
+ struct __shift_left_fn
+ {
+ template<permutable _Iter, sentinel_for<_Iter> _Sent>
+ constexpr subrange<_Iter>
+ operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __n) const
+ {
+ __glibcxx_assert(__n >= 0);
+ if (__n == 0)
+ return {__first, ranges::next(__first, __last)};
+
+ auto __mid = ranges::next(__first, __n, __last);
+ if (__mid == __last)
+ return {__first, __first};
+ return {__first, ranges::move(__mid, __last, __first).out};
+ }
+
+ template<forward_range _Range>
+ requires permutable<iterator_t<_Range>>
+ constexpr borrowed_subrange_t<_Range>
+ operator()(_Range&& __r, range_difference_t<_Range> __n) const
+ { return (*this)(ranges::begin(__r), ranges::end(__r), __n); }
+ };
+
+ inline constexpr __shift_left_fn shift_left{};
+
+ struct __shift_right_fn
+ {
+ template<permutable _Iter, sentinel_for<_Iter> _Sent>
+ constexpr subrange<_Iter>
+ operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __n) const
+ {
+ __glibcxx_assert(__n >= 0);
+ if (__n == 0)
+ return {__first, ranges::next(__first, __last)};
+
+ if constexpr (bidirectional_iterator<_Iter> && same_as<_Iter, _Sent>)
+ {
+ auto __mid = ranges::next(__last, -__n, __first);
+ if (__mid == __first)
+ return {__last, __last};
+
+ return {ranges::move_backward(__first, __mid, __last).out, __last};
+ }
+ else
+ {
+ auto __result = ranges::next(__first, __n, __last);
+ if (__result == __last)
+ return {__result, __result};
+
+ auto __dest_head = __first, __dest_tail = __result;
+ while (__dest_head != __result)
+ {
+ if (__dest_tail == __last)
+ {
+ // If we get here, then we must have
+ // 2*n >= distance(__first, __last)
+ // i.e. we are shifting out at least half of the range. In
+ // this case we can safely perform the shift with a single
+ // move.
+ auto __lasti = ranges::move(__first, __dest_head, __result).out;
+ // __glibcxx_assert(__lasti == __last);
+ return {__result, __lasti};
+ }
+ ++__dest_head;
+ ++__dest_tail;
+ }
+
+ for (;;)
+ {
+ // At the start of each iteration of this outer loop, the range
+ // [__first, __result) contains those elements that after shifting
+ // the whole range right by __n, should end up in
+ // [__dest_head, __dest_tail) in order.
+
+ // The below inner loop swaps the elements of [__first, __result)
+ // and [__dest_head, __dest_tail), while simultaneously shifting
+ // the latter range by __n.
+ auto __cursor = __first;
+ while (__cursor != __result)
+ {
+ if (__dest_tail == __last)
+ {
+ // At this point the ranges [__first, result) and
+ // [__dest_head, dest_tail) are disjoint, so we can safely
+ // move the remaining elements.
+ __dest_head = ranges::move(__cursor, __result, __dest_head).out;
+ auto __lasti = ranges::move(__first, __cursor, __dest_head).out;
+ // __glibcxx_assert(__lasti == __last);
+ return {__result, __lasti};
+ }
+ ranges::iter_swap(__cursor, __dest_head);
+ ++__dest_head;
+ ++__dest_tail;
+ ++__cursor;
+ }
+ }
+ }
+ }
+
+ template<forward_range _Range>
+ requires permutable<iterator_t<_Range>>
+ constexpr borrowed_subrange_t<_Range>
+ operator()(_Range&& __r, range_difference_t<_Range> __n) const
+ { return (*this)(ranges::begin(__r), ranges::end(__r), __n); }
+ };
+
+ inline constexpr __shift_right_fn shift_right{};
+#endif // C++23
+} // namespace ranges
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h
index a08f659b..45ed5b4 100644
--- a/libstdc++-v3/include/bits/ranges_algobase.h
+++ b/libstdc++-v3/include/bits/ranges_algobase.h
@@ -101,7 +101,7 @@ namespace ranges
typename _Pred = ranges::equal_to,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -168,7 +168,7 @@ namespace ranges
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
_Pred, _Proj1, _Proj2>
- constexpr bool
+ [[nodiscard]] constexpr bool
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h
index 488907d..0b8151c 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -68,29 +68,22 @@ namespace ranges
namespace __detail
{
+ [[__gnu__::__always_inline__]]
constexpr __max_size_type
__to_unsigned_like(__max_size_type __t) noexcept
{ return __t; }
+ [[__gnu__::__always_inline__]]
constexpr __max_size_type
__to_unsigned_like(__max_diff_type __t) noexcept
{ return __max_size_type(__t); }
template<integral _Tp>
+ [[__gnu__::__always_inline__]]
constexpr auto
__to_unsigned_like(_Tp __t) noexcept
{ return static_cast<make_unsigned_t<_Tp>>(__t); }
-#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
- constexpr unsigned __int128
- __to_unsigned_like(__int128 __t) noexcept
- { return __t; }
-
- constexpr unsigned __int128
- __to_unsigned_like(unsigned __int128 __t) noexcept
- { return __t; }
-#endif
-
template<typename _Tp>
using __make_unsigned_like_t
= decltype(__detail::__to_unsigned_like(std::declval<_Tp>()));
@@ -113,23 +106,24 @@ namespace ranges
{
private:
template<typename _Tp>
- static constexpr bool
+ static consteval bool
_S_noexcept()
{
if constexpr (is_array_v<remove_reference_t<_Tp>>)
return true;
else if constexpr (__member_begin<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp&>().begin()));
+ return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().begin()));
else
- return noexcept(__decay_copy(begin(std::declval<_Tp&>())));
+ return noexcept(_GLIBCXX_AUTO_CAST(begin(std::declval<_Tp&>())));
}
public:
template<__maybe_borrowed_range _Tp>
requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
|| __adl_begin<_Tp>
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr auto
- operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
+ operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
{
if constexpr (is_array_v<remove_reference_t<_Tp>>)
{
@@ -146,7 +140,7 @@ namespace ranges
template<typename _Tp>
concept __member_end = requires(_Tp& __t)
{
- { __decay_copy(__t.end()) } -> sentinel_for<__range_iter_t<_Tp>>;
+ { _GLIBCXX_AUTO_CAST(__t.end()) } -> sentinel_for<__range_iter_t<_Tp>>;
};
// Poison pill so that unqualified lookup doesn't find std::end.
@@ -156,30 +150,31 @@ namespace ranges
concept __adl_end = __class_or_enum<remove_reference_t<_Tp>>
&& requires(_Tp& __t)
{
- { __decay_copy(end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>;
+ { _GLIBCXX_AUTO_CAST(end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>;
};
struct _End
{
private:
template<typename _Tp>
- static constexpr bool
+ static consteval bool
_S_noexcept()
{
if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
return true;
else if constexpr (__member_end<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp&>().end()));
+ return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().end()));
else
- return noexcept(__decay_copy(end(std::declval<_Tp&>())));
+ return noexcept(_GLIBCXX_AUTO_CAST(end(std::declval<_Tp&>())));
}
public:
template<__maybe_borrowed_range _Tp>
requires is_bounded_array_v<remove_reference_t<_Tp>>
|| __member_end<_Tp> || __adl_end<_Tp>
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr auto
- operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
+ operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
{
if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
{
@@ -196,7 +191,7 @@ namespace ranges
template<typename _Tp>
concept __member_rbegin = requires(_Tp& __t)
{
- { __decay_copy(__t.rbegin()) } -> input_or_output_iterator;
+ { _GLIBCXX_AUTO_CAST(__t.rbegin()) } -> input_or_output_iterator;
};
void rbegin() = delete;
@@ -205,7 +200,7 @@ namespace ranges
concept __adl_rbegin = __class_or_enum<remove_reference_t<_Tp>>
&& requires(_Tp& __t)
{
- { __decay_copy(rbegin(__t)) } -> input_or_output_iterator;
+ { _GLIBCXX_AUTO_CAST(rbegin(__t)) } -> input_or_output_iterator;
};
template<typename _Tp>
@@ -219,13 +214,13 @@ namespace ranges
{
private:
template<typename _Tp>
- static constexpr bool
+ static consteval bool
_S_noexcept()
{
if constexpr (__member_rbegin<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp&>().rbegin()));
+ return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().rbegin()));
else if constexpr (__adl_rbegin<_Tp>)
- return noexcept(__decay_copy(rbegin(std::declval<_Tp&>())));
+ return noexcept(_GLIBCXX_AUTO_CAST(rbegin(std::declval<_Tp&>())));
else
{
if constexpr (noexcept(_End{}(std::declval<_Tp&>())))
@@ -242,8 +237,9 @@ namespace ranges
public:
template<__maybe_borrowed_range _Tp>
requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp>
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr auto
- operator()[[nodiscard]](_Tp&& __t) const
+ operator()(_Tp&& __t) const
noexcept(_S_noexcept<_Tp&>())
{
if constexpr (__member_rbegin<_Tp>)
@@ -258,7 +254,7 @@ namespace ranges
template<typename _Tp>
concept __member_rend = requires(_Tp& __t)
{
- { __decay_copy(__t.rend()) }
+ { _GLIBCXX_AUTO_CAST(__t.rend()) }
-> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
};
@@ -268,7 +264,7 @@ namespace ranges
concept __adl_rend = __class_or_enum<remove_reference_t<_Tp>>
&& requires(_Tp& __t)
{
- { __decay_copy(rend(__t)) }
+ { _GLIBCXX_AUTO_CAST(rend(__t)) }
-> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
};
@@ -276,13 +272,13 @@ namespace ranges
{
private:
template<typename _Tp>
- static constexpr bool
+ static consteval bool
_S_noexcept()
{
if constexpr (__member_rend<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp&>().rend()));
+ return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().rend()));
else if constexpr (__adl_rend<_Tp>)
- return noexcept(__decay_copy(rend(std::declval<_Tp&>())));
+ return noexcept(_GLIBCXX_AUTO_CAST(rend(std::declval<_Tp&>())));
else
{
if constexpr (noexcept(_Begin{}(std::declval<_Tp&>())))
@@ -299,8 +295,9 @@ namespace ranges
public:
template<__maybe_borrowed_range _Tp>
requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp>
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr auto
- operator()[[nodiscard]](_Tp&& __t) const
+ operator()(_Tp&& __t) const
noexcept(_S_noexcept<_Tp&>())
{
if constexpr (__member_rend<_Tp>)
@@ -316,7 +313,7 @@ namespace ranges
concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>>
&& requires(_Tp& __t)
{
- { __decay_copy(__t.size()) } -> __detail::__is_integer_like;
+ { _GLIBCXX_AUTO_CAST(__t.size()) } -> __detail::__is_integer_like;
};
void size() = delete;
@@ -326,7 +323,7 @@ namespace ranges
&& !disable_sized_range<remove_cvref_t<_Tp>>
&& requires(_Tp& __t)
{
- { __decay_copy(size(__t)) } -> __detail::__is_integer_like;
+ { _GLIBCXX_AUTO_CAST(size(__t)) } -> __detail::__is_integer_like;
};
template<typename _Tp>
@@ -345,15 +342,15 @@ namespace ranges
{
private:
template<typename _Tp>
- static constexpr bool
+ static consteval bool
_S_noexcept()
{
if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
return true;
else if constexpr (__member_size<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp&>().size()));
+ return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().size()));
else if constexpr (__adl_size<_Tp>)
- return noexcept(__decay_copy(size(std::declval<_Tp&>())));
+ return noexcept(_GLIBCXX_AUTO_CAST(size(std::declval<_Tp&>())));
else if constexpr (__sentinel_size<_Tp>)
return noexcept(_End{}(std::declval<_Tp&>())
- _Begin{}(std::declval<_Tp&>()));
@@ -363,8 +360,9 @@ namespace ranges
template<typename _Tp>
requires is_bounded_array_v<remove_reference_t<_Tp>>
|| __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp>
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr auto
- operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
+ operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
{
if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
return extent_v<remove_reference_t<_Tp>>;
@@ -383,8 +381,9 @@ namespace ranges
// 3403. Domain of ranges::ssize(E) doesn't match ranges::size(E)
template<typename _Tp>
requires requires (_Tp& __t) { _Size{}(__t); }
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr auto
- operator()[[nodiscard]](_Tp&& __t) const noexcept(noexcept(_Size{}(__t)))
+ operator()(_Tp&& __t) const noexcept(noexcept(_Size{}(__t)))
{
auto __size = _Size{}(__t);
using __size_type = decltype(__size);
@@ -398,11 +397,6 @@ namespace ranges
else
return static_cast<make_signed_t<__size_type>>(__size);
}
-#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
- // For strict-ansi modes integral<__int128> is false
- else if constexpr (__detail::__is_int128<__size_type>)
- return static_cast<__int128>(__size);
-#endif
else // Must be one of __max_diff_type or __max_size_type.
return __detail::__max_diff_type(__size);
}
@@ -428,7 +422,7 @@ namespace ranges
{
private:
template<typename _Tp>
- static constexpr bool
+ static consteval bool
_S_noexcept()
{
if constexpr (__member_empty<_Tp>)
@@ -444,8 +438,9 @@ namespace ranges
template<typename _Tp>
requires __member_empty<_Tp> || __size0_empty<_Tp>
|| __eq_iter_empty<_Tp>
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr bool
- operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
+ operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
{
if constexpr (__member_empty<_Tp>)
return bool(__t.empty());
@@ -463,7 +458,7 @@ namespace ranges
template<typename _Tp>
concept __member_data = requires(_Tp& __t)
{
- { __decay_copy(__t.data()) } -> __pointer_to_object;
+ { _GLIBCXX_AUTO_CAST(__t.data()) } -> __pointer_to_object;
};
template<typename _Tp>
@@ -473,11 +468,11 @@ namespace ranges
{
private:
template<typename _Tp>
- static constexpr bool
+ static consteval bool
_S_noexcept()
{
if constexpr (__member_data<_Tp>)
- return noexcept(__decay_copy(std::declval<_Tp&>().data()));
+ return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().data()));
else
return noexcept(_Begin{}(std::declval<_Tp&>()));
}
@@ -485,8 +480,9 @@ namespace ranges
public:
template<__maybe_borrowed_range _Tp>
requires __member_data<_Tp> || __begin_data<_Tp>
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr auto
- operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
+ operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
{
if constexpr (__member_data<_Tp>)
return __t.data();
@@ -529,11 +525,7 @@ namespace ranges
using sentinel_t = decltype(ranges::end(std::declval<_Range&>()));
#if __glibcxx_ranges_as_const // >= C++23
- template<range _Range>
- using const_iterator_t = const_iterator<iterator_t<_Range>>;
-
- template<range _Range>
- using const_sentinel_t = const_sentinel<sentinel_t<_Range>>;
+ // const_iterator_t and const_sentinel_t defined below.
template<range _Range>
using range_const_reference_t = iter_const_reference_t<iterator_t<_Range>>;
@@ -647,6 +639,7 @@ namespace ranges
{
#if __glibcxx_ranges_as_const // >= C++23
template<input_range _Range>
+ [[__gnu__::__always_inline__]]
constexpr auto&
__possibly_const_range(_Range& __r) noexcept
{
@@ -660,6 +653,7 @@ namespace ranges
#else
// If _To is an lvalue-reference, return const _Tp&, otherwise const _Tp&&.
template<typename _To, typename _Tp>
+ [[__gnu__::__always_inline__]]
constexpr decltype(auto)
__as_const(_Tp& __t) noexcept
{
@@ -685,7 +679,7 @@ namespace ranges
(ranges::begin(__access::__possibly_const_range(__t))); }
{
auto& __r = __access::__possibly_const_range(__t);
- return const_iterator_t<decltype(__r)>(ranges::begin(__r));
+ return const_iterator<decltype(ranges::begin(__r))>(ranges::begin(__r));
}
#else
template<typename _Tp>
@@ -713,7 +707,7 @@ namespace ranges
(ranges::end(__access::__possibly_const_range(__t))); }
{
auto& __r = __access::__possibly_const_range(__t);
- return const_sentinel_t<decltype(__r)>(ranges::end(__r));
+ return const_sentinel<decltype(ranges::end(__r))>(ranges::end(__r));
}
#else
template<typename _Tp>
@@ -817,6 +811,16 @@ namespace ranges
inline constexpr ranges::__access::_CData cdata{};
}
+#if __glibcxx_ranges_as_const // >= C++23
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3946. The definition of const_iterator_t should be reworked
+ template<range _Range>
+ using const_iterator_t = decltype(ranges::cbegin(std::declval<_Range&>()));
+
+ template<range _Range>
+ using const_sentinel_t = decltype(ranges::cend(std::declval<_Range&>()));
+#endif
+
namespace __detail
{
template<typename _Tp>
@@ -894,10 +898,17 @@ namespace ranges
{
if constexpr (sized_sentinel_for<_Sent, _It>)
{
- const auto __diff = __bound - __it;
+ const iter_difference_t<_It> __diff = __bound - __it;
if (__diff == 0)
- return __n;
+ {
+ // inline any possible side effects of advance(it, bound)
+ if constexpr (assignable_from<_It&, _Sent>)
+ __it = std::move(__bound);
+ else if constexpr (random_access_iterator<_It>)
+ __it += iter_difference_t<_It>(0);
+ return __n;
+ }
else if (__diff > 0 ? __n >= __diff : __n <= __diff)
{
(*this)(__it, __bound);
@@ -912,9 +923,14 @@ namespace ranges
return 0;
}
else
- return 0;
+ {
+ // inline any possible side effects of advance(it, n)
+ if constexpr (random_access_iterator<_It>)
+ __it += iter_difference_t<_It>(0);
+ return 0;
+ }
}
- else if (__it == __bound || __n == 0)
+ else if (__n == 0 || __it == __bound)
return __n;
else if (__n > 0)
{
@@ -970,13 +986,13 @@ namespace ranges
}
template<typename _It, sized_sentinel_for<decay_t<_It>> _Sent>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr iter_difference_t<decay_t<_It>>
operator()(_It&& __first, _Sent __last) const
{ return __last - static_cast<const decay_t<_It>&>(__first); }
template<range _Range>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr range_difference_t<_Range>
operator()(_Range&& __r) const
{
@@ -994,7 +1010,7 @@ namespace ranges
struct __next_fn final
{
template<input_or_output_iterator _It>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr _It
operator()(_It __x) const
{
@@ -1003,7 +1019,7 @@ namespace ranges
}
template<input_or_output_iterator _It>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr _It
operator()(_It __x, iter_difference_t<_It> __n) const
{
@@ -1012,7 +1028,7 @@ namespace ranges
}
template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr _It
operator()(_It __x, _Sent __bound) const
{
@@ -1021,7 +1037,7 @@ namespace ranges
}
template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr _It
operator()(_It __x, iter_difference_t<_It> __n, _Sent __bound) const
{
@@ -1037,7 +1053,7 @@ namespace ranges
struct __prev_fn final
{
template<bidirectional_iterator _It>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr _It
operator()(_It __x) const
{
@@ -1046,7 +1062,7 @@ namespace ranges
}
template<bidirectional_iterator _It>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr _It
operator()(_It __x, iter_difference_t<_It> __n) const
{
@@ -1055,7 +1071,7 @@ namespace ranges
}
template<bidirectional_iterator _It>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr _It
operator()(_It __x, iter_difference_t<_It> __n, _It __bound) const
{
@@ -1103,11 +1119,11 @@ namespace __detail
// 4223. Deduction guides for maps are mishandling tuples and references
template<ranges::input_range _Range>
using __range_key_type
- = remove_const_t<tuple_element_t<0, ranges::range_value_t<_Range>>>;
+ = remove_cvref_t<tuple_element_t<0, ranges::range_value_t<_Range>>>;
template<ranges::input_range _Range>
using __range_mapped_type
- = tuple_element_t<1, ranges::range_value_t<_Range>>;
+ = remove_cvref_t<tuple_element_t<1, ranges::range_value_t<_Range>>>;
// The allocator's value_type for map-like containers.
template<ranges::input_range _Range>
diff --git a/libstdc++-v3/include/bits/ranges_cmp.h b/libstdc++-v3/include/bits/ranges_cmp.h
index cd5f7b8..a53cd56 100644
--- a/libstdc++-v3/include/bits/ranges_cmp.h
+++ b/libstdc++-v3/include/bits/ranges_cmp.h
@@ -46,11 +46,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// [func.identity] The identity function.
struct identity
{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++23-extensions" // static operator()
template<typename _Tp>
[[nodiscard]]
- constexpr _Tp&&
- operator()(_Tp&& __t) const noexcept
+ static constexpr _Tp&&
+ operator()(_Tp&& __t) noexcept
{ return std::forward<_Tp>(__t); }
+#pragma GCC diagnostic pop
using is_transparent = __is_transparent;
};
@@ -79,13 +82,15 @@ namespace ranges
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3530 BUILTIN-PTR-MEOW should not opt the type out of syntactic checks
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++23-extensions" // static operator()
/// ranges::equal_to function object type.
struct equal_to
{
template<typename _Tp, typename _Up>
requires equality_comparable_with<_Tp, _Up>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
+ static constexpr bool
+ operator()(_Tp&& __t, _Up&& __u)
noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>()))
{ return std::forward<_Tp>(__t) == std::forward<_Up>(__u); }
@@ -97,8 +102,8 @@ namespace ranges
{
template<typename _Tp, typename _Up>
requires equality_comparable_with<_Tp, _Up>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
+ static constexpr bool
+ operator()(_Tp&& __t, _Up&& __u)
noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>()))
{ return !equal_to{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
@@ -110,8 +115,8 @@ namespace ranges
{
template<typename _Tp, typename _Up>
requires totally_ordered_with<_Tp, _Up>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
+ static constexpr bool
+ operator()(_Tp&& __t, _Up&& __u)
noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>()))
{
if constexpr (__detail::__less_builtin_ptr_cmp<_Tp, _Up>)
@@ -137,8 +142,8 @@ namespace ranges
{
template<typename _Tp, typename _Up>
requires totally_ordered_with<_Tp, _Up>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
+ static constexpr bool
+ operator()(_Tp&& __t, _Up&& __u)
noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>()))
{ return less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); }
@@ -150,8 +155,8 @@ namespace ranges
{
template<typename _Tp, typename _Up>
requires totally_ordered_with<_Tp, _Up>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
+ static constexpr bool
+ operator()(_Tp&& __t, _Up&& __u)
noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>()))
{ return !less{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
@@ -163,13 +168,14 @@ namespace ranges
{
template<typename _Tp, typename _Up>
requires totally_ordered_with<_Tp, _Up>
- constexpr bool
- operator()(_Tp&& __t, _Up&& __u) const
+ static constexpr bool
+ operator()(_Tp&& __t, _Up&& __u)
noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>()))
{ return !less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); }
using is_transparent = __is_transparent;
};
+#pragma GCC diagnostic pop
} // namespace ranges
#endif // __glibcxx_ranges
diff --git a/libstdc++-v3/include/bits/ranges_uninitialized.h b/libstdc++-v3/include/bits/ranges_uninitialized.h
index 12a714b..3f9a07f 100644
--- a/libstdc++-v3/include/bits/ranges_uninitialized.h
+++ b/libstdc++-v3/include/bits/ranges_uninitialized.h
@@ -556,13 +556,12 @@ namespace ranges
__destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept
{
if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
- return ranges::next(std::move(__first), __last);
- else
- {
- for (; __first != __last; ++__first)
- ranges::destroy_at(std::__addressof(*__first));
- return __first;
- }
+ if (!is_constant_evaluated())
+ return ranges::next(std::move(__first), __last);
+
+ for (; __first != __last; ++__first)
+ ranges::destroy_at(std::__addressof(*__first));
+ return __first;
}
template<__detail::__nothrow_input_range _Range>
@@ -581,13 +580,12 @@ namespace ranges
operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept
{
if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
- return ranges::next(std::move(__first), __n);
- else
- {
- for (; __n > 0; ++__first, (void)--__n)
- ranges::destroy_at(std::__addressof(*__first));
- return __first;
- }
+ if (!is_constant_evaluated())
+ return ranges::next(std::move(__first), __n);
+
+ for (; __n > 0; ++__first, (void)--__n)
+ ranges::destroy_at(std::__addressof(*__first));
+ return __first;
}
};
diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h
index 53b7f5c..2aa8938 100644
--- a/libstdc++-v3/include/bits/ranges_util.h
+++ b/libstdc++-v3/include/bits/ranges_util.h
@@ -501,7 +501,7 @@ namespace ranges
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
requires indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>, const _Tp*>
- constexpr _Iter
+ [[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Proj __proj = {}) const
{
@@ -537,7 +537,7 @@ namespace ranges
requires indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp*>
- constexpr borrowed_iterator_t<_Range>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -552,7 +552,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- constexpr _Iter
+ [[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -565,7 +565,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
- constexpr borrowed_iterator_t<_Range>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -580,7 +580,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- constexpr _Iter
+ [[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -593,7 +593,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
- constexpr borrowed_iterator_t<_Range>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -634,7 +634,7 @@ namespace ranges
typename _Pred = ranges::equal_to,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
- constexpr mismatch_result<_Iter1, _Iter2>
+ [[nodiscard]] constexpr mismatch_result<_Iter1, _Iter2>
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -655,6 +655,7 @@ namespace ranges
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
_Pred, _Proj1, _Proj2>
+ [[nodiscard]]
constexpr mismatch_result<iterator_t<_Range1>, iterator_t<_Range2>>
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -675,7 +676,7 @@ namespace ranges
typename _Pred = ranges::equal_to,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
- constexpr subrange<_Iter1>
+ [[nodiscard]] constexpr subrange<_Iter1>
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -719,7 +720,7 @@ namespace ranges
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
_Pred, _Proj1, _Proj2>
- constexpr borrowed_subrange_t<_Range1>
+ [[nodiscard]] constexpr borrowed_subrange_t<_Range1>
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -737,7 +738,7 @@ namespace ranges
template<typename _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
- constexpr const _Tp&
+ [[nodiscard]] constexpr const _Tp&
operator()(const _Tp& __a, const _Tp& __b,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -754,13 +755,13 @@ namespace ranges
_Comp = ranges::less>
requires indirectly_copyable_storable<iterator_t<_Range>,
range_value_t<_Range>*>
- constexpr range_value_t<_Range>
+ [[nodiscard]] constexpr range_value_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
auto __first = ranges::begin(__r);
auto __last = ranges::end(__r);
__glibcxx_assert(__first != __last);
- auto __result = *__first;
+ range_value_t<_Range> __result(*__first);
while (++__first != __last)
{
auto&& __tmp = *__first;
@@ -775,7 +776,7 @@ namespace ranges
template<copyable _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
- constexpr _Tp
+ [[nodiscard]] constexpr _Tp
operator()(initializer_list<_Tp> __r,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -793,7 +794,7 @@ namespace ranges
indirect_binary_predicate<projected<_Iter, _Proj>,
projected<_Iter, _Proj>> _Pred
= ranges::equal_to>
- constexpr _Iter
+ [[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Pred __pred = {}, _Proj __proj = {}) const
{
@@ -814,7 +815,7 @@ namespace ranges
indirect_binary_predicate<
projected<iterator_t<_Range>, _Proj>,
projected<iterator_t<_Range>, _Proj>> _Pred = ranges::equal_to>
- constexpr borrowed_iterator_t<_Range>
+ [[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h
index 612715e..5d9f8c8 100644
--- a/libstdc++-v3/include/bits/refwrap.h
+++ b/libstdc++-v3/include/bits/refwrap.h
@@ -457,6 +457,40 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type)
/// @}
+#if __glibcxx_common_reference_wrapper // C++ >= 20
+ namespace __detail
+ {
+ template<typename _Tp>
+ constexpr bool __is_ref_wrapper = false;
+
+ template<typename _Tp>
+ constexpr bool __is_ref_wrapper<reference_wrapper<_Tp>> = true;
+
+ template<typename _Rp, typename _Tp, typename _RQual, typename _TQual>
+ concept __ref_wrap_common_reference_exists_with = __is_ref_wrapper<_Rp>
+ && requires { typename common_reference_t<typename _Rp::type&, _TQual>; }
+ && convertible_to<_RQual, common_reference_t<typename _Rp::type&, _TQual>>;
+ } // namespace __detail
+
+ template<typename _Rp, typename _Tp,
+ template<typename> class _RQual, template<typename> class _TQual>
+ requires __detail::__ref_wrap_common_reference_exists_with<_Rp, _Tp,
+ _RQual<_Rp>, _TQual<_Tp>>
+ && (!__detail::__ref_wrap_common_reference_exists_with<_Tp, _Rp,
+ _TQual<_Tp>, _RQual<_Rp>>)
+ struct basic_common_reference<_Rp, _Tp, _RQual, _TQual>
+ { using type = common_reference_t<typename _Rp::type&, _TQual<_Tp>>; };
+
+ template<typename _Tp, typename _Rp,
+ template<typename> class _TQual, template<typename> class _RQual>
+ requires __detail::__ref_wrap_common_reference_exists_with<_Rp, _Tp,
+ _RQual<_Rp>, _TQual<_Tp>>
+ && (!__detail::__ref_wrap_common_reference_exists_with<_Tp, _Rp,
+ _TQual<_Tp>, _RQual<_Rp>>)
+ struct basic_common_reference<_Tp, _Rp, _TQual, _RQual>
+ { using type = common_reference_t<typename _Rp::type&, _TQual<_Tp>>; };
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc
index b94fe44..48917cd 100644
--- a/libstdc++-v3/include/bits/regex.tcc
+++ b/libstdc++-v3/include/bits/regex.tcc
@@ -331,20 +331,53 @@ namespace __detail
&& __c == __fctyp.widen('_'));
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
template<typename _Ch_type>
int
regex_traits<_Ch_type>::
value(_Ch_type __ch, int __radix) const
{
- std::basic_istringstream<char_type> __is(string_type(1, __ch));
- long __v;
- if (__radix == 8)
- __is >> std::oct;
- else if (__radix == 16)
- __is >> std::hex;
- __is >> __v;
- return __is.fail() ? -1 : __v;
+ if constexpr (sizeof(_Ch_type) > 1)
+ {
+ const auto& __ctyp = std::use_facet<ctype<_Ch_type>>(_M_locale);
+ const char __c = __ctyp.narrow(__ch, '\0');
+ return regex_traits<char>{}.value(__c, __radix);
+ }
+ else
+ {
+ const char __c = static_cast<char>(__ch);
+ const char __max_digit = __radix == 8 ? '7' : '9';
+ if ('0' <= __c && __c <= __max_digit)
+ return __c - '0';
+ if (__radix < 16)
+ return -1;
+ switch (__c)
+ {
+ case 'a':
+ case 'A':
+ return 10;
+ case 'b':
+ case 'B':
+ return 11;
+ case 'c':
+ case 'C':
+ return 12;
+ case 'd':
+ case 'D':
+ return 13;
+ case 'e':
+ case 'E':
+ return 14;
+ case 'f':
+ case 'F':
+ return 15;
+ default:
+ return -1;
+ }
+ }
}
+#pragma GCC diagnostic pop
template<typename _Bi_iter, typename _Alloc>
template<typename _Out_iter>
diff --git a/libstdc++-v3/include/bits/regex_automaton.tcc b/libstdc++-v3/include/bits/regex_automaton.tcc
index 8a82646..4d566c6 100644
--- a/libstdc++-v3/include/bits/regex_automaton.tcc
+++ b/libstdc++-v3/include/bits/regex_automaton.tcc
@@ -28,6 +28,10 @@
* Do not attempt to use it directly. @headername{regex}
*/
+#ifdef _GLIBCXX_DEBUG
+# include <ostream>
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h
index f24c7e3..21e7065 100644
--- a/libstdc++-v3/include/bits/regex_compiler.h
+++ b/libstdc++-v3/include/bits/regex_compiler.h
@@ -38,6 +38,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_END_NAMESPACE_CXX11
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
namespace __detail
{
/**
@@ -221,9 +223,9 @@ namespace __detail
_CharT
_M_translate(_CharT __ch) const
{
- if _GLIBCXX17_CONSTEXPR (__icase)
+ if constexpr (__icase)
return _M_traits.translate_nocase(__ch);
- else if _GLIBCXX17_CONSTEXPR (__collate)
+ else if constexpr (__collate)
return _M_traits.translate(__ch);
else
return __ch;
@@ -285,7 +287,7 @@ namespace __detail
bool
_M_match_range(_CharT __first, _CharT __last, _CharT __ch) const
{
- if _GLIBCXX17_CONSTEXPR (!__icase)
+ if constexpr (!__icase)
return __first <= __ch && __ch <= __last;
else
return this->_M_in_range_icase(__first, __last, __ch);
@@ -376,26 +378,20 @@ namespace __detail
bool
operator()(_CharT __ch) const
- { return _M_apply(__ch, typename is_same<_CharT, char>::type()); }
-
- bool
- _M_apply(_CharT __ch, true_type) const
{
- auto __c = _M_translator._M_translate(__ch);
- auto __n = _M_translator._M_translate('\n');
- auto __r = _M_translator._M_translate('\r');
- return __c != __n && __c != __r;
- }
-
- bool
- _M_apply(_CharT __ch, false_type) const
- {
- auto __c = _M_translator._M_translate(__ch);
- auto __n = _M_translator._M_translate('\n');
- auto __r = _M_translator._M_translate('\r');
- auto __u2028 = _M_translator._M_translate(u'\u2028');
- auto __u2029 = _M_translator._M_translate(u'\u2029');
- return __c != __n && __c != __r && __c != __u2028 && __c != __u2029;
+ const auto __c = _M_translator._M_translate(__ch);
+ if (__c == _M_translator._M_translate('\n'))
+ return false;
+ if (__c == _M_translator._M_translate('\r'))
+ return false;
+ if constexpr (!is_same<_CharT, char>::value)
+ {
+ if (__c == _M_translator._M_translate(u'\u2028')) // line sep
+ return false;
+ if (__c == _M_translator._M_translate(u'\u2029')) // para sep
+ return false;
+ }
+ return true;
}
_TransT _M_translator;
@@ -441,7 +437,10 @@ namespace __detail
operator()(_CharT __ch) const
{
_GLIBCXX_DEBUG_ASSERT(_M_is_ready);
- return _M_apply(__ch, _UseCache());
+ if constexpr (_UseCache::value)
+ if (!(__ch & 0x80)) [[__likely__]]
+ return _M_cache[static_cast<_UnsignedCharT>(__ch)];
+ return _M_apply(__ch);
}
void
@@ -512,7 +511,9 @@ namespace __detail
std::sort(_M_char_set.begin(), _M_char_set.end());
auto __end = std::unique(_M_char_set.begin(), _M_char_set.end());
_M_char_set.erase(__end, _M_char_set.end());
- _M_make_cache(_UseCache());
+ if constexpr (_UseCache::value)
+ for (unsigned __i = 0; __i < 128; __i++) // Only cache 7-bit chars
+ _M_cache[__i] = _M_apply(static_cast<_CharT>(__i));
_GLIBCXX_DEBUG_ONLY(_M_is_ready = true);
}
@@ -531,22 +532,7 @@ namespace __detail
using _UnsignedCharT = typename std::make_unsigned<_CharT>::type;
bool
- _M_apply(_CharT __ch, false_type) const;
-
- bool
- _M_apply(_CharT __ch, true_type) const
- { return _M_cache[static_cast<_UnsignedCharT>(__ch)]; }
-
- void
- _M_make_cache(true_type)
- {
- for (unsigned __i = 0; __i < _M_cache.size(); __i++)
- _M_cache[__i] = _M_apply(static_cast<_CharT>(__i), false_type());
- }
-
- void
- _M_make_cache(false_type)
- { }
+ _M_apply(_CharT __ch) const;
private:
_GLIBCXX_STD_C::vector<_CharT> _M_char_set;
@@ -565,6 +551,7 @@ namespace __detail
///@} regex-detail
} // namespace __detail
+#pragma GCC diagnostic pop
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
index cd0db27..59b79fd 100644
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
@@ -598,7 +598,7 @@ namespace __detail
template<typename _TraitsT, bool __icase, bool __collate>
bool
_BracketMatcher<_TraitsT, __icase, __collate>::
- _M_apply(_CharT __ch, false_type) const
+ _M_apply(_CharT __ch) const
{
return [this, __ch]
{
diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc
index e887e28..8f0f756 100644
--- a/libstdc++-v3/include/bits/regex_executor.tcc
+++ b/libstdc++-v3/include/bits/regex_executor.tcc
@@ -32,6 +32,8 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
namespace __detail
{
template<typename _BiIter, typename _Alloc, typename _TraitsT,
@@ -217,7 +219,7 @@ namespace __detail
}
else // Non-greedy mode
{
- if (__dfs_mode)
+ if constexpr (__dfs_mode)
{
// vice-versa.
_M_dfs(__match_mode, __state._M_next);
@@ -322,7 +324,7 @@ namespace __detail
if (_M_current == _M_end)
return;
- if (__dfs_mode)
+ if constexpr (__dfs_mode)
{
if (__state._M_matches(*_M_current))
{
@@ -393,7 +395,7 @@ namespace __detail
void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
_M_handle_backref(_Match_mode __match_mode, _StateIdT __i)
{
- __glibcxx_assert(__dfs_mode);
+ static_assert(__dfs_mode, "this should never be instantiated");
const auto& __state = _M_nfa[__i];
auto& __submatch = _M_cur_results[__state._M_backref_index];
@@ -426,7 +428,7 @@ namespace __detail
void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
_M_handle_accept(_Match_mode __match_mode, _StateIdT)
{
- if _GLIBCXX17_CONSTEXPR (__dfs_mode)
+ if constexpr (__dfs_mode)
{
__glibcxx_assert(!_M_has_sol);
if (__match_mode == _Match_mode::_Exact)
@@ -529,7 +531,11 @@ namespace __detail
case _S_opcode_match:
_M_handle_match(__match_mode, __i); break;
case _S_opcode_backref:
- _M_handle_backref(__match_mode, __i); break;
+ if constexpr (__dfs_mode)
+ _M_handle_backref(__match_mode, __i);
+ else
+ __builtin_unreachable();
+ break;
case _S_opcode_accept:
_M_handle_accept(__match_mode, __i); break;
case _S_opcode_alternative:
@@ -564,6 +570,7 @@ namespace __detail
return __left_is_word != __right_is_word;
}
} // namespace __detail
+#pragma GCC diagnostic pop
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/bits/sat_arith.h b/libstdc++-v3/include/bits/sat_arith.h
index 97545d2..bce86d9 100644
--- a/libstdc++-v3/include/bits/sat_arith.h
+++ b/libstdc++-v3/include/bits/sat_arith.h
@@ -46,7 +46,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
_GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Add two integers, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
add_sat(_Tp __x, _Tp __y) noexcept
{
@@ -62,7 +62,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// Subtract one integer from another, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
sub_sat(_Tp __x, _Tp __y) noexcept
{
@@ -78,7 +78,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// Multiply two integers, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
mul_sat(_Tp __x, _Tp __y) noexcept
{
@@ -87,14 +87,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __z;
if constexpr (is_unsigned_v<_Tp>)
return __gnu_cxx::__int_traits<_Tp>::__max;
- else if (__x < 0 != __y < 0)
+ else if ((__x < 0) != (__y < 0))
return __gnu_cxx::__int_traits<_Tp>::__min;
else
return __gnu_cxx::__int_traits<_Tp>::__max;
}
/// Divide one integer by another, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
div_sat(_Tp __x, _Tp __y) noexcept
{
@@ -107,8 +107,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Divide one integer by another, with saturation in case of overflow.
template<typename _Res, typename _Tp>
- requires __is_standard_integer<_Res>::value
- && __is_standard_integer<_Tp>::value
+ requires __is_signed_or_unsigned_integer<_Res>::value
+ && __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Res
saturate_cast(_Tp __x) noexcept
{
diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h
index d8f9bd8..cb815d3 100644
--- a/libstdc++-v3/include/bits/semaphore_base.h
+++ b/libstdc++-v3/include/bits/semaphore_base.h
@@ -34,231 +34,279 @@
#pragma GCC system_header
#endif
+#include <bits/version.h>
+
+#ifdef __glibcxx_semaphore // C++ >= 20 && hosted && atomic_wait
#include <bits/atomic_base.h>
#include <bits/chrono.h>
-#if __glibcxx_atomic_wait
#include <bits/atomic_timed_wait.h>
#include <ext/numeric_traits.h>
-#endif // __cpp_lib_atomic_wait
-
-#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
-# include <cerrno> // errno, EINTR, EAGAIN etc.
-# include <limits.h> // SEM_VALUE_MAX
-# include <semaphore.h> // sem_t, sem_init, sem_wait, sem_post etc.
-#elif defined(_GLIBCXX_USE_POSIX_SEMAPHORE)
-# warning "POSIX semaphore not available, ignoring _GLIBCXX_USE_POSIX_SEMAPHORE"
-# undef _GLIBCXX_USE_POSIX_SEMAPHORE
-#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
-#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
- struct __platform_semaphore
+ struct __semaphore_impl
{
- using __clock_t = chrono::system_clock;
-#ifdef SEM_VALUE_MAX
- static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX;
-#else
- static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX;
-#endif
+ using __count_type = ptrdiff_t;
- explicit __platform_semaphore(ptrdiff_t __count) noexcept
- {
- sem_init(&_M_semaphore, 0, __count);
- }
+ static constexpr ptrdiff_t _S_max
+ = __gnu_cxx::__int_traits<__count_type>::__max;
- __platform_semaphore(const __platform_semaphore&) = delete;
- __platform_semaphore& operator=(const __platform_semaphore&) = delete;
+ constexpr explicit
+ __semaphore_impl(__count_type __count) noexcept
+ : _M_counter(__count)
+ { }
- ~__platform_semaphore()
- { sem_destroy(&_M_semaphore); }
+ __semaphore_impl(const __semaphore_impl&) = delete;
+ __semaphore_impl& operator=(const __semaphore_impl&) = delete;
- _GLIBCXX_ALWAYS_INLINE void
- _M_acquire() noexcept
- {
- while (sem_wait(&_M_semaphore))
- if (errno != EINTR)
- std::__terminate();
- }
+ // Load the current counter value.
+ _GLIBCXX_ALWAYS_INLINE __count_type
+ _M_get_current() const noexcept
+ { return __atomic_impl::load(&_M_counter, memory_order::acquire); }
+ // Try to acquire the semaphore (i.e. decrement the counter).
+ // Returns false if the current counter is zero, or if another thread
+ // changes the value first. In the latter case, __cur is set to the new
+ // value.
_GLIBCXX_ALWAYS_INLINE bool
- _M_try_acquire() noexcept
+ _M_do_try_acquire(__count_type& __cur) noexcept
{
- while (sem_trywait(&_M_semaphore))
- {
- if (errno == EAGAIN) // already locked
- return false;
- else if (errno != EINTR)
- std::__terminate();
- // else got EINTR so retry
- }
- return true;
+ if (__cur == 0)
+ return false; // Cannot decrement when it's already zero.
+
+ return __atomic_impl::compare_exchange_strong(&_M_counter,
+ __cur, __cur - 1,
+ memory_order::acquire,
+ memory_order::relaxed);
}
- _GLIBCXX_ALWAYS_INLINE void
- _M_release(ptrdiff_t __update) noexcept
+ // Keep trying to acquire the semaphore in a loop until it succeeds.
+ void
+ _M_acquire() noexcept
{
- for(; __update != 0; --__update)
- if (sem_post(&_M_semaphore))
- std::__terminate();
+ auto __vfn = [this]{ return _M_get_current(); };
+ _Available __is_available{__vfn()};
+ while (!_M_do_try_acquire(__is_available._M_val))
+ if (!__is_available())
+ std::__atomic_wait_address(&_M_counter, __is_available, __vfn, true);
}
+ // Try to acquire the semaphore, retrying a small number of times
+ // in case of contention.
bool
- _M_try_acquire_until_impl(const chrono::time_point<__clock_t>& __atime)
- noexcept
+ _M_try_acquire() noexcept
{
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
-
- struct timespec __ts =
- {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
-
- while (sem_timedwait(&_M_semaphore, &__ts))
- {
- if (errno == ETIMEDOUT)
- return false;
- else if (errno != EINTR)
- std::__terminate();
- }
- return true;
+ // The fastest implementation of this function is just _M_do_try_acquire
+ // but that can fail under contention even when _M_count > 0.
+ // Using _M_try_acquire_for(0ns) will retry a few times in a loop.
+ return _M_try_acquire_for(__detail::__wait_clock_t::duration{});
}
template<typename _Clock, typename _Duration>
bool
- _M_try_acquire_until(const chrono::time_point<_Clock,
- _Duration>& __atime) noexcept
+ _M_try_acquire_until(const chrono::time_point<_Clock, _Duration>& __atime) noexcept
{
- if constexpr (std::is_same_v<__clock_t, _Clock>)
- {
- using _Dur = __clock_t::duration;
- return _M_try_acquire_until_impl(chrono::ceil<_Dur>(__atime));
- }
- else
- {
- // TODO: if _Clock is monotonic_clock we could use
- // sem_clockwait with CLOCK_MONOTONIC.
-
- const typename _Clock::time_point __c_entry = _Clock::now();
- const auto __s_entry = __clock_t::now();
- const auto __delta = __atime - __c_entry;
- const auto __s_atime = __s_entry + __delta;
- if (_M_try_acquire_until_impl(__s_atime))
- return true;
-
- // We got a timeout when measured against __clock_t but
- // we need to check against the caller-supplied clock
- // to tell whether we should return a timeout.
- return (_Clock::now() < __atime);
- }
+ auto __vfn = [this]{ return _M_get_current(); };
+ _Available __is_available{__vfn()};
+ while (!_M_do_try_acquire(__is_available._M_val))
+ if (!__is_available())
+ if (!std::__atomic_wait_address_until(&_M_counter, __is_available,
+ __vfn, __atime, true))
+ return false; // timed out
+ return true;
}
template<typename _Rep, typename _Period>
- _GLIBCXX_ALWAYS_INLINE bool
- _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime)
- noexcept
- { return _M_try_acquire_until(__clock_t::now() + __rtime); }
+ bool
+ _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) noexcept
+ {
+ auto __vfn = [this]{ return _M_get_current(); };
+ _Available __is_available{__vfn()};
+ while (!_M_do_try_acquire(__is_available._M_val))
+ if (!__is_available())
+ if (!std::__atomic_wait_address_for(&_M_counter, __is_available,
+ __vfn, __rtime, true))
+ return false; // timed out
+ return true;
+ }
+
+ _GLIBCXX_ALWAYS_INLINE ptrdiff_t
+ _M_release(ptrdiff_t __update) noexcept
+ {
+ auto __old = __atomic_impl::fetch_add(&_M_counter, __update,
+ memory_order::release);
+ if (__old == 0 && __update > 0)
+ __atomic_notify_address(&_M_counter, true, true);
+ return __old;
+ }
private:
- sem_t _M_semaphore;
+ struct _Available
+ {
+ __count_type _M_val; // Cache of the last value loaded from _M_counter.
+
+ // Returns true if the cached value is non-zero and so it should be
+ // possible to acquire the semaphore.
+ bool operator()() const noexcept { return _M_val > 0; }
+
+ // Argument should be the latest value of the counter.
+ // Returns true (and caches the value) if it's non-zero, meaning it
+ // should be possible to acquire the semaphore. Returns false otherwise.
+ bool operator()(__count_type __cur) noexcept
+ {
+ if (__cur == 0)
+ return false;
+ _M_val = __cur;
+ return true;
+ }
+ };
+
+ alignas(__atomic_ref<__count_type>::required_alignment)
+ __count_type _M_counter;
};
-#endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE
-#if __glibcxx_atomic_wait
- struct __atomic_semaphore
+ // Optimized specialization using __platform_wait (if available)
+ template<bool _Binary>
+ struct __platform_semaphore_impl
{
- static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits<int>::__max;
- explicit __atomic_semaphore(__detail::__platform_wait_t __count) noexcept
- : _M_counter(__count)
+ using __count_type = __detail::__platform_wait_t;
+
+ static consteval ptrdiff_t
+ _S_calc_max()
{
- __glibcxx_assert(__count >= 0 && __count <= _S_max);
+ if (_Binary)
+ return 1;
+ else if ((ptrdiff_t)__gnu_cxx::__int_traits<__count_type>::__max < 0)
+ return __gnu_cxx::__int_traits<ptrdiff_t>::__max;
+ else
+ return __gnu_cxx::__int_traits<__count_type>::__max;
}
- __atomic_semaphore(const __atomic_semaphore&) = delete;
- __atomic_semaphore& operator=(const __atomic_semaphore&) = delete;
+ static constexpr ptrdiff_t _S_max = _S_calc_max();
+
+ constexpr explicit
+ __platform_semaphore_impl(__count_type __count) noexcept
+ : _M_counter(__count)
+ { }
+
+ __platform_semaphore_impl(__platform_semaphore_impl&) = delete;
+ __platform_semaphore_impl& operator=(const __platform_semaphore_impl&) = delete;
+
+ // Load the current counter value.
+ _GLIBCXX_ALWAYS_INLINE __count_type
+ _M_get_current() const noexcept
+ {
+ if constexpr (_Binary)
+ return 1; // Not necessarily true, but optimistically assume it is.
+ else
+ return __atomic_impl::load(&_M_counter, memory_order::acquire);
+ }
- static _GLIBCXX_ALWAYS_INLINE bool
- _S_do_try_acquire(__detail::__platform_wait_t* __counter) noexcept
+ // Try to acquire the semaphore (i.e. decrement the counter).
+ // Returns false if the current counter is zero, or if another thread
+ // changes the value first. In the latter case, __cur is set to the new
+ // value.
+ _GLIBCXX_ALWAYS_INLINE bool
+ _M_do_try_acquire(__count_type& __cur) noexcept
{
- auto __old = __atomic_impl::load(__counter, memory_order::acquire);
- if (__old == 0)
- return false;
+ if (__cur == 0)
+ return false; // Cannot decrement when it's already zero.
- return __atomic_impl::compare_exchange_strong(__counter,
- __old, __old - 1,
+ return __atomic_impl::compare_exchange_strong(&_M_counter,
+ __cur, __cur - 1,
memory_order::acquire,
memory_order::relaxed);
}
- _GLIBCXX_ALWAYS_INLINE void
+ // Keep trying to acquire the semaphore in a loop until it succeeds.
+ void
_M_acquire() noexcept
{
- auto const __pred =
- [this] { return _S_do_try_acquire(&this->_M_counter); };
- std::__atomic_wait_address_bare(&_M_counter, __pred);
+ auto __val = _M_get_current();
+ while (!_M_do_try_acquire(__val))
+ if (__val == 0)
+ {
+ std::__atomic_wait_address_v(&_M_counter, __val, __ATOMIC_ACQUIRE,
+ true);
+ __val = _M_get_current();
+ }
}
+ // Try to acquire the semaphore.
bool
_M_try_acquire() noexcept
{
- auto const __pred =
- [this] { return _S_do_try_acquire(&this->_M_counter); };
- return std::__detail::__atomic_spin(__pred);
+ if constexpr (_Binary)
+ {
+ __count_type __val = 1;
+ // Do not expect much contention on binary semaphore, only try once.
+ return _M_do_try_acquire(__val);
+ }
+ else
+ // Fastest implementation of this function is just _M_do_try_acquire
+ // but that can fail under contention even when _M_count > 0.
+ // Using _M_try_acquire_for(0ns) will retry a few times in a loop.
+ return _M_try_acquire_for(__detail::__wait_clock_t::duration{});
}
template<typename _Clock, typename _Duration>
- _GLIBCXX_ALWAYS_INLINE bool
- _M_try_acquire_until(const chrono::time_point<_Clock,
- _Duration>& __atime) noexcept
+ bool
+ _M_try_acquire_until(const chrono::time_point<_Clock, _Duration>& __atime) noexcept
{
- auto const __pred =
- [this] { return _S_do_try_acquire(&this->_M_counter); };
-
- return __atomic_wait_address_until_bare(&_M_counter, __pred, __atime);
+ auto __val = _M_get_current();
+ while (!_M_do_try_acquire(__val))
+ if (__val == 0)
+ {
+ if (!std::__atomic_wait_address_until_v(&_M_counter, 0,
+ __ATOMIC_ACQUIRE,
+ __atime, true))
+ return false; // timed out
+ __val = _M_get_current();
+ }
+ return true;
}
template<typename _Rep, typename _Period>
- _GLIBCXX_ALWAYS_INLINE bool
- _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime)
- noexcept
+ bool
+ _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) noexcept
{
- auto const __pred =
- [this] { return _S_do_try_acquire(&this->_M_counter); };
-
- return __atomic_wait_address_for_bare(&_M_counter, __pred, __rtime);
+ auto __val = _M_get_current();
+ while (!_M_do_try_acquire(__val))
+ if (__val == 0)
+ {
+ if (!std::__atomic_wait_address_for_v(&_M_counter, 0,
+ __ATOMIC_ACQUIRE,
+ __rtime, true))
+ return false; // timed out
+ __val = _M_get_current();
+ }
+ return true;
}
- _GLIBCXX_ALWAYS_INLINE void
+ _GLIBCXX_ALWAYS_INLINE ptrdiff_t
_M_release(ptrdiff_t __update) noexcept
{
- if (0 < __atomic_impl::fetch_add(&_M_counter, __update, memory_order_release))
- return;
- if (__update > 1)
- __atomic_notify_address_bare(&_M_counter, true);
- else
- __atomic_notify_address_bare(&_M_counter, true);
-// FIXME - Figure out why this does not wake a waiting thread
-// __atomic_notify_address_bare(&_M_counter, false);
+ auto __old = __atomic_impl::fetch_add(&_M_counter, __update,
+ memory_order::release);
+ if (__old == 0 && __update > 0)
+ __atomic_notify_address(&_M_counter, true, true);
+ return __old;
}
- private:
- alignas(__detail::__platform_wait_alignment)
- __detail::__platform_wait_t _M_counter;
+ protected:
+ alignas(__detail::__platform_wait_alignment) __count_type _M_counter;
};
-#endif // __cpp_lib_atomic_wait
-
-// Note: the _GLIBCXX_USE_POSIX_SEMAPHORE macro can be used to force the
-// use of Posix semaphores (sem_t). Doing so however, alters the ABI.
-#if defined __glibcxx_atomic_wait && !_GLIBCXX_USE_POSIX_SEMAPHORE
- using __semaphore_impl = __atomic_semaphore;
-#elif _GLIBCXX_HAVE_POSIX_SEMAPHORE
- using __semaphore_impl = __platform_semaphore;
-#endif
+
+ template<ptrdiff_t _Max, typename _Tp = __detail::__platform_wait_t>
+ using _Semaphore_impl
+ = __conditional_t<__platform_wait_uses_type<_Tp>
+ && _Max <= __gnu_cxx::__int_traits<_Tp>::__max,
+ __platform_semaphore_impl<(_Max <= 1)>,
+ __semaphore_impl>;
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
+#endif // __glibcxx_semaphore
#endif // _GLIBCXX_SEMAPHORE_BASE_H
diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index a196a0f..f2b4601 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -909,6 +909,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
{ };
+#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26
+
+ /**
+ * @brief Provides ownership-based hashing.
+ * @headerfile memory
+ * @since C++26
+ */
+ struct owner_hash
+ {
+ template<typename _Tp>
+ size_t
+ operator()(const shared_ptr<_Tp>& __s) const noexcept
+ { return __s.owner_hash(); }
+
+ template<typename _Tp>
+ size_t
+ operator()(const weak_ptr<_Tp>& __s) const noexcept
+ { return __s.owner_hash(); }
+
+ using is_transparent = void;
+ };
+
+ /**
+ * @brief Provides ownership-based mixed equality comparisons of
+ * shared and weak pointers.
+ * @headerfile memory
+ * @since C++26
+ */
+ struct owner_equal
+ {
+ template<typename _Tp1, typename _Tp2>
+ bool
+ operator()(const shared_ptr<_Tp1>& __lhs,
+ const shared_ptr<_Tp2>& __rhs) const noexcept
+ { return __lhs.owner_equal(__rhs); }
+
+ template<typename _Tp1, typename _Tp2>
+ bool
+ operator()(const shared_ptr<_Tp1>& __lhs,
+ const weak_ptr<_Tp2>& __rhs) const noexcept
+ { return __lhs.owner_equal(__rhs); }
+
+ template<typename _Tp1, typename _Tp2>
+ bool
+ operator()(const weak_ptr<_Tp1>& __lhs,
+ const shared_ptr<_Tp2>& __rhs) const noexcept
+ { return __lhs.owner_equal(__rhs); }
+
+ template<typename _Tp1, typename _Tp2>
+ bool
+ operator()(const weak_ptr<_Tp1>& __lhs,
+ const weak_ptr<_Tp2>& __rhs) const noexcept
+ { return __lhs.owner_equal(__rhs); }
+
+ using is_transparent = void;
+ };
+#endif
+
/**
* @brief Base class allowing use of the member function `shared_from_this`.
* @headerfile memory
diff --git a/libstdc++-v3/include/bits/shared_ptr_atomic.h b/libstdc++-v3/include/bits/shared_ptr_atomic.h
index cc7841a..cbc4bf6 100644
--- a/libstdc++-v3/include/bits/shared_ptr_atomic.h
+++ b/libstdc++-v3/include/bits/shared_ptr_atomic.h
@@ -392,6 +392,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class _Sp_atomic
{
using value_type = _Tp;
+ using element_type = typename _Tp::element_type;
friend struct atomic<_Tp>;
@@ -420,7 +421,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~_Atomic_count()
{
- auto __val = _M_val.load(memory_order_relaxed);
+ auto __val = _AtomicRef(_M_val).load(memory_order_relaxed);
_GLIBCXX_TSAN_MUTEX_DESTROY(&_M_val);
__glibcxx_assert(!(__val & _S_lock_bit));
if (auto __pi = reinterpret_cast<pointer>(__val))
@@ -442,18 +443,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
// To acquire the lock we flip the LSB from 0 to 1.
- auto __current = _M_val.load(memory_order_relaxed);
+ _AtomicRef __aref(_M_val);
+ auto __current = __aref.load(memory_order_relaxed);
while (__current & _S_lock_bit)
{
#if __glibcxx_atomic_wait
__detail::__thread_relax();
#endif
- __current = _M_val.load(memory_order_relaxed);
+ __current = __aref.load(memory_order_relaxed);
}
_GLIBCXX_TSAN_MUTEX_TRY_LOCK(&_M_val);
- while (!_M_val.compare_exchange_strong(__current,
+ while (!__aref.compare_exchange_strong(__current,
__current | _S_lock_bit,
__o,
memory_order_relaxed))
@@ -474,7 +476,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
unlock(memory_order __o) const noexcept
{
_GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(&_M_val);
- _M_val.fetch_sub(1, __o);
+ _AtomicRef(_M_val).fetch_sub(1, __o);
_GLIBCXX_TSAN_MUTEX_POST_UNLOCK(&_M_val);
}
@@ -487,7 +489,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__o = memory_order_release;
auto __x = reinterpret_cast<uintptr_t>(__c._M_pi);
_GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(&_M_val);
- __x = _M_val.exchange(__x, __o);
+ __x = _AtomicRef(_M_val).exchange(__x, __o);
_GLIBCXX_TSAN_MUTEX_POST_UNLOCK(&_M_val);
__c._M_pi = reinterpret_cast<pointer>(__x & ~_S_lock_bit);
}
@@ -495,19 +497,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __glibcxx_atomic_wait
// Precondition: caller holds lock!
void
- _M_wait_unlock(memory_order __o) const noexcept
+ _M_wait_unlock(const element_type* const& __ptr, memory_order __o) const noexcept
{
+ auto __old_ptr = __ptr;
_GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(&_M_val);
- auto __v = _M_val.fetch_sub(1, memory_order_relaxed);
+ uintptr_t __old_pi
+ = _AtomicRef(_M_val).fetch_sub(1, memory_order_relaxed) - 1u;
_GLIBCXX_TSAN_MUTEX_POST_UNLOCK(&_M_val);
- _M_val.wait(__v & ~_S_lock_bit, __o);
+
+ // Ensure that the correct value of _M_ptr is visible after locking,
+ // by upgrading relaxed or consume to acquire.
+ auto __lo = __o;
+ if (__o != memory_order_seq_cst)
+ __lo = memory_order_acquire;
+
+ std::__atomic_wait_address(
+ &_M_val,
+ [=, &__ptr, this](uintptr_t __new_pi)
+ {
+ if (__old_pi != (__new_pi & ~_S_lock_bit))
+ // control block changed, we can wake up
+ return true;
+
+ // control block is same, we need to check if ptr changed,
+ // the lock needs to be taken first, the value of pi may have
+ // also been updated in meantime, so reload it
+ __new_pi = reinterpret_cast<uintptr_t>(this->lock(__lo));
+ auto __new_ptr = __ptr;
+ this->unlock(memory_order_relaxed);
+ // wake up if either of the values changed
+ return __new_pi != __old_pi || __new_ptr != __old_ptr;
+ },
+ [__o, this] { return _AtomicRef(_M_val).load(__o); });
}
void
notify_one() noexcept
{
_GLIBCXX_TSAN_MUTEX_PRE_SIGNAL(&_M_val);
- _M_val.notify_one();
+ _AtomicRef(_M_val).notify_one();
_GLIBCXX_TSAN_MUTEX_POST_SIGNAL(&_M_val);
}
@@ -515,17 +543,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
notify_all() noexcept
{
_GLIBCXX_TSAN_MUTEX_PRE_SIGNAL(&_M_val);
- _M_val.notify_all();
+ _AtomicRef(_M_val).notify_all();
_GLIBCXX_TSAN_MUTEX_POST_SIGNAL(&_M_val);
}
#endif
private:
- mutable __atomic_base<uintptr_t> _M_val{0};
+ using _AtomicRef = __atomic_ref<uintptr_t>;
+ alignas(_AtomicRef::required_alignment) mutable uintptr_t _M_val{0};
static constexpr uintptr_t _S_lock_bit{1};
};
- typename _Tp::element_type* _M_ptr = nullptr;
+ element_type* _M_ptr = nullptr;
_Atomic_count _M_refcount;
static typename _Atomic_count::pointer
@@ -608,7 +637,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
auto __pi = _M_refcount.lock(memory_order_acquire);
if (_M_ptr == __old._M_ptr && __pi == __old._M_refcount._M_pi)
- _M_refcount._M_wait_unlock(__o);
+ _M_refcount._M_wait_unlock(_M_ptr, __o);
else
_M_refcount.unlock(memory_order_relaxed);
}
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index 3622e02..9af706a 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -148,7 +148,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Increment the use count (used when the count is greater than zero).
void
_M_add_ref_copy()
- { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
+ { _S_chk(__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1)); }
// Increment the use count if it is non-zero, throw otherwise.
void
@@ -200,7 +200,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Increment the weak count.
void
_M_weak_add_ref() noexcept
- { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
+ {
+ // _M_weak_count can always use negative values because it cannot be
+ // observed by users (unlike _M_use_count). See _S_chk for details.
+ constexpr _Atomic_word __max = -1;
+ if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, 1) == __max)
+ [[__unlikely__]] __builtin_trap();
+ }
// Decrement the weak count.
void
@@ -224,19 +230,87 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
long
_M_get_use_count() const noexcept
{
- // No memory barrier is used here so there is no synchronization
- // with other threads.
- return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED);
+ // No memory barrier is used here so there is no synchronization
+ // with other threads.
+ auto __count = __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED);
+
+ // If long is wider than _Atomic_word then we can treat _Atomic_word
+ // as unsigned, and so double its usable range. If the widths are the
+ // same then casting to unsigned and then to long is a no-op.
+ return static_cast<_Unsigned_count_type>(__count);
}
private:
_Sp_counted_base(_Sp_counted_base const&) = delete;
_Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wignored-attributes"
+ // This is only to be used for arithmetic, not for atomic ops.
+ using _Unsigned_count_type = make_unsigned<_Atomic_word>::type;
+#pragma GCC diagnostic pop
+
+ // Called when incrementing _M_use_count to cause a trap on overflow.
+ // This should be passed the value of the counter before the increment.
+ static void
+ _S_chk(_Atomic_word __count)
+ {
+ constexpr _Atomic_word __max_atomic_word = _Unsigned_count_type(-1)/2;
+
+ // __max is the maximum allowed value for the shared reference count.
+ // All valid reference count values need to fit into [0,LONG_MAX)
+ // because users can observe the count via shared_ptr::use_count().
+ //
+ // When long is wider than _Atomic_word, _M_use_count can go negative
+ // and the cast in _Sp_counted_base::use_count() will turn it into a
+ // positive value suitable for returning to users. The implementation
+ // only cares whether _M_use_count reaches zero after a decrement,
+ // so negative values are not a problem internally.
+ // So when possible, use -1 for __max (incrementing past that would
+ // overflow _M_use_count to 0, which means an empty shared_ptr).
+ //
+ // When long is not wider than _Atomic_word, __max is just the type's
+ // maximum positive value. We cannot use negative counts because they
+ // would not fit in [0,LONG_MAX) after casting to an unsigned type,
+ // which would cause use_count() to return bogus values.
+ constexpr _Atomic_word __max
+ = sizeof(long) > sizeof(_Atomic_word) ? -1 : __max_atomic_word;
+
+ if (__count == __max) [[__unlikely__]]
+ __builtin_trap();
+ }
+
_Atomic_word _M_use_count; // #shared
_Atomic_word _M_weak_count; // #weak + (#shared != 0)
};
+ // We use __atomic_add_single and __exchange_and_add_single in the _S_single
+ // member specializations because they use unsigned arithmetic and so avoid
+ // undefined overflow.
+ template<>
+ inline void
+ _Sp_counted_base<_S_single>::_M_add_ref_copy()
+ {
+ _S_chk(_M_use_count);
+ __gnu_cxx::__atomic_add_single(&_M_use_count, 1);
+ }
+
+ template<>
+ inline void
+ _Sp_counted_base<_S_single>::_M_weak_release() noexcept
+ {
+ if (__gnu_cxx::__exchange_and_add_single(&_M_weak_count, -1) == 1)
+ _M_destroy();
+ }
+
+ template<>
+ inline long
+ _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
+ {
+ return static_cast<_Unsigned_count_type>(_M_use_count);
+ }
+
+
template<>
inline bool
_Sp_counted_base<_S_single>::
@@ -244,7 +318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (_M_use_count == 0)
return false;
- ++_M_use_count;
+ _M_add_ref_copy();
return true;
}
@@ -254,8 +328,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_add_ref_lock_nothrow() noexcept
{
__gnu_cxx::__scoped_lock sentry(*this);
- if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
+ if (auto __c = __gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1))
+ _S_chk(__c);
+ else
{
+ // Count was zero, so we cannot lock it to get a shared_ptr.
+ // Reset to zero. This isn't racy, because there are no shared_ptr
+ // objects using this count and any other weak_ptr objects using it
+ // must call this function to modify _M_use_count, so would be
+ // synchronized by the mutex.
_M_use_count = 0;
return false;
}
@@ -279,23 +360,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
true, __ATOMIC_ACQ_REL,
__ATOMIC_RELAXED));
+ _S_chk(__count);
return true;
}
template<>
inline void
- _Sp_counted_base<_S_single>::_M_add_ref_copy()
- { ++_M_use_count; }
-
- template<>
- inline void
_Sp_counted_base<_S_single>::_M_release() noexcept
{
- if (--_M_use_count == 0)
+ if (__gnu_cxx::__exchange_and_add_single(&_M_use_count, -1) == 1)
{
- _M_dispose();
- if (--_M_weak_count == 0)
- _M_destroy();
+ _M_dispose();
+ _M_weak_release();
}
}
@@ -315,6 +391,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline void
_Sp_counted_base<_S_atomic>::_M_release() noexcept
{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
#if ! _GLIBCXX_TSAN
constexpr bool __lock_free
@@ -325,7 +403,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// The ref-count members follow the vptr, so are aligned to
// alignof(void*).
constexpr bool __aligned = __alignof(long long) <= alignof(void*);
- if _GLIBCXX17_CONSTEXPR (__lock_free && __double_word && __aligned)
+ if constexpr (__lock_free && __double_word && __aligned)
{
constexpr int __wordbits = __CHAR_BIT__ * sizeof(_Atomic_word);
constexpr int __shiftbits = __double_word ? __wordbits : 0;
@@ -359,27 +437,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_M_release_last_use();
}
+#pragma GCC diagnostic pop
}
- template<>
- inline void
- _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept
- { ++_M_weak_count; }
-
- template<>
- inline void
- _Sp_counted_base<_S_single>::_M_weak_release() noexcept
- {
- if (--_M_weak_count == 0)
- _M_destroy();
- }
-
- template<>
- inline long
- _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
- { return _M_use_count; }
-
-
// Forward declarations.
template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
class __shared_ptr;
@@ -1119,6 +1179,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_less(const __weak_count<_Lp>& __rhs) const noexcept
{ return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
+#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26
+ size_t
+ _M_owner_hash() const noexcept
+ { return std::hash<_Sp_counted_base<_Lp>*>()(this->_M_pi); }
+#endif
+
// Friend function injected into enclosing namespace and found by ADL
friend inline bool
operator==(const __shared_count& __a, const __shared_count& __b) noexcept
@@ -1222,6 +1288,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_less(const __shared_count<_Lp>& __rhs) const noexcept
{ return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
+#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26
+ size_t
+ _M_owner_hash() const noexcept
+ { return std::hash<_Sp_counted_base<_Lp>*>()(this->_M_pi); }
+#endif
+
// Friend function injected into enclosing namespace and found by ADL
friend inline bool
operator==(const __weak_count& __a, const __weak_count& __b) noexcept
@@ -1712,6 +1784,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return _M_refcount._M_less(__rhs._M_refcount); }
/// @}
+#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26
+ size_t owner_hash() const noexcept { return _M_refcount._M_owner_hash(); }
+
+ template<typename _Tp1>
+ bool
+ owner_equal(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept
+ { return _M_refcount == __rhs._M_refcount; }
+
+ template<typename _Tp1>
+ bool
+ owner_equal(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept
+ { return _M_refcount == __rhs._M_refcount; }
+#endif
+
protected:
// This constructor is non-standard, it is used by allocate_shared.
template<typename _Alloc, typename... _Args>
@@ -1983,6 +2069,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, _Lock_policy _Lp>
class __weak_ptr
{
+ public:
+ using element_type = typename remove_extent<_Tp>::type;
+
+ private:
template<typename _Yp, typename _Res = void>
using _Compatible = typename
enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
@@ -1991,9 +2081,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Yp>
using _Assignable = _Compatible<_Yp, __weak_ptr&>;
- public:
- using element_type = typename remove_extent<_Tp>::type;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ // Helper for construction/assignment:
+ template<typename _Yp>
+ static element_type*
+ _S_safe_upcast(const __weak_ptr<_Yp, _Lp>& __r)
+ {
+ // We know that _Yp and _Tp are compatible, that is, either
+ // _Yp* is convertible to _Tp* or _Yp is U[N] and _Tp is U cv [].
+
+ // If _Yp is the same as _Tp after removing extents and cv
+ // qualifications, there's no pointer adjustments to do. This
+ // also allows us to support incomplete types.
+ using _At = typename remove_cv<typename remove_extent<_Tp>::type>::type;
+ using _Bt = typename remove_cv<typename remove_extent<_Yp>::type>::type;
+ if constexpr (is_same<_At, _Bt>::value)
+ return __r._M_ptr;
+ // If they're not the same type, but they're both scalars,
+ // we again don't need any adjustment. This allows us to support e.g.
+ // pointers to a differently cv qualified type X.
+ else if constexpr (__and_<is_scalar<_At>, is_scalar<_Bt>>::value)
+ return __r._M_ptr;
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__builtin_is_virtual_base_of)
+ // If _Tp is not a virtual base class of _Yp, the pointer
+ // conversion does not require dereferencing __r._M_ptr; just
+ // rely on the implicit conversion.
+ else if constexpr (!__builtin_is_virtual_base_of(_Tp, _Yp))
+ return __r._M_ptr;
+#endif
+ // Expensive path; must lock() and do the pointer conversion while
+ // a shared_ptr keeps the pointee alive (because we may need
+ // to dereference).
+ else
+ return __r.lock().get();
+ }
+#pragma GCC diagnostic pop
+ public:
constexpr __weak_ptr() noexcept
: _M_ptr(nullptr), _M_refcount()
{ }
@@ -2018,8 +2143,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// in multithreaded programs __r._M_ptr may be invalidated at any point.
template<typename _Yp, typename = _Compatible<_Yp>>
__weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
- : _M_refcount(__r._M_refcount)
- { _M_ptr = __r.lock().get(); }
+ : _M_ptr(_S_safe_upcast(__r)), _M_refcount(__r._M_refcount)
+ { }
template<typename _Yp, typename = _Compatible<_Yp>>
__weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
@@ -2032,7 +2157,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Yp, typename = _Compatible<_Yp>>
__weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
- : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
+ : _M_ptr(_S_safe_upcast(__r)), _M_refcount(std::move(__r._M_refcount))
{ __r._M_ptr = nullptr; }
__weak_ptr&
@@ -2042,7 +2167,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Assignable<_Yp>
operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
{
- _M_ptr = __r.lock().get();
+ _M_ptr = _S_safe_upcast(__r);
_M_refcount = __r._M_refcount;
return *this;
}
@@ -2067,7 +2192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Assignable<_Yp>
operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
{
- _M_ptr = __r.lock().get();
+ _M_ptr = _S_safe_upcast(__r);
_M_refcount = std::move(__r._M_refcount);
__r._M_ptr = nullptr;
return *this;
@@ -2095,6 +2220,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept
{ return _M_refcount._M_less(__rhs._M_refcount); }
+#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26
+ size_t owner_hash() const noexcept { return _M_refcount._M_owner_hash(); }
+
+ template<typename _Tp1>
+ bool
+ owner_equal(const __shared_ptr<_Tp1, _Lp> & __rhs) const noexcept
+ { return _M_refcount == __rhs._M_refcount; }
+
+ template<typename _Tp1>
+ bool
+ owner_equal(const __weak_ptr<_Tp1, _Lp> & __rhs) const noexcept
+ { return _M_refcount == __rhs._M_refcount; }
+#endif
+
void
reset() noexcept
{ __weak_ptr().swap(*this); }
diff --git a/libstdc++-v3/include/bits/std_abs.h b/libstdc++-v3/include/bits/std_abs.h
index 35ec4d3..3d805e6 100644
--- a/libstdc++-v3/include/bits/std_abs.h
+++ b/libstdc++-v3/include/bits/std_abs.h
@@ -103,6 +103,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
#endif
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+ // In strict modes __GLIBCXX_TYPE_INT_N_0 is not defined for __int128,
+ // but we want to always define std::abs(__int128).
+ __extension__ inline _GLIBCXX_CONSTEXPR __int128
+ abs(__int128 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+
#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
constexpr _Float16
abs(_Float16 __x)
@@ -137,7 +144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __gnu_cxx::__bfloat16_t(__builtin_fabsf(__x)); }
#endif
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
+#if defined(_GLIBCXX_USE_FLOAT128)
__extension__ inline _GLIBCXX_CONSTEXPR
__float128
abs(__float128 __x)
diff --git a/libstdc++-v3/include/bits/std_function.h b/libstdc++-v3/include/bits/std_function.h
index 1bf8b9a..3bfbe82 100644
--- a/libstdc++-v3/include/bits/std_function.h
+++ b/libstdc++-v3/include/bits/std_function.h
@@ -135,13 +135,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static _Functor*
_M_get_pointer(const _Any_data& __source) noexcept
{
- if _GLIBCXX17_CONSTEXPR (__stored_locally)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ if constexpr (__stored_locally)
{
const _Functor& __f = __source._M_access<_Functor>();
return const_cast<_Functor*>(std::__addressof(__f));
}
else // have stored a pointer
return __source._M_access<_Functor*>();
+#pragma GCC diagnostic pop
}
private:
@@ -312,21 +315,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return false; }
};
- // Avoids instantiating ill-formed specializations of _Function_handler
- // in std::function<_Signature>::target<_Functor>().
- // e.g. _Function_handler<Sig, void()> and _Function_handler<Sig, void>
- // would be ill-formed.
- template<typename _Signature, typename _Functor,
- bool __valid = is_object<_Functor>::value>
- struct _Target_handler
- : _Function_handler<_Signature, typename remove_cv<_Functor>::type>
- { };
-
- template<typename _Signature, typename _Functor>
- struct _Target_handler<_Signature, _Functor, false>
- : _Function_handler<void, void>
- { };
-
/**
* @brief Polymorphic function wrapper.
* @ingroup functors
@@ -644,13 +632,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const _Functor*
target() const noexcept
{
- if _GLIBCXX17_CONSTEXPR (is_object<_Functor>::value)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ if constexpr (is_object<_Functor>::value)
{
- // For C++11 and C++14 if-constexpr is not used above, so
- // _Target_handler avoids ill-formed _Function_handler types.
- using _Handler = _Target_handler<_Res(_ArgTypes...), _Functor>;
-
- if (_M_manager == &_Handler::_M_manager
+ if (_M_manager == &_Handler<_Functor>::_M_manager
#if __cpp_rtti
|| (_M_manager && typeid(_Functor) == target_type())
#endif
@@ -661,6 +647,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __ptr._M_access<const _Functor*>();
}
}
+#pragma GCC diagnostic pop
return nullptr;
}
/// @}
diff --git a/libstdc++-v3/include/bits/std_mutex.h b/libstdc++-v3/include/bits/std_mutex.h
index 777097b..5f9f154 100644
--- a/libstdc++-v3/include/bits/std_mutex.h
+++ b/libstdc++-v3/include/bits/std_mutex.h
@@ -39,6 +39,7 @@
#else
#include <errno.h> // EBUSY
+#include <bits/chrono.h>
#include <bits/functexcept.h>
#include <bits/gthr.h>
@@ -210,8 +211,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__gthread_cond_t _M_cond;
#endif
};
- /// @endcond
+namespace chrono
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions"
+ // Convert a time_point to an absolute time represented as __gthread_time_t
+ // (which is typically just a typedef for struct timespec).
+ template<typename _Clock, typename _Dur>
+ [[__nodiscard__]] _GLIBCXX14_CONSTEXPR inline
+ __gthread_time_t
+ __to_timeout_gthread_time_t(const time_point<_Clock, _Dur>& __t)
+ {
+ auto __ts = chrono::__to_timeout_timespec(__t.time_since_epoch());
+ if constexpr (is_same<::timespec, __gthread_time_t>::value)
+ return __ts;
+ else if constexpr (is_convertible<::timespec, __gthread_time_t>::value)
+ return __ts;
+ else if constexpr (is_scalar<__gthread_time_t>::value) // Assume seconds:
+ return static_cast<__gthread_time_t>(__ts.tv_sec);
+ else // Assume this works and the members are in the correct order:
+ return __gthread_time_t{ __ts.tv_sec, __ts.tv_nsec };
+ }
+#pragma GCC diagnostic pop
+}
+ /// @endcond
#endif // _GLIBCXX_HAS_GTHREADS
/// Do not acquire ownership of the mutex.
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 71ead10..bbd1800 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -85,21 +85,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Iterator, typename _Compare>
_GLIBCXX20_CONSTEXPR
void
- __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b,
+ __move_median_to_first(_Iterator __result, _Iterator __a, _Iterator __b,
_Iterator __c, _Compare __comp)
{
- if (__comp(__a, __b))
+ if (__comp(*__a, *__b))
{
- if (__comp(__b, __c))
+ if (__comp(*__b, *__c))
std::iter_swap(__result, __b);
- else if (__comp(__a, __c))
+ else if (__comp(*__a, *__c))
std::iter_swap(__result, __c);
else
std::iter_swap(__result, __a);
}
- else if (__comp(__a, __c))
+ else if (__comp(*__a, *__c))
std::iter_swap(__result, __a);
- else if (__comp(__b, __c))
+ else if (__comp(*__b, *__c))
std::iter_swap(__result, __c);
else
std::iter_swap(__result, __b);
@@ -113,7 +113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Predicate __pred)
{
return std::__find_if(__first, __last,
- __gnu_cxx::__ops::__negate(__pred));
+ __gnu_cxx::__ops::not1(__pred));
}
/// Like find_if_not(), but uses and updates a count of the
@@ -125,7 +125,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred)
{
for (; __len; --__len, (void) ++__first)
- if (!__pred(__first))
+ if (!__pred(*__first))
break;
return __first;
}
@@ -162,7 +162,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__n = __count;
_ForwardIterator __i = __first;
++__i;
- while (__i != __last && __n != 1 && __unary_pred(__i))
+ while (__i != __last && __n != 1 && __unary_pred(*__i))
{
++__i;
--__n;
@@ -201,10 +201,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// __first here is always pointing to one past the last element of
// next possible match.
_RandomAccessIter __backTrack = __first;
- while (__unary_pred(--__backTrack))
+ while (__unary_pred(*--__backTrack))
{
if (--__remainder == 0)
- return (__first - __count); // Success
+ return __first - _DistanceType(__count); // Success
}
__remainder = __count + 1 - (__first - __backTrack);
}
@@ -339,7 +339,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return std::__find_end(__first1, __last1, __first2, __last2,
std::__iterator_category(__first1),
std::__iterator_category(__first2),
- __gnu_cxx::__ops::__iter_equal_to_iter());
+ __gnu_cxx::__ops::equal_to());
}
/**
@@ -390,7 +390,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return std::__find_end(__first1, __last1, __first2, __last2,
std::__iterator_category(__first1),
std::__iterator_category(__first2),
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ __comp);
}
#if __cplusplus >= 201103L
@@ -470,8 +470,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__find_if_not(__first, __last,
- __gnu_cxx::__ops::__pred_iter(__pred));
+ return std::__find_if_not(__first, __last, __pred);
}
/**
@@ -551,7 +550,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_OutputIterator __result, _Predicate __pred)
{
for (; __first != __last; ++__first)
- if (!__pred(__first))
+ if (!__pred(*__first))
{
*__result = *__first;
++__result;
@@ -588,7 +587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last);
return std::__remove_copy_if(__first, __last, __result,
- __gnu_cxx::__ops::__iter_equals_val(__value));
+ __gnu_cxx::__ops::__equal_to(__value));
}
/**
@@ -621,8 +620,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__remove_copy_if(__first, __last, __result,
- __gnu_cxx::__ops::__pred_iter(__pred));
+ return std::__remove_copy_if(__first, __last, __result, __pred);
}
#if __cplusplus >= 201103L
@@ -780,7 +778,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last);
return std::__remove_if(__first, __last,
- __gnu_cxx::__ops::__iter_equals_val(__value));
+ __gnu_cxx::__ops::__equal_to(__value));
}
/**
@@ -813,8 +811,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__remove_if(__first, __last,
- __gnu_cxx::__ops::__pred_iter(__pred));
+ return std::__remove_if(__first, __last, __pred);
}
template<typename _ForwardIterator, typename _BinaryPredicate>
@@ -828,7 +825,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_ForwardIterator __next = __first;
while (++__next != __last)
{
- if (__binary_pred(__first, __next))
+ if (__binary_pred(*__first, *__next))
return __first;
__first = __next;
}
@@ -850,7 +847,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_ForwardIterator __dest = __first;
++__first;
while (++__first != __last)
- if (!__binary_pred(__dest, __first))
+ if (!__binary_pred(*__dest, *__first))
*++__dest = _GLIBCXX_MOVE(*__first);
return ++__dest;
}
@@ -881,8 +878,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__unique(__first, __last,
- __gnu_cxx::__ops::__iter_equal_to_iter());
+ return std::__unique(__first, __last, __gnu_cxx::__ops::equal_to());
}
/**
@@ -914,66 +910,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__unique(__first, __last,
- __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
+ return std::__unique(__first, __last, __binary_pred);
}
- /**
- * This is an uglified
- * unique_copy(_InputIterator, _InputIterator, _OutputIterator,
- * _BinaryPredicate)
- * overloaded for forward iterators and output iterator as result.
- */
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4269. unique_copy passes arguments to its predicate backwards
+
+ // Implementation of std::unique_copy for forward iterators.
+ // This case is easy, just compare *i with *(i-1).
template<typename _ForwardIterator, typename _OutputIterator,
typename _BinaryPredicate>
_GLIBCXX20_CONSTEXPR
_OutputIterator
__unique_copy(_ForwardIterator __first, _ForwardIterator __last,
_OutputIterator __result, _BinaryPredicate __binary_pred,
- forward_iterator_tag, output_iterator_tag)
+ forward_iterator_tag)
{
- // concept requirements -- iterators already checked
- __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
- typename iterator_traits<_ForwardIterator>::value_type,
- typename iterator_traits<_ForwardIterator>::value_type>)
-
- _ForwardIterator __next = __first;
+ _ForwardIterator __prev = __first;
*__result = *__first;
- while (++__next != __last)
- if (!__binary_pred(__first, __next))
+ while (++__first != __last)
+ if (!__binary_pred(*__prev, *__first))
{
- __first = __next;
*++__result = *__first;
+ __prev = __first;
}
return ++__result;
}
- /**
- * This is an uglified
- * unique_copy(_InputIterator, _InputIterator, _OutputIterator,
- * _BinaryPredicate)
- * overloaded for input iterators and output iterator as result.
- */
+ // Implementation of std::unique_copy for non-forward iterators,
+ // where we cannot compare with elements written to the output.
template<typename _InputIterator, typename _OutputIterator,
typename _BinaryPredicate>
_GLIBCXX20_CONSTEXPR
_OutputIterator
- __unique_copy(_InputIterator __first, _InputIterator __last,
- _OutputIterator __result, _BinaryPredicate __binary_pred,
- input_iterator_tag, output_iterator_tag)
+ __unique_copy_1(_InputIterator __first, _InputIterator __last,
+ _OutputIterator __result, _BinaryPredicate __binary_pred,
+ __false_type)
{
- // concept requirements -- iterators already checked
- __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
- typename iterator_traits<_InputIterator>::value_type,
- typename iterator_traits<_InputIterator>::value_type>)
-
- typename iterator_traits<_InputIterator>::value_type __value = *__first;
- __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred))
- __rebound_pred
- = __gnu_cxx::__ops::__iter_comp_val(__binary_pred);
+ typedef typename iterator_traits<_InputIterator>::value_type _Val;
+ _Val __value = *__first;
*__result = __value;
while (++__first != __last)
- if (!__rebound_pred(__first, __value))
+ if (!__binary_pred(__value, *__first))
{
__value = *__first;
*++__result = __value;
@@ -981,31 +959,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return ++__result;
}
- /**
- * This is an uglified
- * unique_copy(_InputIterator, _InputIterator, _OutputIterator,
- * _BinaryPredicate)
- * overloaded for input iterators and forward iterator as result.
- */
+ // Implementation of std::unique_copy for non-forward iterators,
+ // where we can compare with the last element written to the output.
template<typename _InputIterator, typename _ForwardIterator,
typename _BinaryPredicate>
- _GLIBCXX20_CONSTEXPR
_ForwardIterator
- __unique_copy(_InputIterator __first, _InputIterator __last,
- _ForwardIterator __result, _BinaryPredicate __binary_pred,
- input_iterator_tag, forward_iterator_tag)
+ __unique_copy_1(_InputIterator __first, _InputIterator __last,
+ _ForwardIterator __result, _BinaryPredicate __binary_pred,
+ __true_type)
{
- // concept requirements -- iterators already checked
- __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
- typename iterator_traits<_ForwardIterator>::value_type,
- typename iterator_traits<_InputIterator>::value_type>)
*__result = *__first;
while (++__first != __last)
- if (!__binary_pred(__result, __first))
+ if (!__binary_pred(*__result, *__first))
*++__result = *__first;
return ++__result;
}
+ // Implementation of std::unique_copy for non-forward iterators.
+ // We cannot compare *i to *(i-1) so we need to either make a copy
+ // or compare with the last element written to the output range.
+ template<typename _InputIterator, typename _OutputIterator,
+ typename _BinaryPredicate>
+ _GLIBCXX20_CONSTEXPR
+ _OutputIterator
+ __unique_copy(_InputIterator __first, _InputIterator __last,
+ _OutputIterator __result, _BinaryPredicate __binary_pred,
+ input_iterator_tag)
+ {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2439. unique_copy() sometimes can't fall back to reading its output
+ typedef iterator_traits<_InputIterator> _InItTraits;
+ typedef iterator_traits<_OutputIterator> _OutItTraits;
+ typedef typename _OutItTraits::iterator_category _Cat;
+ const bool __output_is_fwd = __is_base_of(forward_iterator_tag, _Cat);
+ const bool __same_type = __is_same(typename _OutItTraits::value_type,
+ typename _InItTraits::value_type);
+ typedef __truth_type<__output_is_fwd && __same_type> __cmp_with_output;
+ return std::__unique_copy_1(__first, __last, __result, __binary_pred,
+ typename __cmp_with_output::__type());
+ }
+
+
/**
* This is an uglified reverse(_BidirectionalIterator,
* _BidirectionalIterator)
@@ -1259,9 +1253,12 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
{
if (__is_pod(_ValueType) && __k == 1)
{
+ _RandomAccessIterator __mid = __p + _Distance(__n - 1);
+ _RandomAccessIterator __end = __mid;
+ ++__end;
_ValueType __t = _GLIBCXX_MOVE(*__p);
- _GLIBCXX_MOVE3(__p + 1, __p + __n, __p);
- *(__p + __n - 1) = _GLIBCXX_MOVE(__t);
+ _GLIBCXX_MOVE3(__p + _Distance(1), __end, __p);
+ *__mid = _GLIBCXX_MOVE(__t);
return __ret;
}
_RandomAccessIterator __q = __p + __k;
@@ -1282,8 +1279,11 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
__k = __n - __k;
if (__is_pod(_ValueType) && __k == 1)
{
- _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1));
- _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n);
+ _RandomAccessIterator __mid = __p + _Distance(__n - 1);
+ _RandomAccessIterator __end = __mid;
+ ++__end;
+ _ValueType __t = _GLIBCXX_MOVE(*__mid);
+ _GLIBCXX_MOVE_BACKWARD3(__p, __mid, __end);
*__p = _GLIBCXX_MOVE(__t);
return __ret;
}
@@ -1440,10 +1440,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
// partition
/// This is a helper function...
- /// Requires __first != __last and !__pred(__first)
+ /// Requires __first != __last and !__pred(*__first)
/// and __len == distance(__first, __last).
///
- /// !__pred(__first) allows us to guarantee that we don't
+ /// !__pred(*__first) allows us to guarantee that we don't
/// move-assign an element onto itself.
template<typename _ForwardIterator, typename _Pointer, typename _Predicate,
typename _Distance>
@@ -1463,14 +1463,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
_ForwardIterator __result1 = __first;
_Pointer __result2 = __buffer;
- // The precondition guarantees that !__pred(__first), so
+ // The precondition guarantees that !__pred(*__first), so
// move that element to the buffer before starting the loop.
// This ensures that we only call __pred once per element.
*__result2 = _GLIBCXX_MOVE(*__first);
++__result2;
++__first;
for (; __first != __last; ++__first)
- if (__pred(__first))
+ if (__pred(*__first))
{
*__result1 = _GLIBCXX_MOVE(*__first);
++__result1;
@@ -1576,8 +1576,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__stable_partition(__first, __last,
- __gnu_cxx::__ops::__pred_iter(__pred));
+ return std::__stable_partition(__first, __last, __pred);
}
#endif // HOSTED
@@ -1593,7 +1592,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
{
std::__make_heap(__first, __middle, __comp);
for (_RandomAccessIterator __i = __middle; __i < __last; ++__i)
- if (__comp(__i, __first))
+ if (__comp(*__i, *__first))
std::__pop_heap(__first, __middle, __i, __comp);
}
@@ -1626,7 +1625,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
std::__make_heap(__result_first, __result_real_last, __comp);
while (__first != __last)
{
- if (__comp(__first, __result_first))
+ if (__comp(*__first, *__result_first))
std::__adjust_heap(__result_first, _DistanceType(0),
_DistanceType(__result_real_last
- __result_first),
@@ -1684,7 +1683,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
return std::__partial_sort_copy(__first, __last,
__result_first, __result_last,
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -1739,7 +1738,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
return std::__partial_sort_copy(__first, __last,
__result_first, __result_last,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ __comp);
}
/// @cond undocumented
@@ -1755,7 +1754,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__val = _GLIBCXX_MOVE(*__last);
_RandomAccessIterator __next = __last;
--__next;
- while (__comp(__val, __next))
+ while (__comp(__val, *__next))
{
*__last = _GLIBCXX_MOVE(*__next);
__last = __next;
@@ -1771,20 +1770,22 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__insertion_sort(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp)
{
- if (__first == __last) return;
+ if (__first == __last)
+ return;
- for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
+ typedef iterator_traits<_RandomAccessIterator> _IterTraits;
+ typedef typename _IterTraits::difference_type _Dist;
+
+ for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last; ++__i)
{
- if (__comp(__i, __first))
+ if (__comp(*__i, *__first))
{
- typename iterator_traits<_RandomAccessIterator>::value_type
- __val = _GLIBCXX_MOVE(*__i);
- _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1);
+ typename _IterTraits::value_type __val = _GLIBCXX_MOVE(*__i);
+ _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + _Dist(1));
*__first = _GLIBCXX_MOVE(__val);
}
else
- std::__unguarded_linear_insert(__i,
- __gnu_cxx::__ops::__val_comp_iter(__comp));
+ std::__unguarded_linear_insert(__i, __comp);
}
}
@@ -1796,8 +1797,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
_RandomAccessIterator __last, _Compare __comp)
{
for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
- std::__unguarded_linear_insert(__i,
- __gnu_cxx::__ops::__val_comp_iter(__comp));
+ std::__unguarded_linear_insert(__i, __comp);
}
/**
@@ -1813,10 +1813,13 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__final_insertion_sort(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp)
{
- if (__last - __first > int(_S_threshold))
+ typename iterator_traits<_RandomAccessIterator>::difference_type
+ __threshold = _S_threshold;
+
+ if (__last - __first > __threshold)
{
- std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
- std::__unguarded_insertion_sort(__first + int(_S_threshold), __last,
+ std::__insertion_sort(__first, __first + __threshold, __comp);
+ std::__unguarded_insertion_sort(__first + __threshold, __last,
__comp);
}
else
@@ -1833,10 +1836,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
{
while (true)
{
- while (__comp(__first, __pivot))
+ while (__comp(*__first, *__pivot))
++__first;
--__last;
- while (__comp(__pivot, __last))
+ while (__comp(*__pivot, *__last))
--__last;
if (!(__first < __last))
return __first;
@@ -1852,10 +1855,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__unguarded_partition_pivot(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp)
{
- _RandomAccessIterator __mid = __first + (__last - __first) / 2;
- std::__move_median_to_first(__first, __first + 1, __mid, __last - 1,
+ typedef iterator_traits<_RandomAccessIterator> _IterTraits;
+ typedef typename _IterTraits::difference_type _Dist;
+
+ _RandomAccessIterator __mid = __first + _Dist((__last - __first) / 2);
+ _RandomAccessIterator __second = __first + _Dist(1);
+ std::__move_median_to_first(__first, __second, __mid, __last - _Dist(1),
__comp);
- return std::__unguarded_partition(__first + 1, __last, __first, __comp);
+ return std::__unguarded_partition(__second, __last, __first, __comp);
}
template<typename _RandomAccessIterator, typename _Compare>
@@ -1917,11 +1924,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
_RandomAccessIterator __last, _Size __depth_limit,
_Compare __comp)
{
+ _RandomAccessIterator __after_nth = __nth;
+ ++__after_nth;
+
while (__last - __first > 3)
{
if (__depth_limit == 0)
{
- std::__heap_select(__first, __nth + 1, __last, __comp);
+ std::__heap_select(__first, __after_nth, __last, __comp);
// Place the nth largest element in its final position.
std::iter_swap(__first, __nth);
return;
@@ -1971,8 +1981,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_partitioned_lower_pred(__first, __last,
__val, __comp);
- return std::__lower_bound(__first, __last, __val,
- __gnu_cxx::__ops::__iter_comp_val(__comp));
+ return std::__lower_bound(__first, __last, __val, __comp);
}
template<typename _ForwardIterator, typename _Tp, typename _Compare>
@@ -1991,7 +2000,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
_DistanceType __half = __len >> 1;
_ForwardIterator __middle = __first;
std::advance(__middle, __half);
- if (__comp(__val, __middle))
+ if (__comp(__val, *__middle))
__len = __half;
else
{
@@ -2027,7 +2036,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_partitioned_upper(__first, __last, __val);
return std::__upper_bound(__first, __last, __val,
- __gnu_cxx::__ops::__val_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -2058,17 +2067,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_partitioned_upper_pred(__first, __last,
__val, __comp);
- return std::__upper_bound(__first, __last, __val,
- __gnu_cxx::__ops::__val_comp_iter(__comp));
+ return std::__upper_bound(__first, __last, __val, __comp);
}
- template<typename _ForwardIterator, typename _Tp,
- typename _CompareItTp, typename _CompareTpIt>
+ template<typename _ForwardIterator, typename _Tp, typename _Compare>
_GLIBCXX20_CONSTEXPR
pair<_ForwardIterator, _ForwardIterator>
__equal_range(_ForwardIterator __first, _ForwardIterator __last,
- const _Tp& __val,
- _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it)
+ const _Tp& __val, _Compare __comp)
{
typedef typename iterator_traits<_ForwardIterator>::difference_type
_DistanceType;
@@ -2080,21 +2086,21 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
_DistanceType __half = __len >> 1;
_ForwardIterator __middle = __first;
std::advance(__middle, __half);
- if (__comp_it_val(__middle, __val))
+ if (__comp(*__middle, __val))
{
__first = __middle;
++__first;
__len = __len - __half - 1;
}
- else if (__comp_val_it(__val, __middle))
+ else if (__comp(__val, *__middle))
__len = __half;
else
{
_ForwardIterator __left
- = std::__lower_bound(__first, __middle, __val, __comp_it_val);
+ = std::__lower_bound(__first, __middle, __val, __comp);
std::advance(__first, __len);
_ForwardIterator __right
- = std::__upper_bound(++__middle, __first, __val, __comp_val_it);
+ = std::__upper_bound(++__middle, __first, __val, __comp);
return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
}
}
@@ -2134,8 +2140,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_partitioned_upper(__first, __last, __val);
return std::__equal_range(__first, __last, __val,
- __gnu_cxx::__ops::__iter_less_val(),
- __gnu_cxx::__ops::__val_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -2172,9 +2177,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_partitioned_upper_pred(__first, __last,
__val, __comp);
- return std::__equal_range(__first, __last, __val,
- __gnu_cxx::__ops::__iter_comp_val(__comp),
- __gnu_cxx::__ops::__val_comp_iter(__comp));
+ return std::__equal_range(__first, __last, __val, __comp);
}
/**
@@ -2203,8 +2206,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_partitioned_upper(__first, __last, __val);
_ForwardIterator __i
- = std::__lower_bound(__first, __last, __val,
- __gnu_cxx::__ops::__iter_less_val());
+ = std::__lower_bound(__first, __last, __val, __gnu_cxx::__ops::less());
return __i != __last && !(__val < *__i);
}
@@ -2239,8 +2241,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__val, __comp);
_ForwardIterator __i
- = std::__lower_bound(__first, __last, __val,
- __gnu_cxx::__ops::__iter_comp_val(__comp));
+ = std::__lower_bound(__first, __last, __val, __comp);
return __i != __last && !bool(__comp(__val, *__i));
}
@@ -2256,7 +2257,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
{
while (__first1 != __last1 && __first2 != __last2)
{
- if (__comp(__first2, __first1))
+ if (__comp(*__first2, *__first1))
{
*__result = _GLIBCXX_MOVE(*__first2);
++__first2;
@@ -2295,7 +2296,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
--__last2;
while (true)
{
- if (__comp(__last2, __last1))
+ if (__comp(*__last2, *__last1))
{
*--__result = _GLIBCXX_MOVE(*__last1);
if (__first1 == __last1)
@@ -2401,8 +2402,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__len11 = __len1 / 2;
std::advance(__first_cut, __len11);
__second_cut
- = std::__lower_bound(__middle, __last, *__first_cut,
- __gnu_cxx::__ops::__iter_comp_val(__comp));
+ = std::__lower_bound(__middle, __last, *__first_cut, __comp);
__len22 = std::distance(__middle, __second_cut);
}
else
@@ -2410,8 +2410,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__len22 = __len2 / 2;
std::advance(__second_cut, __len22);
__first_cut
- = std::__upper_bound(__first, __middle, *__second_cut,
- __gnu_cxx::__ops::__val_comp_iter(__comp));
+ = std::__upper_bound(__first, __middle, *__second_cut, __comp);
__len11 = std::distance(__first, __first_cut);
}
@@ -2445,7 +2444,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
if (__len1 + __len2 == 2)
{
- if (__comp(__middle, __first))
+ if (__comp(*__middle, *__first))
std::iter_swap(__first, __middle);
return;
}
@@ -2459,8 +2458,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__len11 = __len1 / 2;
std::advance(__first_cut, __len11);
__second_cut
- = std::__lower_bound(__middle, __last, *__first_cut,
- __gnu_cxx::__ops::__iter_comp_val(__comp));
+ = std::__lower_bound(__middle, __last, *__first_cut, __comp);
__len22 = std::distance(__middle, __second_cut);
}
else
@@ -2468,8 +2466,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__len22 = __len2 / 2;
std::advance(__second_cut, __len22);
__first_cut
- = std::__upper_bound(__first, __middle, *__second_cut,
- __gnu_cxx::__ops::__val_comp_iter(__comp));
+ = std::__upper_bound(__first, __middle, *__second_cut, __comp);
__len11 = std::distance(__first, __first_cut);
}
@@ -2512,7 +2509,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
// [first,middle) and [middle,last).
_TmpBuf __buf(__first, std::min(__len1, __len2));
- if (__builtin_expect(__buf.size() == __buf.requested_size(), true))
+ if (__builtin_expect(__buf.size() == __buf._M_requested_size(), true))
std::__merge_adaptive
(__first, __middle, __last, __len1, __len2, __buf.begin(), __comp);
else if (__builtin_expect(__buf.begin() == 0, false))
@@ -2563,7 +2560,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_irreflexive(__first, __last);
std::__inplace_merge(__first, __middle, __last,
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -2606,8 +2603,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_sorted_pred(__middle, __last, __comp);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- std::__inplace_merge(__first, __middle, __last,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ std::__inplace_merge(__first, __middle, __last, __comp);
}
@@ -2621,7 +2617,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
{
while (__first1 != __last1 && __first2 != __last2)
{
- if (__comp(__first2, __first1))
+ if (__comp(*__first2, *__first1))
{
*__result = _GLIBCXX_MOVE(*__first2);
++__first2;
@@ -2786,9 +2782,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
{
while (__first1 != __last1 && __first2 != __last2)
{
- if (__comp(__first2, __first1))
+ if (__comp(*__first2, *__first1))
return false;
- if (!__comp(__first1, __first2))
+ if (!__comp(*__first1, *__first2))
++__first2;
++__first1;
}
@@ -2835,7 +2831,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_irreflexive2(__first2, __last2);
return std::__includes(__first1, __last1, __first2, __last2,
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -2881,8 +2877,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
__glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
- return std::__includes(__first1, __last1, __first2, __last2,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return std::__includes(__first1, __last1, __first2, __last2, __comp);
}
// nth_element
@@ -2914,10 +2909,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
{
_BidirectionalIterator __ii = __i;
--__i;
- if (__comp(__i, __ii))
+ if (__comp(*__i, *__ii))
{
_BidirectionalIterator __j = __last;
- while (!__comp(__i, --__j))
+ while (!__comp(*__i, *--__j))
{}
std::iter_swap(__i, __j);
std::__reverse(__ii, __last,
@@ -2959,8 +2954,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last);
- return std::__next_permutation
- (__first, __last, __gnu_cxx::__ops::__iter_less_iter());
+ return std::__next_permutation(__first, __last, __gnu_cxx::__ops::less());
}
/**
@@ -2993,8 +2987,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- return std::__next_permutation
- (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return std::__next_permutation(__first, __last, __comp);
}
template<typename _BidirectionalIterator, typename _Compare>
@@ -3016,10 +3009,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
{
_BidirectionalIterator __ii = __i;
--__i;
- if (__comp(__ii, __i))
+ if (__comp(*__ii, *__i))
{
_BidirectionalIterator __j = __last;
- while (!__comp(--__j, __i))
+ while (!__comp(*--__j, *__i))
{}
std::iter_swap(__i, __j);
std::__reverse(__ii, __last,
@@ -3062,8 +3055,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last);
- return std::__prev_permutation(__first, __last,
- __gnu_cxx::__ops::__iter_less_iter());
+ return std::__prev_permutation(__first, __last, __gnu_cxx::__ops::less());
}
/**
@@ -3096,8 +3088,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- return std::__prev_permutation(__first, __last,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return std::__prev_permutation(__first, __last, __comp);
}
// replace
@@ -3112,7 +3103,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
_Predicate __pred, const _Tp& __new_value)
{
for (; __first != __last; ++__first, (void)++__result)
- if (__pred(__first))
+ if (__pred(*__first))
*__result = __new_value;
else
*__result = *__first;
@@ -3149,8 +3140,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_valid_range(__first, __last);
return std::__replace_copy_if(__first, __last, __result,
- __gnu_cxx::__ops::__iter_equals_val(__old_value),
- __new_value);
+ __gnu_cxx::__ops::__equal_to(__old_value),
+ __new_value);
}
/**
@@ -3184,9 +3175,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__replace_copy_if(__first, __last, __result,
- __gnu_cxx::__ops::__pred_iter(__pred),
- __new_value);
+ return std::__replace_copy_if(__first, __last, __result, __pred,
+ __new_value);
}
#if __cplusplus >= 201103L
@@ -3230,7 +3220,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
_ForwardIterator __next = __first;
for (++__next; __next != __last; __first = __next, (void)++__next)
- if (__comp(__next, __first))
+ if (__comp(*__next, *__first))
return __next;
return __next;
}
@@ -3256,7 +3246,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_irreflexive(__first, __last);
return std::__is_sorted_until(__first, __last,
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -3282,8 +3272,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- return std::__is_sorted_until(__first, __last,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return std::__is_sorted_until(__first, __last, __comp);
}
/**
@@ -3336,7 +3325,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
return std::make_pair(__first, __first);
_ForwardIterator __min{}, __max{};
- if (__comp(__next, __first))
+ if (__comp(*__next, *__first))
{
__min = __next;
__max = __first;
@@ -3355,25 +3344,25 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__next = __first;
if (++__next == __last)
{
- if (__comp(__first, __min))
+ if (__comp(*__first, *__min))
__min = __first;
- else if (!__comp(__first, __max))
+ else if (!__comp(*__first, *__max))
__max = __first;
break;
}
- if (__comp(__next, __first))
+ if (__comp(*__next, *__first))
{
- if (__comp(__next, __min))
+ if (__comp(*__next, *__min))
__min = __next;
- if (!__comp(__first, __max))
+ if (!__comp(*__first, *__max))
__max = __first;
}
else
{
- if (__comp(__first, __min))
+ if (__comp(*__first, *__min))
__min = __first;
- if (!__comp(__next, __max))
+ if (!__comp(*__next, *__max))
__max = __next;
}
@@ -3407,8 +3396,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last);
- return std::__minmax_element(__first, __last,
- __gnu_cxx::__ops::__iter_less_iter());
+ return std::__minmax_element(__first, __last, __gnu_cxx::__ops::less());
}
/**
@@ -3437,8 +3425,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- return std::__minmax_element(__first, __last,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return std::__minmax_element(__first, __last, __comp);
}
template<typename _Tp>
@@ -3449,7 +3436,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_irreflexive(__l.begin(), __l.end());
pair<const _Tp*, const _Tp*> __p =
std::__minmax_element(__l.begin(), __l.end(),
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
return std::make_pair(*__p.first, *__p.second);
}
@@ -3460,8 +3447,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
{
__glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp);
pair<const _Tp*, const _Tp*> __p =
- std::__minmax_element(__l.begin(), __l.end(),
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ std::__minmax_element(__l.begin(), __l.end(), __comp);
return std::make_pair(*__p.first, *__p.second);
}
@@ -3494,11 +3480,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
typename iterator_traits<_ForwardIterator2>::value_type>)
__glibcxx_requires_valid_range(__first1, __last1);
- return std::__is_permutation(__first1, __last1, __first2,
- __gnu_cxx::__ops::__iter_comp_iter(__pred));
+ return std::__is_permutation(__first1, __last1, __first2, __pred);
}
-#if __cplusplus > 201103L
+#if __glibcxx_robust_nonmodifying_seq_ops // C++ >= 14
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
template<typename _ForwardIterator1, typename _ForwardIterator2,
@@ -3526,7 +3511,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
// have the same elements in the same order.
for (; __first1 != __last1 && __first2 != __last2;
++__first1, (void)++__first2)
- if (!__pred(__first1, __first2))
+ if (!__pred(*__first1, *__first2))
break;
if constexpr (__ra_iters)
@@ -3546,16 +3531,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan)
{
- if (__scan != std::__find_if(__first1, __scan,
- __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)))
+ auto&& __scan_val = *__scan;
+ auto __scaneq = __gnu_cxx::__ops::bind1st(__pred, __scan_val);
+ if (__scan != std::__find_if(__first1, __scan, __scaneq))
continue; // We've seen this one before.
- auto __matches = std::__count_if(__first2, __last2,
- __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan));
+ auto __matches = std::__count_if(__first2, __last2, __scaneq);
if (0 == __matches
- || std::__count_if(__scan, __last1,
- __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
- != __matches)
+ || std::__count_if(__scan, __last1, __scaneq) != __matches)
return false;
}
return true;
@@ -3584,9 +3567,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_valid_range(__first1, __last1);
__glibcxx_requires_valid_range(__first2, __last2);
- return
- std::__is_permutation(__first1, __last1, __first2, __last2,
- __gnu_cxx::__ops::__iter_equal_to_iter());
+ return std::__is_permutation(__first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::equal_to());
}
/**
@@ -3615,9 +3597,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
__glibcxx_requires_valid_range(__first2, __last2);
return std::__is_permutation(__first1, __last1, __first2, __last2,
- __gnu_cxx::__ops::__iter_comp_iter(__pred));
+ __pred);
}
-#endif // C++14
+#endif // __glibcxx_robust_nonmodifying_seq_ops
#ifdef __glibcxx_clamp // C++ >= 17
/**
@@ -3823,7 +3805,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
{
if (__n2 <= 0)
return __first;
- auto __last = __first + __n2;
+ typename iterator_traits<_InputIterator>::difference_type __d = __n2;
+ auto __last = __first + __d;
std::for_each(__first, __last, std::move(__f));
return __last;
}
@@ -3893,7 +3876,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
#endif
return std::__find_if(__first, __last,
- __gnu_cxx::__ops::__iter_equals_val(__val));
+ __gnu_cxx::__ops::__equal_to(__val));
}
/**
@@ -3918,8 +3901,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__find_if(__first, __last,
- __gnu_cxx::__ops::__pred_iter(__pred));
+ return std::__find_if(__first, __last, __pred);
}
/**
@@ -4024,7 +4006,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first, __last);
return std::__adjacent_find(__first, __last,
- __gnu_cxx::__ops::__iter_equal_to_iter());
+ __gnu_cxx::__ops::equal_to());
}
/**
@@ -4051,8 +4033,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__adjacent_find(__first, __last,
- __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
+ return std::__adjacent_find(__first, __last, __binary_pred);
}
/**
@@ -4076,7 +4057,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first, __last);
return std::__count_if(__first, __last,
- __gnu_cxx::__ops::__iter_equals_val(__value));
+ __gnu_cxx::__ops::__equal_to(__value));
}
/**
@@ -4099,8 +4080,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__count_if(__first, __last,
- __gnu_cxx::__ops::__pred_iter(__pred));
+ return std::__count_if(__first, __last, __pred);
}
/**
@@ -4145,7 +4125,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first2, __last2);
return std::__search(__first1, __last1, __first2, __last2,
- __gnu_cxx::__ops::__iter_equal_to_iter());
+ __gnu_cxx::__ops::equal_to());
}
/**
@@ -4176,7 +4156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first, __last);
return std::__search_n(__first, __last, __count,
- __gnu_cxx::__ops::__iter_equals_val(__val));
+ __gnu_cxx::__ops::__equal_to(__val));
}
@@ -4212,7 +4192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first, __last);
return std::__search_n(__first, __last, __count,
- __gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val));
+ __gnu_cxx::__ops::bind2nd(__binary_pred, __val));
}
#if __cplusplus >= 201703L
@@ -4469,9 +4449,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
if (__first == __last)
return __result;
return std::__unique_copy(__first, __last, __result,
- __gnu_cxx::__ops::__iter_equal_to_iter(),
- std::__iterator_category(__first),
- std::__iterator_category(__result));
+ __gnu_cxx::__ops::equal_to(),
+ std::__iterator_category(__first));
}
/**
@@ -4505,13 +4484,14 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
+ __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
+ typename iterator_traits<_InputIterator>::value_type,
+ typename iterator_traits<_InputIterator>::value_type>)
if (__first == __last)
return __result;
- return std::__unique_copy(__first, __last, __result,
- __gnu_cxx::__ops::__iter_comp_iter(__binary_pred),
- std::__iterator_category(__first),
- std::__iterator_category(__result));
+ return std::__unique_copy(__first, __last, __result, __binary_pred,
+ std::__iterator_category(__first));
}
#if __cplusplus <= 201103L || _GLIBCXX_USE_DEPRECATED
@@ -4544,6 +4524,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
if (__first == __last)
return;
+ typedef typename iterator_traits<_RandomAccessIterator>::difference_type
+ _Dist;
+
#if RAND_MAX < __INT_MAX__
if (__builtin_expect((__last - __first) >= RAND_MAX / 4, 0))
{
@@ -4551,14 +4534,15 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
// instead of using rand() for all the random numbers needed.
unsigned __xss
= (unsigned)std::rand() ^ ((unsigned)std::rand() << 15);
- for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
+ for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last;
+ ++__i)
{
__xss += !__xss;
__xss ^= __xss << 13;
__xss ^= __xss >> 17;
__xss ^= __xss << 5;
- _RandomAccessIterator __j = __first
- + (__xss % ((__i - __first) + 1));
+ _RandomAccessIterator __j
+ = __first + _Dist(__xss % ((__i - __first) + 1));
if (__i != __j)
std::iter_swap(__i, __j);
}
@@ -4566,11 +4550,11 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
}
#endif
- for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
+ for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last; ++__i)
{
// XXX rand() % N is not uniformly distributed
- _RandomAccessIterator __j = __first
- + (std::rand() % ((__i - __first) + 1));
+ _RandomAccessIterator __j
+ = __first + _Dist(std::rand() % ((__i - __first) + 1));
if (__i != __j)
std::iter_swap(__i, __j);
}
@@ -4611,9 +4595,14 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
if (__first == __last)
return;
- for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
+
+ typedef typename iterator_traits<_RandomAccessIterator>::difference_type
+ _Dist;
+
+ for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last; ++__i)
{
- _RandomAccessIterator __j = __first + __rand((__i - __first) + 1);
+ _RandomAccessIterator __j
+ = __first + _Dist(__rand((__i - __first) + 1));
if (__i != __j)
std::iter_swap(__i, __j);
}
@@ -4688,7 +4677,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive(__first, __last);
std::__partial_sort(__first, __middle, __last,
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -4728,8 +4717,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__middle, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- std::__partial_sort(__first, __middle, __last,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ std::__partial_sort(__first, __middle, __last, __comp);
}
/**
@@ -4767,7 +4755,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
std::__introselect(__first, __nth, __last,
std::__lg(__last - __first) * 2,
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -4808,7 +4796,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
std::__introselect(__first, __nth, __last,
std::__lg(__last - __first) * 2,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ __comp);
}
/**
@@ -4838,7 +4826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last);
- std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
+ std::__sort(__first, __last, __gnu_cxx::__ops::less());
}
/**
@@ -4871,7 +4859,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ std::__sort(__first, __last, __comp);
}
template<typename _InputIterator1, typename _InputIterator2,
@@ -4884,7 +4872,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
{
while (__first1 != __last1 && __first2 != __last2)
{
- if (__comp(__first2, __first1))
+ if (__comp(*__first2, *__first1))
{
*__result = *__first2;
++__first2;
@@ -4942,9 +4930,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive2(__first1, __last1);
__glibcxx_requires_irreflexive2(__first2, __last2);
- return _GLIBCXX_STD_A::__merge(__first1, __last1,
- __first2, __last2, __result,
- __gnu_cxx::__ops::__iter_less_iter());
+ return _GLIBCXX_STD_A::__merge(__first1, __last1, __first2, __last2,
+ __result, __gnu_cxx::__ops::less());
}
/**
@@ -4993,9 +4980,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
__glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
- return _GLIBCXX_STD_A::__merge(__first1, __last1,
- __first2, __last2, __result,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return _GLIBCXX_STD_A::__merge(__first1, __last1, __first2, __last2,
+ __result, __comp);
}
template<typename _RandomAccessIterator, typename _Compare>
@@ -5024,7 +5010,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
// so the buffer only needs to fit half the range at once.
_TmpBuf __buf(__first, (__last - __first + 1) / 2);
- if (__builtin_expect(__buf.requested_size() == __buf.size(), true))
+ if (__builtin_expect(__buf._M_requested_size() == __buf.size(), true))
std::__stable_sort_adaptive(__first,
__first + _DistanceType(__buf.size()),
__last, __buf.begin(), __comp);
@@ -5069,7 +5055,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive(__first, __last);
_GLIBCXX_STD_A::__stable_sort(__first, __last,
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -5105,13 +5091,11 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- _GLIBCXX_STD_A::__stable_sort(__first, __last,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ _GLIBCXX_STD_A::__stable_sort(__first, __last, __comp);
}
template<typename _InputIterator1, typename _InputIterator2,
- typename _OutputIterator,
- typename _Compare>
+ typename _OutputIterator, typename _Compare>
_GLIBCXX20_CONSTEXPR
_OutputIterator
__set_union(_InputIterator1 __first1, _InputIterator1 __last1,
@@ -5120,12 +5104,12 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
{
while (__first1 != __last1 && __first2 != __last2)
{
- if (__comp(__first1, __first2))
+ if (__comp(*__first1, *__first2))
{
*__result = *__first1;
++__first1;
}
- else if (__comp(__first2, __first1))
+ else if (__comp(*__first2, *__first1))
{
*__result = *__first2;
++__first2;
@@ -5187,9 +5171,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive2(__first1, __last1);
__glibcxx_requires_irreflexive2(__first2, __last2);
- return _GLIBCXX_STD_A::__set_union(__first1, __last1,
- __first2, __last2, __result,
- __gnu_cxx::__ops::__iter_less_iter());
+ return _GLIBCXX_STD_A::__set_union(__first1, __last1, __first2, __last2,
+ __result, __gnu_cxx::__ops::less());
}
/**
@@ -5238,14 +5221,12 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
__glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
- return _GLIBCXX_STD_A::__set_union(__first1, __last1,
- __first2, __last2, __result,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return _GLIBCXX_STD_A::__set_union(__first1, __last1, __first2, __last2,
+ __result, __comp);
}
template<typename _InputIterator1, typename _InputIterator2,
- typename _OutputIterator,
- typename _Compare>
+ typename _OutputIterator, typename _Compare>
_GLIBCXX20_CONSTEXPR
_OutputIterator
__set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
@@ -5253,9 +5234,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
_OutputIterator __result, _Compare __comp)
{
while (__first1 != __last1 && __first2 != __last2)
- if (__comp(__first1, __first2))
+ if (__comp(*__first1, *__first2))
++__first1;
- else if (__comp(__first2, __first1))
+ else if (__comp(*__first2, *__first1))
++__first2;
else
{
@@ -5309,9 +5290,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive2(__first1, __last1);
__glibcxx_requires_irreflexive2(__first2, __last2);
- return _GLIBCXX_STD_A::__set_intersection(__first1, __last1,
- __first2, __last2, __result,
- __gnu_cxx::__ops::__iter_less_iter());
+ return _GLIBCXX_STD_A::
+ __set_intersection(__first1, __last1, __first2, __last2,
+ __result, __gnu_cxx::__ops::less());
}
/**
@@ -5359,14 +5340,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
__glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
- return _GLIBCXX_STD_A::__set_intersection(__first1, __last1,
- __first2, __last2, __result,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return _GLIBCXX_STD_A::
+ __set_intersection(__first1, __last1, __first2, __last2,
+ __result, __comp);
}
template<typename _InputIterator1, typename _InputIterator2,
- typename _OutputIterator,
- typename _Compare>
+ typename _OutputIterator, typename _Compare>
_GLIBCXX20_CONSTEXPR
_OutputIterator
__set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
@@ -5374,13 +5354,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
_OutputIterator __result, _Compare __comp)
{
while (__first1 != __last1 && __first2 != __last2)
- if (__comp(__first1, __first2))
+ if (__comp(*__first1, *__first2))
{
*__result = *__first1;
++__first1;
++__result;
}
- else if (__comp(__first2, __first1))
+ else if (__comp(*__first2, *__first1))
++__first2;
else
{
@@ -5434,9 +5414,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive2(__first1, __last1);
__glibcxx_requires_irreflexive2(__first2, __last2);
- return _GLIBCXX_STD_A::__set_difference(__first1, __last1,
- __first2, __last2, __result,
- __gnu_cxx::__ops::__iter_less_iter());
+ return _GLIBCXX_STD_A::
+ __set_difference(__first1, __last1, __first2, __last2, __result,
+ __gnu_cxx::__ops::less());
}
/**
@@ -5486,9 +5466,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
__glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
- return _GLIBCXX_STD_A::__set_difference(__first1, __last1,
- __first2, __last2, __result,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return _GLIBCXX_STD_A::
+ __set_difference(__first1, __last1, __first2, __last2, __result,
+ __comp);
}
template<typename _InputIterator1, typename _InputIterator2,
@@ -5504,13 +5484,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
_Compare __comp)
{
while (__first1 != __last1 && __first2 != __last2)
- if (__comp(__first1, __first2))
+ if (__comp(*__first1, *__first2))
{
*__result = *__first1;
++__first1;
++__result;
}
- else if (__comp(__first2, __first1))
+ else if (__comp(*__first2, *__first1))
{
*__result = *__first2;
++__first2;
@@ -5569,9 +5549,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive2(__first1, __last1);
__glibcxx_requires_irreflexive2(__first2, __last2);
- return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1,
- __first2, __last2, __result,
- __gnu_cxx::__ops::__iter_less_iter());
+ return _GLIBCXX_STD_A::
+ __set_symmetric_difference(__first1, __last1, __first2, __last2,
+ __result, __gnu_cxx::__ops::less());
}
/**
@@ -5622,9 +5602,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
__glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
- return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1,
- __first2, __last2, __result,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return _GLIBCXX_STD_A::
+ __set_symmetric_difference(__first1, __last1, __first2, __last2,
+ __result, __comp);
}
template<typename _ForwardIterator, typename _Compare>
@@ -5637,7 +5617,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
return __first;
_ForwardIterator __result = __first;
while (++__first != __last)
- if (__comp(__first, __result))
+ if (__comp(*__first, *__result))
__result = __first;
return __result;
}
@@ -5651,8 +5631,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _ForwardIterator>
_GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR
- _ForwardIterator
- inline min_element(_ForwardIterator __first, _ForwardIterator __last)
+ inline _ForwardIterator
+ min_element(_ForwardIterator __first, _ForwardIterator __last)
{
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
@@ -5662,7 +5642,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive(__first, __last);
return _GLIBCXX_STD_A::__min_element(__first, __last,
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -5688,8 +5668,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- return _GLIBCXX_STD_A::__min_element(__first, __last,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return _GLIBCXX_STD_A::__min_element(__first, __last, __comp);
}
template<typename _ForwardIterator, typename _Compare>
@@ -5701,7 +5680,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
if (__first == __last) return __first;
_ForwardIterator __result = __first;
while (++__first != __last)
- if (__comp(__result, __first))
+ if (__comp(*__result, *__first))
__result = __first;
return __result;
}
@@ -5726,7 +5705,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_irreflexive(__first, __last);
return _GLIBCXX_STD_A::__max_element(__first, __last,
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
/**
@@ -5752,54 +5731,51 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- return _GLIBCXX_STD_A::__max_element(__first, __last,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return _GLIBCXX_STD_A::__max_element(__first, __last, __comp);
}
#if __cplusplus >= 201103L
// N2722 + DR 915.
template<typename _Tp>
- _GLIBCXX14_CONSTEXPR
+ _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR
inline _Tp
min(initializer_list<_Tp> __l)
{
__glibcxx_requires_irreflexive(__l.begin(), __l.end());
return *_GLIBCXX_STD_A::__min_element(__l.begin(), __l.end(),
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
template<typename _Tp, typename _Compare>
- _GLIBCXX14_CONSTEXPR
+ _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR
inline _Tp
min(initializer_list<_Tp> __l, _Compare __comp)
{
__glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp);
- return *_GLIBCXX_STD_A::__min_element(__l.begin(), __l.end(),
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return *_GLIBCXX_STD_A::__min_element(__l.begin(), __l.end(), __comp);
}
template<typename _Tp>
- _GLIBCXX14_CONSTEXPR
+ _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR
inline _Tp
max(initializer_list<_Tp> __l)
{
__glibcxx_requires_irreflexive(__l.begin(), __l.end());
return *_GLIBCXX_STD_A::__max_element(__l.begin(), __l.end(),
- __gnu_cxx::__ops::__iter_less_iter());
+ __gnu_cxx::__ops::less());
}
template<typename _Tp, typename _Compare>
- _GLIBCXX14_CONSTEXPR
+ _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR
inline _Tp
max(initializer_list<_Tp> __l, _Compare __comp)
{
__glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp);
- return *_GLIBCXX_STD_A::__max_element(__l.begin(), __l.end(),
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ return *_GLIBCXX_STD_A::__max_element(__l.begin(), __l.end(), __comp);
}
#endif // C++11
-#if __cplusplus >= 201402L
+#if __cplusplus >= 201402L // C++17 std::sample and C++14 experimental::sample
/// Reservoir sampling algorithm.
template<typename _InputIterator, typename _RandomAccessIterator,
typename _Size, typename _UniformRandomBitGenerator>
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index 119dbe9..443cbef 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -1046,19 +1046,26 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
__size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_2 __n) { return __n; }
#endif
#if defined(__GLIBCXX_TYPE_INT_N_3)
- __extension__ inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_3
- __size_to_integer(__GLIBCXX_TYPE_INT_N_3 __n) { return __n; }
__extension__ inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3
+ __size_to_integer(__GLIBCXX_TYPE_INT_N_3 __n) { return __n; }
+ __extension__ inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_3
__size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_3 __n) { return __n; }
#endif
+#if defined(__STRICT_ANSI__) && defined(__SIZEOF_INT128__)
+ __extension__ inline _GLIBCXX_CONSTEXPR __int128
+ __size_to_integer(__int128 __n) { return __n; }
+ __extension__ inline _GLIBCXX_CONSTEXPR unsigned __int128
+ __size_to_integer(unsigned __int128 __n) { return __n; }
+#endif
+
inline _GLIBCXX_CONSTEXPR long long
__size_to_integer(float __n) { return (long long)__n; }
inline _GLIBCXX_CONSTEXPR long long
__size_to_integer(double __n) { return (long long)__n; }
inline _GLIBCXX_CONSTEXPR long long
__size_to_integer(long double __n) { return (long long)__n; }
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
+#ifdef _GLIBCXX_USE_FLOAT128
__extension__ inline _GLIBCXX_CONSTEXPR long long
__size_to_integer(__float128 __n) { return (long long)__n; }
#endif
@@ -1143,10 +1150,12 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
if (__n <= 0)
return __first;
- __glibcxx_requires_can_increment(__first, __n);
+ typename iterator_traits<_OutputIterator>::difference_type __d = __n;
+ __glibcxx_requires_can_increment(__first, __d);
- std::__fill_a(__first, __first + __n, __value);
- return __first + __n;
+ _OutputIterator __last = __first + __d;
+ std::__fill_a(__first, __last, __value);
+ return __last;
}
/**
@@ -1303,11 +1312,11 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
__newlast1(_RAI1 __first1, _RAI1 __last1,
_RAI2 __first2, _RAI2 __last2)
{
- const typename iterator_traits<_RAI1>::difference_type
- __diff1 = __last1 - __first1;
- const typename iterator_traits<_RAI2>::difference_type
- __diff2 = __last2 - __first2;
- return __diff2 < __diff1 ? __first1 + __diff2 : __last1;
+ typedef typename iterator_traits<_RAI1>::difference_type _Diff1;
+ typedef typename iterator_traits<_RAI2>::difference_type _Diff2;
+ const _Diff1 __diff1 = __last1 - __first1;
+ const _Diff2 __diff2 = __last2 - __first2;
+ return __diff2 < __diff1 ? __first1 + _Diff1(__diff2) : __last1;
}
template<typename _RAI>
@@ -1331,9 +1340,9 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
++__first1, (void)++__first2)
{
- if (__comp(__first1, __first2))
+ if (__comp(*__first1, *__first2))
return true;
- if (__comp(__first2, __first1))
+ if (__comp(*__first2, *__first1))
return false;
}
return __first1 == __last1 && __first2 != __last2;
@@ -1347,10 +1356,10 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
static bool
__lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2)
{
- using __gnu_cxx::__ops::__iter_less_iter;
+ using __gnu_cxx::__ops::less;
return std::__lexicographical_compare_impl(__first1, __last1,
__first2, __last2,
- __iter_less_iter());
+ less());
}
template<typename _II1, typename _II2>
@@ -1506,7 +1515,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
_DistanceType __half = __len >> 1;
_ForwardIterator __middle = __first;
std::advance(__middle, __half);
- if (__comp(__middle, __val))
+ if (__comp(*__middle, __val))
{
__first = __middle;
++__first;
@@ -1542,7 +1551,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
__glibcxx_requires_partitioned_lower(__first, __last, __val);
return std::__lower_bound(__first, __last, __val,
- __gnu_cxx::__ops::__iter_less_val());
+ __gnu_cxx::__ops::less());
}
/// This is a helper function for the sort routines and for random.tcc.
@@ -1816,8 +1825,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first2, __last2);
return std::__lexicographical_compare_impl
- (__first1, __last1, __first2, __last2,
- __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ (__first1, __last1, __first2, __last2, __comp);
}
#if __cpp_lib_three_way_comparison
@@ -1925,7 +1933,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _BinaryPredicate __binary_pred)
{
- while (__first1 != __last1 && __binary_pred(__first1, __first2))
+ while (__first1 != __last1 && __binary_pred(*__first1, *__first2))
{
++__first1;
++__first2;
@@ -1961,7 +1969,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first1, __last1);
return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2,
- __gnu_cxx::__ops::__iter_equal_to_iter());
+ __gnu_cxx::__ops::equal_to());
}
/**
@@ -1993,7 +2001,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first1, __last1);
return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2,
- __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
+ __binary_pred);
}
#if __glibcxx_robust_nonmodifying_seq_ops // C++ >= 14
@@ -2006,7 +2014,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
_BinaryPredicate __binary_pred)
{
while (__first1 != __last1 && __first2 != __last2
- && __binary_pred(__first1, __first2))
+ && __binary_pred(*__first1, *__first2))
{
++__first1;
++__first2;
@@ -2044,7 +2052,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first2, __last2);
return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2,
- __gnu_cxx::__ops::__iter_equal_to_iter());
+ __gnu_cxx::__ops::equal_to());
}
/**
@@ -2079,9 +2087,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first2, __last2);
return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2,
- __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
+ __binary_pred);
}
-#endif
+#endif // __glibcxx_robust_nonmodifying_seq_ops
_GLIBCXX_END_NAMESPACE_ALGO
@@ -2092,7 +2100,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
__find_if(_Iterator __first, _Iterator __last, _Predicate __pred)
{
#pragma GCC unroll 4
- while (__first != __last && !__pred(__first))
+ while (__first != __last && !__pred(*__first))
++__first;
return __first;
}
@@ -2104,7 +2112,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
{
typename iterator_traits<_InputIterator>::difference_type __n = 0;
for (; __first != __last; ++__first)
- if (__pred(__first))
+ if (__pred(*__first))
++__n;
return __n;
}
@@ -2121,7 +2129,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
_ForwardIterator __result = __first;
++__first;
for (; __first != __last; ++__first)
- if (!__pred(__first))
+ if (!__pred(*__first))
{
*__result = _GLIBCXX_MOVE(*__first);
++__result;
@@ -2141,20 +2149,21 @@ _GLIBCXX_END_NAMESPACE_ALGO
if (__first1 == __last1 || __first2 == __last2)
return __first1;
+ __decltype(*__first2) __first2_val(*__first2);
+ __decltype(__gnu_cxx::__ops::bind2nd(__predicate, __first2_val))
+ __match_first = __gnu_cxx::__ops::bind2nd(__predicate, __first2_val);
+
// Test for a pattern of length 1.
_ForwardIterator2 __p1(__first2);
if (++__p1 == __last2)
- return std::__find_if(__first1, __last1,
- __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
+ return std::__find_if(__first1, __last1, __match_first);
// General case.
_ForwardIterator1 __current = __first1;
for (;;)
{
- __first1 =
- std::__find_if(__first1, __last1,
- __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
+ __first1 = std::__find_if(__first1, __last1, __match_first);
if (__first1 == __last1)
return __last1;
@@ -2164,7 +2173,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
if (++__current == __last1)
return __last1;
- while (__predicate(__current, __p))
+ while (__predicate(*__current, *__p))
{
if (++__p == __last2)
return __first1;
@@ -2175,6 +2184,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
}
return __first1;
}
+#undef __match_first
#if __cplusplus >= 201103L
template<typename _ForwardIterator1, typename _ForwardIterator2,
@@ -2187,7 +2197,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
// Efficiently compare identical prefixes: O(N) if sequences
// have the same elements in the same order.
for (; __first1 != __last1; ++__first1, (void)++__first2)
- if (!__pred(__first1, __first2))
+ if (!__pred(*__first1, *__first2))
break;
if (__first1 == __last1)
@@ -2199,17 +2209,14 @@ _GLIBCXX_END_NAMESPACE_ALGO
std::advance(__last2, std::distance(__first1, __last1));
for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan)
{
- if (__scan != std::__find_if(__first1, __scan,
- __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)))
+ auto&& __scan_val = *__scan;
+ auto __scaneq = __gnu_cxx::__ops::bind1st(__pred, __scan_val);
+ if (__scan != std::__find_if(__first1, __scan, __scaneq))
continue; // We've seen this one before.
- auto __matches
- = std::__count_if(__first2, __last2,
- __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan));
- if (0 == __matches ||
- std::__count_if(__scan, __last1,
- __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
- != __matches)
+ auto __matches = std::__count_if(__first2, __last2, __scaneq);
+ if (0 == __matches
+ || std::__count_if(__scan, __last1, __scaneq) != __matches)
return false;
}
return true;
@@ -2242,7 +2249,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first1, __last1);
return std::__is_permutation(__first1, __last1, __first2,
- __gnu_cxx::__ops::__iter_equal_to_iter());
+ __gnu_cxx::__ops::equal_to());
}
#endif // C++11
@@ -2286,8 +2293,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first1, __last1);
__glibcxx_requires_valid_range(__first2, __last2);
- return std::__search(__first1, __last1, __first2, __last2,
- __gnu_cxx::__ops::__iter_comp_iter(__predicate));
+ return std::__search(__first1, __last1, __first2, __last2, __predicate);
}
_GLIBCXX_END_NAMESPACE_ALGO
diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h
index 23b8fb7..98b403c 100644
--- a/libstdc++-v3/include/bits/stl_construct.h
+++ b/libstdc++-v3/include/bits/stl_construct.h
@@ -82,7 +82,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if constexpr (__cplusplus > 201703L && is_array_v<_Tp>)
{
for (auto& __x : *__location)
- std::destroy_at(std::__addressof(__x));
+ std::destroy_at(std::addressof(__x));
}
else
__location->~_Tp();
@@ -123,7 +123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Construct(_Tp* __p, _Args&&... __args)
{
#if __cpp_constexpr_dynamic_alloc // >= C++20
- if (std::__is_constant_evaluated())
+ if (std::is_constant_evaluated())
{
// Allow std::_Construct to be used in constant expressions.
std::construct_at(__p, std::forward<_Args>(__args)...);
@@ -181,6 +181,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
for (; __first != __last; ++__first)
std::_Destroy(std::__addressof(*__first));
}
+
+ template<typename _ForwardIterator, typename _Size>
+ static _GLIBCXX20_CONSTEXPR _ForwardIterator
+ __destroy_n(_ForwardIterator __first, _Size __count)
+ {
+ for (; __count > 0; (void)++__first, --__count)
+ std::_Destroy(std::__addressof(*__first));
+ return __first;
+ }
};
template<>
@@ -189,6 +198,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _ForwardIterator>
static void
__destroy(_ForwardIterator, _ForwardIterator) { }
+
+ template<typename _ForwardIterator, typename _Size>
+ static _ForwardIterator
+ __destroy_n(_ForwardIterator __first, _Size __count)
+ {
+ std::advance(__first, __count);
+ return __first;
+ }
};
#endif
@@ -204,16 +221,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename iterator_traits<_ForwardIterator>::value_type
_Value_type;
#if __cplusplus >= 201103L
- // A deleted destructor is trivial, this ensures we reject such types:
- static_assert(is_destructible<_Value_type>::value,
- "value type is destructible");
- if constexpr (!__has_trivial_destructor(_Value_type))
+ if constexpr (!is_trivially_destructible<_Value_type>::value)
for (; __first != __last; ++__first)
- std::_Destroy(std::__addressof(*__first));
+ std::_Destroy(std::addressof(*__first));
#if __cpp_constexpr_dynamic_alloc // >= C++20
- else if (std::__is_constant_evaluated())
+ else if (std::is_constant_evaluated())
for (; __first != __last; ++__first)
- std::destroy_at(std::__addressof(*__first));
+ std::destroy_at(std::addressof(*__first));
#endif
#else
std::_Destroy_aux<__has_trivial_destructor(_Value_type)>::
@@ -221,33 +235,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
}
-#if __cplusplus < 201103L
- template<bool>
- struct _Destroy_n_aux
- {
- template<typename _ForwardIterator, typename _Size>
- static _GLIBCXX20_CONSTEXPR _ForwardIterator
- __destroy_n(_ForwardIterator __first, _Size __count)
- {
- for (; __count > 0; (void)++__first, --__count)
- std::_Destroy(std::__addressof(*__first));
- return __first;
- }
- };
-
- template<>
- struct _Destroy_n_aux<true>
- {
- template<typename _ForwardIterator, typename _Size>
- static _ForwardIterator
- __destroy_n(_ForwardIterator __first, _Size __count)
- {
- std::advance(__first, __count);
- return __first;
- }
- };
-#endif
-
/**
* Destroy a range of objects. If the value_type of the object has
* a trivial destructor, the compiler should optimize all of this
@@ -260,22 +247,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename iterator_traits<_ForwardIterator>::value_type
_Value_type;
#if __cplusplus >= 201103L
- // A deleted destructor is trivial, this ensures we reject such types:
- static_assert(is_destructible<_Value_type>::value,
- "value type is destructible");
- if constexpr (!__has_trivial_destructor(_Value_type))
+ if constexpr (!is_trivially_destructible<_Value_type>::value)
for (; __count > 0; (void)++__first, --__count)
- std::_Destroy(std::__addressof(*__first));
+ std::_Destroy(std::addressof(*__first));
#if __cpp_constexpr_dynamic_alloc // >= C++20
- else if (std::__is_constant_evaluated())
+ else if (std::is_constant_evaluated())
for (; __count > 0; (void)++__first, --__count)
- std::destroy_at(std::__addressof(*__first));
+ std::destroy_at(std::addressof(*__first));
#endif
else
std::advance(__first, __count);
return __first;
#else
- return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>::
+ return std::_Destroy_aux<__has_trivial_destructor(_Value_type)>::
__destroy_n(__first, __count);
#endif
}
@@ -297,6 +281,129 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#endif // C++17
+#if __glibcxx_start_lifetime_as >= 202207L // C++ >= 23
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ inline _Tp*
+ start_lifetime_as(void* __p) noexcept
+ {
+#if __glibcxx_is_implicit_lifetime >= 202302L
+ static_assert(is_implicit_lifetime_v<_Tp>);
+#endif
+ auto __q = reinterpret_cast<_Tp*>(__p);
+ __asm__ __volatile__("" : "=g" (__q), "=m" (*__q)
+ : "0" (__q), "m" (*__q));
+ return __q;
+ }
+
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ inline const _Tp*
+ start_lifetime_as(const void* __p) noexcept
+ {
+#if __glibcxx_is_implicit_lifetime >= 202302L
+ static_assert(is_implicit_lifetime_v<_Tp>);
+#endif
+ auto __q = reinterpret_cast<const _Tp*>(__p);
+ auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p));
+ __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
+ : "0" (__q), "m" (*__q));
+ return __q;
+ }
+
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ inline volatile _Tp*
+ start_lifetime_as(volatile void* __p) noexcept
+ {
+#if __glibcxx_is_implicit_lifetime >= 202302L
+ static_assert(is_implicit_lifetime_v<_Tp>);
+#endif
+ auto __q = reinterpret_cast<volatile _Tp*>(__p);
+ auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p));
+ __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
+ : "0" (__q), "m" (*__q));
+ return __q;
+ }
+
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ inline const volatile _Tp*
+ start_lifetime_as(const volatile void* __p) noexcept
+ {
+#if __glibcxx_is_implicit_lifetime >= 202302L
+ static_assert(is_implicit_lifetime_v<_Tp>);
+#endif
+ auto __q = reinterpret_cast<const volatile _Tp*>(__p);
+ auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p));
+ __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
+ : "0" (__q), "m" (*__q));
+ return __q;
+ }
+
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ inline _Tp*
+ start_lifetime_as_array(void* __p, size_t __n) noexcept
+ {
+ auto __q = reinterpret_cast<_Tp*>(__p);
+ if (!__n)
+ return __q;
+ auto __r = (__extension__ reinterpret_cast<_Tp(*)[__n]>(__p));
+ __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
+ : "0" (__q), "m" (*__r));
+ return __q;
+ }
+
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ inline const _Tp*
+ start_lifetime_as_array(const void* __p, size_t __n) noexcept
+ {
+ auto __q = reinterpret_cast<const _Tp*>(__p);
+ if (!__n)
+ return __q;
+ auto __r = (__extension__ reinterpret_cast<const _Tp(*)[__n]>(__p));
+ auto __s = (__extension__
+ reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p)));
+ __asm__ __volatile__("" : "=g" (__q), "=m" (*__s)
+ : "0" (__q), "m" (*__r));
+ return __q;
+ }
+
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ inline volatile _Tp*
+ start_lifetime_as_array(volatile void* __p, size_t __n) noexcept
+ {
+ auto __q = reinterpret_cast<volatile _Tp*>(__p);
+ if (!__n)
+ return __q;
+ auto __r = (__extension__ reinterpret_cast<volatile _Tp(*)[__n]>(__p));
+ auto __s = (__extension__
+ reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p)));
+ __asm__ __volatile__("" : "=g" (__q), "=m" (*__s)
+ : "0" (__q), "m" (*__r));
+ return __q;
+ }
+
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ inline const volatile _Tp*
+ start_lifetime_as_array(const volatile void* __p, size_t __n) noexcept
+ {
+ auto __q = reinterpret_cast<const volatile _Tp*>(__p);
+ if (!__n)
+ return __q;
+ auto __r = (__extension__ reinterpret_cast<const volatile _Tp(*)[__n]>(__p));
+ auto __s = (__extension__
+ reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p)));
+ __asm__ __volatile__("" : "=g" (__q), "=m" (*__s)
+ : "0" (__q), "m" (*__r));
+ return __q;
+ }
+#endif // C++23
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index 8d8ee57..7cc711e 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -1331,7 +1331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
size_type __sz = this->_M_impl._M_finish - this->_M_impl._M_start;
if (__sz > max_size ())
- __builtin_unreachable ();
+ __builtin_unreachable();
return __sz;
}
@@ -2163,6 +2163,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator
_M_insert_aux(iterator __pos, const value_type& __x);
#else
+ struct _Temporary_value
+ {
+ template<typename... _Args>
+ _GLIBCXX20_CONSTEXPR explicit
+ _Temporary_value(deque* __deque, _Args&&... __args) : _M_this(__deque)
+ {
+ _Alloc_traits::construct(_M_this->_M_impl, _M_ptr(),
+ std::forward<_Args>(__args)...);
+ }
+
+ _GLIBCXX20_CONSTEXPR
+ ~_Temporary_value()
+ { _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); }
+
+ _GLIBCXX20_CONSTEXPR value_type&
+ _M_val() noexcept { return __tmp_val; }
+
+ private:
+ _GLIBCXX20_CONSTEXPR _Tp*
+ _M_ptr() noexcept { return std::__addressof(__tmp_val); }
+
+ union
+ {
+ _Tp __tmp_val;
+ };
+
+ deque* _M_this;
+ };
+
iterator
_M_insert_aux(iterator __pos, const value_type& __x)
{ return _M_emplace_aux(__pos, __x); }
diff --git a/libstdc++-v3/include/bits/stl_function.h b/libstdc++-v3/include/bits/stl_function.h
index 136fd01..ff3f8f4 100644
--- a/libstdc++-v3/include/bits/stl_function.h
+++ b/libstdc++-v3/include/bits/stl_function.h
@@ -762,6 +762,58 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
is_convertible<_Tp, const volatile void*>,
is_convertible<_Up, const volatile void*>>;
};
+#else // < C++14
+
+ // We need less<void> and equal_to<void> for <bits/predefined_ops.h>
+
+ template<>
+ struct equal_to<void>
+ {
+#ifdef __cpp_rvalue_references
+ template<typename _Tp, typename _Up>
+ bool
+ operator()(_Tp&& __t, _Up&& __u) const
+ { return __t == __u; }
+#else // C++98
+ template<typename _Tp, typename _Up>
+ bool
+ operator()(_Tp& __t, _Up& __u) const { return __t == __u; }
+ template<typename _Tp, typename _Up>
+ bool
+ operator()(const _Tp& __t, _Up& __u) const { return __t == __u; }
+ template<typename _Tp, typename _Up>
+ bool
+ operator()(_Tp& __t, const _Up& __u) const { return __t == __u; }
+ template<typename _Tp, typename _Up>
+ bool
+ operator()(const _Tp& __t, const _Up& __u) const { return __t == __u; }
+#endif
+ };
+
+ template<>
+ struct less<void>
+ {
+#ifdef __cpp_rvalue_references
+ template<typename _Tp, typename _Up>
+ bool
+ operator()(_Tp&& __t, _Up&& __u) const
+ { return __t < __u; }
+#else // C++98
+ template<typename _Tp, typename _Up>
+ bool
+ operator()(_Tp& __t, _Up& __u) const { return __t < __u; }
+ template<typename _Tp, typename _Up>
+ bool
+ operator()(const _Tp& __t, _Up& __u) const { return __t < __u; }
+ template<typename _Tp, typename _Up>
+ bool
+ operator()(_Tp& __t, const _Up& __u) const { return __t < __u; }
+ template<typename _Tp, typename _Up>
+ bool
+ operator()(const _Tp& __t, const _Up& __u) const { return __t < __u; }
+#endif
+ };
+
#endif // __glibcxx_transparent_operators
/** @} */
diff --git a/libstdc++-v3/include/bits/stl_heap.h b/libstdc++-v3/include/bits/stl_heap.h
index 028ac83..b10495b 100644
--- a/libstdc++-v3/include/bits/stl_heap.h
+++ b/libstdc++-v3/include/bits/stl_heap.h
@@ -76,10 +76,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__is_heap_until(_RandomAccessIterator __first, _Distance __n,
_Compare& __comp)
{
+#if __cplusplus >= 201103L
+ using _IterTraits = iterator_traits<_RandomAccessIterator>;
+ static_assert(is_same<typename _IterTraits::difference_type,
+ _Distance>::value,
+ "Argument 'n' must be the iterator's difference type");
+#endif
_Distance __parent = 0;
for (_Distance __child = 1; __child < __n; ++__child)
{
- if (__comp(__first + __parent, __first + __child))
+ if (__comp(__first[__parent], __first[__child]))
return __child;
if ((__child & 1) == 0)
++__parent;
@@ -94,8 +100,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline bool
__is_heap(_RandomAccessIterator __first, _Distance __n)
{
- __gnu_cxx::__ops::_Iter_less_iter __comp;
- return std::__is_heap_until(__first, __n, __comp) == __n;
+ typename iterator_traits<_RandomAccessIterator>::difference_type __d(__n);
+ __gnu_cxx::__ops::less __comp;
+ return std::__is_heap_until(__first, __d, __comp) == __n;
}
template<typename _RandomAccessIterator, typename _Compare,
@@ -104,9 +111,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline bool
__is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
{
- typedef __decltype(__comp) _Cmp;
- __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
- return std::__is_heap_until(__first, __n, __cmp) == __n;
+ typename iterator_traits<_RandomAccessIterator>::difference_type __d(__n);
+ return std::__is_heap_until(__first, __d, __comp) == __n;
}
template<typename _RandomAccessIterator>
@@ -137,7 +143,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Compare& __comp)
{
_Distance __parent = (__holeIndex - 1) / 2;
- while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
+ while (__holeIndex > __topIndex && __comp(__first[__parent], __value))
{
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
__holeIndex = __parent;
@@ -172,10 +178,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last);
- __glibcxx_requires_heap(__first, __last - 1);
+ __glibcxx_requires_heap(__first, __last - _DistanceType(1));
- __gnu_cxx::__ops::_Iter_less_val __comp;
- _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
+ __gnu_cxx::__ops::less __comp;
+ _ValueType __value = _GLIBCXX_MOVE(*(__last - _DistanceType(1)));
std::__push_heap(__first, _DistanceType((__last - __first) - 1),
_DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
}
@@ -208,13 +214,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_RandomAccessIterator>)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
+ __glibcxx_requires_heap_pred(__first, __last - _DistanceType(1), __comp);
- __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
- __cmp(_GLIBCXX_MOVE(__comp));
- _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
+ _ValueType __value = _GLIBCXX_MOVE(*(__last - _DistanceType(1)));
std::__push_heap(__first, _DistanceType((__last - __first) - 1),
- _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp);
+ _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
}
template<typename _RandomAccessIterator, typename _Distance,
@@ -229,8 +233,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
while (__secondChild < (__len - 1) / 2)
{
__secondChild = 2 * (__secondChild + 1);
- if (__comp(__first + __secondChild,
- __first + (__secondChild - 1)))
+ if (__comp(__first[__secondChild],
+ __first[__secondChild - 1]))
__secondChild--;
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
__holeIndex = __secondChild;
@@ -242,10 +246,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ (__secondChild - 1)));
__holeIndex = __secondChild - 1;
}
- __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
- __cmp(_GLIBCXX_MOVE(__comp));
std::__push_heap(__first, __holeIndex, __topIndex,
- _GLIBCXX_MOVE(__value), __cmp);
+ _GLIBCXX_MOVE(__value), __comp);
}
template<typename _RandomAccessIterator, typename _Compare>
@@ -295,7 +297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__last - __first > 1)
{
--__last;
- __gnu_cxx::__ops::_Iter_less_iter __comp;
+ __gnu_cxx::__ops::less __comp;
std::__pop_heap(__first, __last, __last, __comp);
}
}
@@ -327,10 +329,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__last - __first > 1)
{
- typedef __decltype(__comp) _Cmp;
- __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
--__last;
- std::__pop_heap(__first, __last, __last, __cmp);
+ std::__pop_heap(__first, __last, __last, __comp);
}
}
@@ -382,7 +382,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last);
- __gnu_cxx::__ops::_Iter_less_iter __comp;
+ __gnu_cxx::__ops::less __comp;
std::__make_heap(__first, __last, __comp);
}
@@ -408,9 +408,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- typedef __decltype(__comp) _Cmp;
- __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
- std::__make_heap(__first, __last, __cmp);
+ std::__make_heap(__first, __last, __comp);
}
template<typename _RandomAccessIterator, typename _Compare>
@@ -448,7 +446,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_irreflexive(__first, __last);
__glibcxx_requires_heap(__first, __last);
- __gnu_cxx::__ops::_Iter_less_iter __comp;
+ __gnu_cxx::__ops::less __comp;
std::__sort_heap(__first, __last, __comp);
}
@@ -475,9 +473,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
__glibcxx_requires_heap_pred(__first, __last, __comp);
- typedef __decltype(__comp) _Cmp;
- __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
- std::__sort_heap(__first, __last, __cmp);
+ std::__sort_heap(__first, __last, __comp);
}
#if __cplusplus >= 201103L
@@ -504,7 +500,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last);
- __gnu_cxx::__ops::_Iter_less_iter __comp;
+ __gnu_cxx::__ops::less __comp;
return __first +
std::__is_heap_until(__first, std::distance(__first, __last), __comp);
}
@@ -532,10 +528,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
- typedef __decltype(__comp) _Cmp;
- __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
return __first
- + std::__is_heap_until(__first, std::distance(__first, __last), __cmp);
+ + std::__is_heap_until(__first, std::distance(__first, __last),
+ __comp);
}
/**
@@ -572,9 +567,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
const auto __dist = std::distance(__first, __last);
- typedef __decltype(__comp) _Cmp;
- __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
- return std::__is_heap_until(__first, __dist, __cmp) == __dist;
+ return std::__is_heap_until(__first, __dist, __comp) == __dist;
}
#endif
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index 9203a66..75e794f 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -1164,188 +1164,201 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const _Iterator&
base() const _GLIBCXX_NOEXCEPT
{ return _M_current; }
- };
- // Note: In what follows, the left- and right-hand-side iterators are
- // allowed to vary in types (conceptually in cv-qualification) so that
- // comparison between cv-qualified and non-cv-qualified iterators be
- // valid. However, the greedy and unfriendly operators in std::rel_ops
- // will make overload resolution ambiguous (when in scope) if we don't
- // provide overloads whose operands are of the same type. Can someone
- // remind me what generic programming is about? -- Gaby
+ private:
+ // Note: In what follows, the left- and right-hand-side iterators are
+ // allowed to vary in types (conceptually in cv-qualification) so that
+ // comparison between cv-qualified and non-cv-qualified iterators be
+ // valid. However, the greedy and unfriendly operators in std::rel_ops
+ // will make overload resolution ambiguous (when in scope) if we don't
+ // provide overloads whose operands are of the same type. Can someone
+ // remind me what generic programming is about? -- Gaby
#ifdef __cpp_lib_three_way_comparison
- template<typename _IteratorL, typename _IteratorR, typename _Container>
- [[nodiscard, __gnu__::__always_inline__]]
- constexpr bool
- operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
- const __normal_iterator<_IteratorR, _Container>& __rhs)
- noexcept(noexcept(__lhs.base() == __rhs.base()))
- requires requires {
- { __lhs.base() == __rhs.base() } -> std::convertible_to<bool>;
- }
- { return __lhs.base() == __rhs.base(); }
-
- template<typename _IteratorL, typename _IteratorR, typename _Container>
- [[nodiscard, __gnu__::__always_inline__]]
- constexpr std::__detail::__synth3way_t<_IteratorR, _IteratorL>
- operator<=>(const __normal_iterator<_IteratorL, _Container>& __lhs,
- const __normal_iterator<_IteratorR, _Container>& __rhs)
- noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base())))
- { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); }
+ template<typename _Iter>
+ [[nodiscard, __gnu__::__always_inline__]]
+ friend
+ constexpr bool
+ operator==(const __normal_iterator& __lhs,
+ const __normal_iterator<_Iter, _Container>& __rhs)
+ noexcept(noexcept(__lhs.base() == __rhs.base()))
+ requires requires {
+ { __lhs.base() == __rhs.base() } -> std::convertible_to<bool>;
+ }
+ { return __lhs.base() == __rhs.base(); }
- template<typename _Iterator, typename _Container>
- [[nodiscard, __gnu__::__always_inline__]]
- constexpr bool
- operator==(const __normal_iterator<_Iterator, _Container>& __lhs,
- const __normal_iterator<_Iterator, _Container>& __rhs)
- noexcept(noexcept(__lhs.base() == __rhs.base()))
- requires requires {
- { __lhs.base() == __rhs.base() } -> std::convertible_to<bool>;
- }
- { return __lhs.base() == __rhs.base(); }
+ [[nodiscard, __gnu__::__always_inline__]]
+ friend
+ constexpr bool
+ operator==(const __normal_iterator& __lhs, const __normal_iterator& __rhs)
+ noexcept(noexcept(__lhs.base() == __rhs.base()))
+ requires requires {
+ { __lhs.base() == __rhs.base() } -> std::convertible_to<bool>;
+ }
+ { return __lhs.base() == __rhs.base(); }
- template<typename _Iterator, typename _Container>
- [[nodiscard, __gnu__::__always_inline__]]
- constexpr std::__detail::__synth3way_t<_Iterator>
- operator<=>(const __normal_iterator<_Iterator, _Container>& __lhs,
- const __normal_iterator<_Iterator, _Container>& __rhs)
- noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base())))
- { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); }
+ template<typename _Iter>
+ [[nodiscard, __gnu__::__always_inline__]]
+ friend
+ constexpr std::__detail::__synth3way_t<_Iterator, _Iter>
+ operator<=>(const __normal_iterator& __lhs,
+ const __normal_iterator<_Iter, _Container>& __rhs)
+ noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base())))
+ requires requires {
+ std::__detail::__synth3way(__lhs.base(), __rhs.base());
+ }
+ { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); }
#else
- // Forward iterator requirements
- template<typename _IteratorL, typename _IteratorR, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
- const __normal_iterator<_IteratorR, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() == __rhs.base(); }
+ // Forward iterator requirements
+ template<typename _Iter>
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ bool
+ operator==(const __normal_iterator& __lhs,
+ const __normal_iterator<_Iter, _Container>& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() == __rhs.base(); }
- template<typename _Iterator, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator==(const __normal_iterator<_Iterator, _Container>& __lhs,
- const __normal_iterator<_Iterator, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() == __rhs.base(); }
-
- template<typename _IteratorL, typename _IteratorR, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs,
- const __normal_iterator<_IteratorR, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() != __rhs.base(); }
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ bool
+ operator==(const __normal_iterator& __lhs, const __normal_iterator& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() == __rhs.base(); }
- template<typename _Iterator, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator!=(const __normal_iterator<_Iterator, _Container>& __lhs,
- const __normal_iterator<_Iterator, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() != __rhs.base(); }
-
- // Random access iterator requirements
- template<typename _IteratorL, typename _IteratorR, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
- const __normal_iterator<_IteratorR, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() < __rhs.base(); }
+ template<typename _Iter>
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ bool
+ operator!=(const __normal_iterator& __lhs,
+ const __normal_iterator<_Iter, _Container>& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() != __rhs.base(); }
- template<typename _Iterator, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR
- inline bool
- operator<(const __normal_iterator<_Iterator, _Container>& __lhs,
- const __normal_iterator<_Iterator, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() < __rhs.base(); }
-
- template<typename _IteratorL, typename _IteratorR, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator>(const __normal_iterator<_IteratorL, _Container>& __lhs,
- const __normal_iterator<_IteratorR, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() > __rhs.base(); }
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ bool
+ operator!=(const __normal_iterator& __lhs, const __normal_iterator& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() != __rhs.base(); }
- template<typename _Iterator, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator>(const __normal_iterator<_Iterator, _Container>& __lhs,
- const __normal_iterator<_Iterator, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() > __rhs.base(); }
-
- template<typename _IteratorL, typename _IteratorR, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs,
- const __normal_iterator<_IteratorR, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() <= __rhs.base(); }
+ // Random access iterator requirements
+ template<typename _Iter>
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ inline bool
+ operator<(const __normal_iterator& __lhs,
+ const __normal_iterator<_Iter, _Container>& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() < __rhs.base(); }
- template<typename _Iterator, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator<=(const __normal_iterator<_Iterator, _Container>& __lhs,
- const __normal_iterator<_Iterator, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() <= __rhs.base(); }
-
- template<typename _IteratorL, typename _IteratorR, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs,
- const __normal_iterator<_IteratorR, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() >= __rhs.base(); }
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX20_CONSTEXPR
+ bool
+ operator<(const __normal_iterator& __lhs, const __normal_iterator& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() < __rhs.base(); }
- template<typename _Iterator, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline bool
- operator>=(const __normal_iterator<_Iterator, _Container>& __lhs,
- const __normal_iterator<_Iterator, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() >= __rhs.base(); }
+ template<typename _Iter>
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ bool
+ operator>(const __normal_iterator& __lhs,
+ const __normal_iterator<_Iter, _Container>& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() > __rhs.base(); }
+
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ bool
+ operator>(const __normal_iterator& __lhs, const __normal_iterator& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() > __rhs.base(); }
+
+ template<typename _Iter>
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ bool
+ operator<=(const __normal_iterator& __lhs,
+ const __normal_iterator<_Iter, _Container>& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() <= __rhs.base(); }
+
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ bool
+ operator<=(const __normal_iterator& __lhs, const __normal_iterator& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() <= __rhs.base(); }
+
+ template<typename _Iter>
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ bool
+ operator>=(const __normal_iterator& __lhs,
+ const __normal_iterator<_Iter, _Container>& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() >= __rhs.base(); }
+
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ bool
+ operator>=(const __normal_iterator& __lhs, const __normal_iterator& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() >= __rhs.base(); }
#endif // three-way comparison
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // According to the resolution of DR179 not only the various comparison
- // operators but also operator- must accept mixed iterator/const_iterator
- // parameters.
- template<typename _IteratorL, typename _IteratorR, typename _Container>
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 179. Comparison of const_iterators to iterators doesn't work
+ // According to the resolution of DR179 not only the various comparison
+ // operators but also operator- must accept mixed iterator/const_iterator
+ // parameters.
+ template<typename _Iter>
#if __cplusplus >= 201103L
- // DR 685.
- [[__nodiscard__, __gnu__::__always_inline__]]
- constexpr auto
- operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
- const __normal_iterator<_IteratorR, _Container>& __rhs) noexcept
- -> decltype(__lhs.base() - __rhs.base())
+ [[__nodiscard__, __gnu__::__always_inline__]]
+ friend
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 685. reverse_iterator/move_iterator difference has invalid signatures
+ constexpr auto
+ operator-(const __normal_iterator& __lhs,
+ const __normal_iterator<_Iter, _Container>& __rhs) noexcept
+ -> decltype(__lhs.base() - __rhs.base())
#else
- inline typename __normal_iterator<_IteratorL, _Container>::difference_type
- operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
- const __normal_iterator<_IteratorR, _Container>& __rhs)
+ friend
+ difference_type
+ operator-(const __normal_iterator& __lhs,
+ const __normal_iterator<_Iter, _Container>& __rhs)
#endif
- { return __lhs.base() - __rhs.base(); }
+ { return __lhs.base() - __rhs.base(); }
- template<typename _Iterator, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline typename __normal_iterator<_Iterator, _Container>::difference_type
- operator-(const __normal_iterator<_Iterator, _Container>& __lhs,
- const __normal_iterator<_Iterator, _Container>& __rhs)
- _GLIBCXX_NOEXCEPT
- { return __lhs.base() - __rhs.base(); }
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ difference_type
+ operator-(const __normal_iterator& __lhs, const __normal_iterator& __rhs)
+ _GLIBCXX_NOEXCEPT
+ { return __lhs.base() - __rhs.base(); }
- template<typename _Iterator, typename _Container>
- _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
- inline __normal_iterator<_Iterator, _Container>
- operator+(typename __normal_iterator<_Iterator, _Container>::difference_type
- __n, const __normal_iterator<_Iterator, _Container>& __i)
- _GLIBCXX_NOEXCEPT
- { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); }
+ _GLIBCXX_NODISCARD __attribute__((__always_inline__))
+ friend
+ _GLIBCXX_CONSTEXPR
+ __normal_iterator
+ operator+(difference_type __n, const __normal_iterator& __i)
+ _GLIBCXX_NOEXCEPT
+ { return __normal_iterator(__i.base() + __n); }
+ };
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __gnu_cxx
@@ -2511,17 +2524,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[nodiscard]]
friend constexpr iter_difference_t<_It2>
operator-(const counted_iterator& __x,
- const counted_iterator<_It2>& __y)
+ const counted_iterator<_It2>& __y) noexcept
{ return __y._M_length - __x._M_length; }
[[nodiscard]]
friend constexpr iter_difference_t<_It>
- operator-(const counted_iterator& __x, default_sentinel_t)
+ operator-(const counted_iterator& __x, default_sentinel_t) noexcept
{ return -__x._M_length; }
[[nodiscard]]
friend constexpr iter_difference_t<_It>
- operator-(default_sentinel_t, const counted_iterator& __y)
+ operator-(default_sentinel_t, const counted_iterator& __y) noexcept
{ return __y._M_length; }
constexpr counted_iterator&
@@ -2548,19 +2561,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[nodiscard]]
friend constexpr bool
operator==(const counted_iterator& __x,
- const counted_iterator<_It2>& __y)
+ const counted_iterator<_It2>& __y) noexcept
{ return __x._M_length == __y._M_length; }
[[nodiscard]]
friend constexpr bool
- operator==(const counted_iterator& __x, default_sentinel_t)
+ operator==(const counted_iterator& __x, default_sentinel_t) noexcept
{ return __x._M_length == 0; }
template<common_with<_It> _It2>
[[nodiscard]]
friend constexpr strong_ordering
operator<=>(const counted_iterator& __x,
- const counted_iterator<_It2>& __y)
+ const counted_iterator<_It2>& __y) noexcept
{ return __y._M_length <=> __x._M_length; }
[[nodiscard]]
@@ -3086,8 +3099,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cpp_deduction_guides >= 201606
// These helper traits are used for deduction guides
// of associative containers.
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4223. Deduction guides for maps are mishandling tuples and references
template<typename _InputIterator>
- using __iter_key_t = remove_const_t<
+ using __iter_key_t = __remove_cvref_t<
#ifdef __glibcxx_tuple_like // >= C++23
tuple_element_t<0, typename iterator_traits<_InputIterator>::value_type>>;
#else
@@ -3095,11 +3111,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
template<typename _InputIterator>
- using __iter_val_t
+ using __iter_val_t = __remove_cvref_t<
#ifdef __glibcxx_tuple_like // >= C++23
- = tuple_element_t<1, typename iterator_traits<_InputIterator>::value_type>;
+ tuple_element_t<1, typename iterator_traits<_InputIterator>::value_type>>;
#else
- = typename iterator_traits<_InputIterator>::value_type::second_type;
+ typename iterator_traits<_InputIterator>::value_type::second_type>;
#endif
template<typename _T1, typename _T2>
diff --git a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
index 637159f..7c80e14 100644
--- a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
+++ b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
@@ -130,6 +130,28 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
__distance(_OutputIterator, _OutputIterator, output_iterator_tag) = delete;
#endif
+#ifdef __glibcxx_concepts
+namespace __detail
+{
+ // Satisfied if ITER_TRAITS(Iter)::iterator_category is valid and is
+ // at least as strong as ITER_TRAITS(Iter)::iterator_concept.
+ template<typename _Iter>
+ concept __iter_category_converts_to_concept
+ = convertible_to<typename __iter_traits<_Iter>::iterator_category,
+ typename __iter_traits<_Iter>::iterator_concept>;
+
+ // Satisfied if the type is a C++20 iterator that defines iterator_concept,
+ // and its iterator_concept is stronger than its iterator_category (if any).
+ // Used by std::distance and std::advance to detect iterators which should
+ // dispatch based on their C++20 concept not their C++17 category.
+ template<typename _Iter>
+ concept __promotable_iterator
+ = input_iterator<_Iter>
+ && requires { typename __iter_traits<_Iter>::iterator_concept; }
+ && ! __iter_category_converts_to_concept<_Iter>;
+} // namespace __detail
+#endif
+
/**
* @brief A generalization of pointer arithmetic.
* @param __first An input iterator.
@@ -149,6 +171,24 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
typename iterator_traits<_InputIterator>::difference_type
distance(_InputIterator __first, _InputIterator __last)
{
+#ifdef __glibcxx_concepts
+ // A type which satisfies the C++20 random_access_iterator concept might
+ // have input_iterator_tag as its iterator_category type, which would
+ // mean we select the O(n) __distance. Or a C++20 std::input_iterator
+ // that is not a Cpp17InputIterator might have output_iterator_tag as
+ // its iterator_category type and then calling __distance with
+ // std::__iterator_category(__first) would be ill-formed.
+ // So for C++20 iterator types we can just choose to do the right thing.
+ if constexpr (__detail::__promotable_iterator<_InputIterator>)
+ {
+ if constexpr (random_access_iterator<_InputIterator>)
+ return __last - __first;
+ else
+ return std::__distance(std::move(__first), std::move(__last),
+ input_iterator_tag());
+ }
+ else // assume it meets the Cpp17InputIterator requirements:
+#endif
// concept requirements -- taken care of in __distance
return std::__distance(__first, __last,
std::__iterator_category(__first));
@@ -161,7 +201,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_assert(__n >= 0);
- while (__n--)
+ while (__n-- > 0)
++__i;
}
@@ -221,9 +261,31 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
inline _GLIBCXX17_CONSTEXPR void
advance(_InputIterator& __i, _Distance __n)
{
- // concept requirements -- taken care of in __advance
- typename iterator_traits<_InputIterator>::difference_type __d = __n;
- std::__advance(__i, __d, std::__iterator_category(__i));
+#ifdef __glibcxx_concepts
+ // A type which satisfies the C++20 bidirectional_iterator concept might
+ // have input_iterator_tag as its iterator_category type, which would
+ // mean we select the __advance overload which cannot move backwards.
+ // For a C++20 random_access_iterator we might select the O(n) __advance
+ // if it doesn't meet the Cpp17RandomAccessIterator requirements.
+ // So for C++20 iterator types we can just choose to do the right thing.
+ if constexpr (__detail::__promotable_iterator<_InputIterator>
+ && ranges::__detail::__is_integer_like<_Distance>)
+ {
+ auto __d = static_cast<iter_difference_t<_InputIterator>>(__n);
+ if constexpr (random_access_iterator<_InputIterator>)
+ std::__advance(__i, __d, random_access_iterator_tag());
+ else if constexpr (bidirectional_iterator<_InputIterator>)
+ std::__advance(__i, __d, bidirectional_iterator_tag());
+ else
+ std::__advance(__i, __d, input_iterator_tag());
+ }
+ else // assume it meets the Cpp17InputIterator requirements:
+#endif
+ {
+ // concept requirements -- taken care of in __advance
+ typename iterator_traits<_InputIterator>::difference_type __d = __n;
+ std::__advance(__i, __d, std::__iterator_category(__i));
+ }
}
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h
index a67d7bd..0c34ad7 100644
--- a/libstdc++-v3/include/bits/stl_iterator_base_types.h
+++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h
@@ -257,6 +257,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _InIter>
concept __has_input_iter_cat
= is_convertible_v<__iter_category_t<_InIter>, input_iterator_tag>;
+
+#ifdef __cpp_lib_concepts
+ // Is a Cpp17InputIterator or satisfies std::input_iterator.
+ template<typename _InIterator>
+ concept __any_input_iterator
+ = input_iterator<_InIterator> || __has_input_iter_cat<_InIterator>;
+#endif
#endif
template<typename _It,
diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h
index 006ff46..62d66ce 100644
--- a/libstdc++-v3/include/bits/stl_map.h
+++ b/libstdc++-v3/include/bits/stl_map.h
@@ -1156,7 +1156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*/
size_type
erase(const key_type& __x)
- { return _M_t.erase(__x); }
+ { return _M_t._M_erase_unique(__x); }
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -1259,7 +1259,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x)
{ return _M_t.find(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x))
@@ -1284,7 +1284,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x) const
{ return _M_t.find(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x))
@@ -1305,7 +1305,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_t.find(__x) == _M_t.end() ? 0 : 1; }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x))
@@ -1348,7 +1348,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
lower_bound(const key_type& __x)
{ return _M_t.lower_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
lower_bound(const _Kt& __x)
@@ -1373,7 +1373,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
lower_bound(const key_type& __x) const
{ return _M_t.lower_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
lower_bound(const _Kt& __x) const
@@ -1393,7 +1393,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
upper_bound(const key_type& __x)
{ return _M_t.upper_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
upper_bound(const _Kt& __x)
@@ -1413,7 +1413,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
upper_bound(const key_type& __x) const
{ return _M_t.upper_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
upper_bound(const _Kt& __x) const
@@ -1442,7 +1442,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x)
{ return _M_t.equal_range(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
equal_range(const _Kt& __x)
@@ -1471,7 +1471,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x) const
{ return _M_t.equal_range(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
equal_range(const _Kt& __x) const
@@ -1649,7 +1649,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
// Allow std::map access to internals of compatible maps.
template<typename _Key, typename _Val, typename _Cmp1, typename _Alloc,
typename _Cmp2>
diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h
index 4ee4a84..b2ae2ba 100644
--- a/libstdc++-v3/include/bits/stl_multimap.h
+++ b/libstdc++-v3/include/bits/stl_multimap.h
@@ -891,7 +891,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x)
{ return _M_t.find(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x))
@@ -915,7 +915,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x) const
{ return _M_t.find(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x))
@@ -933,7 +933,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_t.count(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x))
@@ -976,7 +976,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
lower_bound(const key_type& __x)
{ return _M_t.lower_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
lower_bound(const _Kt& __x)
@@ -1001,7 +1001,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
lower_bound(const key_type& __x) const
{ return _M_t.lower_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
lower_bound(const _Kt& __x) const
@@ -1021,7 +1021,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
upper_bound(const key_type& __x)
{ return _M_t.upper_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
upper_bound(const _Kt& __x)
@@ -1041,7 +1041,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
upper_bound(const key_type& __x) const
{ return _M_t.upper_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
upper_bound(const _Kt& __x) const
@@ -1068,7 +1068,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x)
{ return _M_t.equal_range(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
equal_range(const _Kt& __x)
@@ -1095,7 +1095,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x) const
{ return _M_t.equal_range(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
equal_range(const _Kt& __x) const
@@ -1272,7 +1272,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
// Allow std::multimap access to internals of compatible maps.
template<typename _Key, typename _Val, typename _Cmp1, typename _Alloc,
typename _Cmp2>
diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h
index 31451ab..b6e1bfc 100644
--- a/libstdc++-v3/include/bits/stl_multiset.h
+++ b/libstdc++-v3/include/bits/stl_multiset.h
@@ -773,7 +773,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_t.count(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x))
@@ -822,7 +822,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x) const
{ return _M_t.find(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
find(const _Kt& __x)
@@ -857,7 +857,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
lower_bound(const key_type& __x) const
{ return _M_t.lower_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
lower_bound(const _Kt& __x)
@@ -887,7 +887,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
upper_bound(const key_type& __x) const
{ return _M_t.upper_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
upper_bound(const _Kt& __x)
@@ -926,7 +926,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x) const
{ return _M_t.equal_range(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
equal_range(const _Kt& __x)
@@ -1103,7 +1103,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
// Allow std::multiset access to internals of compatible sets.
template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2>
struct
diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index 8c57712..231d0bb 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -445,7 +445,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Constructor accepting lvalues of `first_type` and `second_type`
constexpr explicit(!_S_convertible<const _T1&, const _T2&>())
- pair(const _T1& __x, const _T2& __y)
+ pair(const type_identity_t<_T1>& __x, const _T2& __y)
noexcept(_S_nothrow_constructible<const _T1&, const _T2&>())
requires (_S_constructible<const _T1&, const _T2&>())
: first(__x), second(__y)
@@ -1132,6 +1132,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif // C++23
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2766. Swapping non-swappable types
template<typename _T1, typename _T2>
typename enable_if<!__and_<__is_swappable<_T1>,
__is_swappable<_T2>>::value>::type
@@ -1313,12 +1315,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _Tp, typename _Up>
constexpr _Tp&&
get(pair<_Tp, _Up>&& __p) noexcept
- { return std::move(__p.first); }
+ { return std::forward<_Tp>(__p.first); }
template <typename _Tp, typename _Up>
constexpr const _Tp&&
get(const pair<_Tp, _Up>&& __p) noexcept
- { return std::move(__p.first); }
+ { return std::forward<const _Tp>(__p.first); }
template <typename _Tp, typename _Up>
constexpr _Tp&
@@ -1333,12 +1335,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _Tp, typename _Up>
constexpr _Tp&&
get(pair<_Up, _Tp>&& __p) noexcept
- { return std::move(__p.second); }
+ { return std::forward<_Tp>(__p.second); }
template <typename _Tp, typename _Up>
constexpr const _Tp&&
get(const pair<_Up, _Tp>&& __p) noexcept
- { return std::move(__p.second); }
+ { return std::forward<const _Tp>(__p.second); }
#endif // __glibcxx_tuples_by_type
diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h
index 554e076..a3a8bc1 100644
--- a/libstdc++-v3/include/bits/stl_queue.h
+++ b/libstdc++-v3/include/bits/stl_queue.h
@@ -70,6 +70,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+#if __glibcxx_format_ranges
+ template<typename, typename> class formatter;
+#endif
+
/**
* @brief A standard container giving FIFO behavior.
*
@@ -369,6 +373,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(c, __q.c);
}
#endif // __cplusplus >= 201103L
+
+#if __glibcxx_format_ranges
+ friend class formatter<queue<_Tp, _Sequence>, char>;
+ friend class formatter<queue<_Tp, _Sequence>, wchar_t>;
+#endif
};
#if __cpp_deduction_guides >= 201606
@@ -898,6 +907,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(comp, __pq.comp);
}
#endif // __cplusplus >= 201103L
+
+#if __glibcxx_format_ranges
+ friend class formatter<priority_queue<_Tp, _Sequence, _Compare>, char>;
+ friend class formatter<priority_queue<_Tp, _Sequence, _Compare>, wchar_t>;
+#endif
};
#if __cpp_deduction_guides >= 201606
diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h
index 0799fd0..f03d9e5 100644
--- a/libstdc++-v3/include/bits/stl_set.h
+++ b/libstdc++-v3/include/bits/stl_set.h
@@ -728,7 +728,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*/
size_type
erase(const key_type& __x)
- { return _M_t.erase(__x); }
+ { return _M_t._M_erase_unique(__x); }
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -794,7 +794,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_t.find(__x) == _M_t.end() ? 0 : 1; }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
count(const _Kt& __x) const
@@ -844,7 +844,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x) const
{ return _M_t.find(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
find(const _Kt& __x)
@@ -879,7 +879,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
lower_bound(const key_type& __x) const
{ return _M_t.lower_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
lower_bound(const _Kt& __x)
@@ -909,7 +909,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
upper_bound(const key_type& __x) const
{ return _M_t.upper_bound(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
upper_bound(const _Kt& __x)
@@ -948,7 +948,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x) const
{ return _M_t.equal_range(__x); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt>
auto
equal_range(const _Kt& __x)
@@ -1119,7 +1119,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
// Allow std::set access to internals of compatible sets.
template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2>
struct
diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h
index 7b32464..27c79d6 100644
--- a/libstdc++-v3/include/bits/stl_stack.h
+++ b/libstdc++-v3/include/bits/stl_stack.h
@@ -70,6 +70,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+#if __glibcxx_format_ranges
+ template<typename, typename> class formatter;
+#endif
+
/**
* @brief A standard container giving FILO behavior.
*
@@ -343,6 +347,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(c, __s.c);
}
#endif // __cplusplus >= 201103L
+
+#if __glibcxx_format_ranges
+ friend class formatter<stack<_Tp, _Sequence>, char>;
+ friend class formatter<stack<_Tp, _Sequence>, wchar_t>;
+#endif
};
#if __cpp_deduction_guides >= 201606
diff --git a/libstdc++-v3/include/bits/stl_tempbuf.h b/libstdc++-v3/include/bits/stl_tempbuf.h
index 7a7619e..8cc7b11 100644
--- a/libstdc++-v3/include/bits/stl_tempbuf.h
+++ b/libstdc++-v3/include/bits/stl_tempbuf.h
@@ -227,7 +227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Returns the size requested by the constructor; may be >size().
size_type
- requested_size() const
+ _M_requested_size() const
{ return _M_original_len; }
/// As per Table mumble.
diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index 6b35f99..e78fa1d 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -1390,27 +1390,25 @@ namespace __rb_tree
_M_end() const _GLIBCXX_NOEXCEPT
{ return this->_M_impl._M_header._M_base_ptr(); }
- static const _Key&
- _S_key(const _Node& __node)
- {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2542. Missing const requirements for associative containers
+ template<typename _Key1, typename _Key2>
+ bool
+ _M_key_compare(const _Key1& __k1, const _Key2& __k2) const
+ {
#if __cplusplus >= 201103L
- // If we're asking for the key we're presumably using the comparison
- // object, and so this is a good place to sanity check it.
- static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},
- "comparison object must be invocable "
- "with two arguments of key type");
-# if __cplusplus >= 201703L
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 2542. Missing const requirements for associative containers
- if constexpr (__is_invocable<_Compare&, const _Key&, const _Key&>{})
+ // Enforce this here with a user-friendly message.
static_assert(
- is_invocable_v<const _Compare&, const _Key&, const _Key&>,
- "comparison object must be invocable as const");
-# endif // C++17
-#endif // C++11
+ __is_invocable<const _Compare&, const _Key&, const _Key&>::value,
+ "comparison object must be invocable with two arguments of key type"
+ );
+#endif
+ return _M_impl._M_key_compare(__k1, __k2);
+ }
- return _KeyOfValue()(*__node._M_valptr());
- }
+ static const _Key&
+ _S_key(const _Node& __node)
+ { return _KeyOfValue()(*__node._M_valptr()); }
static const _Key&
_S_key(_Base_ptr __x)
@@ -1852,6 +1850,9 @@ namespace __rb_tree
size_type
erase(const key_type& __x);
+ size_type
+ _M_erase_unique(const key_type& __x);
+
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 130. Associative erase should return an iterator.
@@ -1917,7 +1918,7 @@ namespace __rb_tree
pair<const_iterator, const_iterator>
equal_range(const key_type& __k) const;
-#if __cplusplus >= 201402L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req = __has_is_transparent_t<_Compare, _Kt>>
iterator
@@ -1933,7 +1934,7 @@ namespace __rb_tree
_M_find_tr(const _Kt& __k) const
{
const_iterator __j(_M_lower_bound_tr(__k));
- if (__j != end() && _M_impl._M_key_compare(__k, _S_key(__j._M_node)))
+ if (__j != end() && _M_key_compare(__k, _S_key(__j._M_node)))
__j = end();
return __j;
}
@@ -1955,7 +1956,7 @@ namespace __rb_tree
auto __x = _M_begin();
auto __y = _M_end();
while (__x)
- if (!_M_impl._M_key_compare(_S_key(__x), __k))
+ if (!_M_key_compare(_S_key(__x), __k))
{
__y = __x;
__x = _S_left(__x);
@@ -1973,7 +1974,7 @@ namespace __rb_tree
auto __x = _M_begin();
auto __y = _M_end();
while (__x)
- if (_M_impl._M_key_compare(__k, _S_key(__x)))
+ if (_M_key_compare(__k, _S_key(__x)))
{
__y = __x;
__x = _S_left(__x);
@@ -2006,7 +2007,7 @@ namespace __rb_tree
++__high;
return { __low, __high };
}
-#endif
+#endif // __glibcxx_generic_associative_lookup
// Debugging.
bool
@@ -2342,8 +2343,11 @@ namespace __rb_tree
constexpr bool __move = !__move_if_noexcept_cond<value_type>::value;
_Alloc_node __an(*this);
_M_root() = _M_copy<__move>(__x, __an);
- if _GLIBCXX17_CONSTEXPR (__move)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ if constexpr (__move)
__x.clear();
+#pragma GCC diagnostic pop
}
}
@@ -2474,8 +2478,8 @@ namespace __rb_tree
_NodeGen& __node_gen)
{
bool __insert_left = (__x || __p == _M_end()
- || _M_impl._M_key_compare(_KeyOfValue()(__v),
- _S_key(__p)));
+ || _M_key_compare(_KeyOfValue()(__v),
+ _S_key(__p)));
_Base_ptr __z =
__node_gen(_GLIBCXX_FORWARD(_Arg, __v))->_M_base_ptr();
@@ -2500,8 +2504,8 @@ namespace __rb_tree
#endif
{
bool __insert_left = (__p == _M_end()
- || !_M_impl._M_key_compare(_S_key(__p),
- _KeyOfValue()(__v)));
+ || !_M_key_compare(_S_key(__p),
+ _KeyOfValue()(__v)));
_Base_ptr __z =
_M_create_node(_GLIBCXX_FORWARD(_Arg, __v))->_M_base_ptr();
@@ -2529,7 +2533,7 @@ namespace __rb_tree
while (__x)
{
__y = __x;
- __x = !_M_impl._M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ?
+ __x = !_M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ?
_S_left(__x) : _S_right(__x);
}
return _M_insert_lower(__y, _GLIBCXX_FORWARD(_Arg, __v));
@@ -2601,7 +2605,7 @@ namespace __rb_tree
const _Key& __k) const
{
while (__x)
- if (!_M_impl._M_key_compare(_S_key(__x), __k))
+ if (!_M_key_compare(_S_key(__x), __k))
__y = __x, __x = _S_left(__x);
else
__x = _S_right(__x);
@@ -2617,7 +2621,7 @@ namespace __rb_tree
const _Key& __k) const
{
while (__x)
- if (_M_impl._M_key_compare(__k, _S_key(__x)))
+ if (_M_key_compare(__k, _S_key(__x)))
__y = __x, __x = _S_left(__x);
else
__x = _S_right(__x);
@@ -2639,9 +2643,9 @@ namespace __rb_tree
_Base_ptr __y = _M_end();
while (__x)
{
- if (_M_impl._M_key_compare(_S_key(__x), __k))
+ if (_M_key_compare(_S_key(__x), __k))
__x = _S_right(__x);
- else if (_M_impl._M_key_compare(__k, _S_key(__x)))
+ else if (_M_key_compare(__k, _S_key(__x)))
__y = __x, __x = _S_left(__x);
else
{
@@ -2671,9 +2675,9 @@ namespace __rb_tree
_Base_ptr __y = _M_end();
while (__x)
{
- if (_M_impl._M_key_compare(_S_key(__x), __k))
+ if (_M_key_compare(_S_key(__x), __k))
__x = _S_right(__x);
- else if (_M_impl._M_key_compare(__k, _S_key(__x)))
+ else if (_M_key_compare(__k, _S_key(__x)))
__y = __x, __x = _S_left(__x);
else
{
@@ -2737,7 +2741,7 @@ namespace __rb_tree
while (__x)
{
__y = __x;
- __comp = _M_impl._M_key_compare(__k, _S_key(__x));
+ __comp = _M_key_compare(__k, _S_key(__x));
__x = __comp ? _S_left(__x) : _S_right(__x);
}
iterator __j = iterator(__y);
@@ -2748,7 +2752,7 @@ namespace __rb_tree
else
--__j;
}
- if (_M_impl._M_key_compare(_S_key(__j._M_node), __k))
+ if (_M_key_compare(_S_key(__j._M_node), __k))
return _Res(__x, __y);
return _Res(__j._M_node, _Base_ptr());
}
@@ -2768,8 +2772,7 @@ namespace __rb_tree
while (__x)
{
__y = __x;
- __x = _M_impl._M_key_compare(__k, _S_key(__x)) ?
- _S_left(__x) : _S_right(__x);
+ __x = _M_key_compare(__k, _S_key(__x)) ? _S_left(__x) : _S_right(__x);
}
return _Res(__x, __y);
}
@@ -2838,19 +2841,18 @@ namespace __rb_tree
// end()
if (__position._M_node == _M_end())
{
- if (size() > 0
- && _M_impl._M_key_compare(_S_key(_M_rightmost()), __k))
+ if (size() > 0 && _M_key_compare(_S_key(_M_rightmost()), __k))
return _Res(_Base_ptr(), _M_rightmost());
else
return _M_get_insert_unique_pos(__k);
}
- else if (_M_impl._M_key_compare(__k, _S_key(__position._M_node)))
+ else if (_M_key_compare(__k, _S_key(__position._M_node)))
{
// First, try before...
iterator __before(__position._M_node);
if (__position._M_node == _M_leftmost()) // begin()
return _Res(_M_leftmost(), _M_leftmost());
- else if (_M_impl._M_key_compare(_S_key((--__before)._M_node), __k))
+ else if (_M_key_compare(_S_key((--__before)._M_node), __k))
{
if (!_S_right(__before._M_node))
return _Res(_Base_ptr(), __before._M_node);
@@ -2860,13 +2862,13 @@ namespace __rb_tree
else
return _M_get_insert_unique_pos(__k);
}
- else if (_M_impl._M_key_compare(_S_key(__position._M_node), __k))
+ else if (_M_key_compare(_S_key(__position._M_node), __k))
{
// ... then try after.
iterator __after(__position._M_node);
if (__position._M_node == _M_rightmost())
return _Res(_Base_ptr(), _M_rightmost());
- else if (_M_impl._M_key_compare(__k, _S_key((++__after)._M_node)))
+ else if (_M_key_compare(__k, _S_key((++__after)._M_node)))
{
if (!_S_right(__position._M_node))
return _Res(_Base_ptr(), __position._M_node);
@@ -2923,18 +2925,18 @@ namespace __rb_tree
if (__position._M_node == _M_end())
{
if (size() > 0
- && !_M_impl._M_key_compare(__k, _S_key(_M_rightmost())))
+ && !_M_key_compare(__k, _S_key(_M_rightmost())))
return _Res(_Base_ptr(), _M_rightmost());
else
return _M_get_insert_equal_pos(__k);
}
- else if (!_M_impl._M_key_compare(_S_key(__position._M_node), __k))
+ else if (!_M_key_compare(_S_key(__position._M_node), __k))
{
// First, try before...
iterator __before(__position._M_node);
if (__position._M_node == _M_leftmost()) // begin()
return _Res(_M_leftmost(), _M_leftmost());
- else if (!_M_impl._M_key_compare(__k, _S_key((--__before)._M_node)))
+ else if (!_M_key_compare(__k, _S_key((--__before)._M_node)))
{
if (!_S_right(__before._M_node))
return _Res(_Base_ptr(), __before._M_node);
@@ -2950,7 +2952,7 @@ namespace __rb_tree
iterator __after(__position._M_node);
if (__position._M_node == _M_rightmost())
return _Res(_Base_ptr(), _M_rightmost());
- else if (!_M_impl._M_key_compare(_S_key((++__after)._M_node), __k))
+ else if (!_M_key_compare(_S_key((++__after)._M_node), __k))
{
if (!_S_right(__position._M_node))
return _Res(_Base_ptr(), __position._M_node);
@@ -2999,8 +3001,7 @@ namespace __rb_tree
-> iterator
{
bool __insert_left = (__x || __p == _M_end()
- || _M_impl._M_key_compare(_S_key(__z),
- _S_key(__p)));
+ || _M_key_compare(_S_key(__z), _S_key(__p)));
_Base_ptr __base_z = __z->_M_base_ptr();
_Node_traits::_S_insert_and_rebalance
@@ -3017,8 +3018,7 @@ namespace __rb_tree
-> iterator
{
bool __insert_left = (__p == _M_end()
- || !_M_impl._M_key_compare(_S_key(__p),
- _S_key(__z)));
+ || !_M_key_compare(_S_key(__p), _S_key(__z)));
_Base_ptr __base_z = __z->_M_base_ptr();
_Node_traits::_S_insert_and_rebalance
@@ -3039,7 +3039,7 @@ namespace __rb_tree
while (__x)
{
__y = __x;
- __x = !_M_impl._M_key_compare(_S_key(__x), _S_key(__z)) ?
+ __x = !_M_key_compare(_S_key(__x), _S_key(__z)) ?
_S_left(__x) : _S_right(__x);
}
return _M_insert_lower_node(__y, __z);
@@ -3144,6 +3144,20 @@ namespace __rb_tree
template<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc>
+ typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type
+ _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
+ _M_erase_unique(const _Key& __x)
+ {
+ iterator __it = find(__x);
+ if (__it == end())
+ return 0;
+
+ _M_erase_aux(__it);
+ return 1;
+ }
+
+ template<typename _Key, typename _Val, typename _KeyOfValue,
+ typename _Compare, typename _Alloc>
typename _Rb_tree<_Key, _Val, _KeyOfValue,
_Compare, _Alloc>::iterator
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
@@ -3151,8 +3165,7 @@ namespace __rb_tree
{
iterator __j(_M_lower_bound(_M_begin(), _M_end(), __k));
return (__j == end()
- || _M_impl._M_key_compare(__k,
- _S_key(__j._M_node))) ? end() : __j;
+ || _M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j;
}
template<typename _Key, typename _Val, typename _KeyOfValue,
@@ -3164,8 +3177,7 @@ namespace __rb_tree
{
const_iterator __j(_M_lower_bound(_M_begin(), _M_end(), __k));
return (__j == end()
- || _M_impl._M_key_compare(__k,
- _S_key(__j._M_node))) ? end() : __j;
+ || _M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j;
}
template<typename _Key, typename _Val, typename _KeyOfValue,
@@ -3205,9 +3217,9 @@ namespace __rb_tree
|| (__R && __R->_M_color == _S_red))
return false;
- if (__L && _M_impl._M_key_compare(_S_key(__x), _S_key(__L)))
+ if (__L && _M_key_compare(_S_key(__x), _S_key(__L)))
return false;
- if (__R && _M_impl._M_key_compare(_S_key(__R), _S_key(__x)))
+ if (__R && _M_key_compare(_S_key(__R), _S_key(__x)))
return false;
if (!__L && !__R && _Rb_tree_black_count(__x, _M_root()) != __len)
diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h
index b1428db..70a5646 100644
--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -118,7 +118,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~_UninitDestroyGuard()
{
if (__builtin_expect(_M_cur != 0, 0))
+#if __cplusplus == 201703L
+ // std::uninitialized_{value,default}{,_n} can construct array types,
+ // but std::_Destroy cannot handle them until C++20 (PR 120397).
+ _S_destroy(_M_first, *_M_cur);
+#else
std::_Destroy(_M_first, *_M_cur);
+#endif
}
_GLIBCXX20_CONSTEXPR
@@ -129,6 +135,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
_UninitDestroyGuard(const _UninitDestroyGuard&);
+
+#if __cplusplus == 201703L
+ template<typename _Iter>
+ static void
+ _S_destroy(_Iter __first, _Iter __last)
+ {
+ using _ValT = typename iterator_traits<_Iter>::value_type;
+ if constexpr (is_array<_ValT>::value)
+ for (; __first != __last; ++__first)
+ _S_destroy(*__first, *__first + extent<_ValT>::value);
+ else
+ std::_Destroy(__first, __last);
+ }
+#endif
};
// This is the default implementation of std::uninitialized_copy.
@@ -216,6 +236,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc++17-extensions"
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
/**
* @brief Copies the range [first,last) into result.
* @param __first An input iterator.
@@ -357,7 +378,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::__niter_base(__last),
__x);
else
- std::__do_uninit_copy(__first, __last, __x);
+ std::__do_uninit_fill(__first, __last, __x);
}
// Overload for pointers.
@@ -407,6 +428,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc++17-extensions"
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
#if __glibcxx_raw_memory_algorithms >= 202411L // >= C++26
if consteval {
return std::__do_uninit_fill(__first, __last, __x);
@@ -509,6 +531,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc++17-extensions"
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 1339. uninitialized_fill_n should return the end of its range
/**
@@ -839,7 +862,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_UninitDestroyGuard<_ForwardIterator> __guard(__first);
for (; __first != __last; ++__first)
- std::_Construct(std::__addressof(*__first));
+ std::_Construct(std::addressof(*__first));
__guard.release();
}
};
@@ -856,7 +879,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return;
typename iterator_traits<_ForwardIterator>::value_type* __val
- = std::__addressof(*__first);
+ = std::addressof(*__first);
std::_Construct(__val);
if (++__first != __last)
std::fill(__first, __last, *__val);
@@ -873,7 +896,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_UninitDestroyGuard<_ForwardIterator> __guard(__first);
for (; __n > 0; --__n, (void) ++__first)
- std::_Construct(std::__addressof(*__first));
+ std::_Construct(std::addressof(*__first));
__guard.release();
return __first;
}
@@ -890,7 +913,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__n > 0)
{
typename iterator_traits<_ForwardIterator>::value_type* __val
- = std::__addressof(*__first);
+ = std::addressof(*__first);
std::_Construct(__val);
++__first;
__first = std::fill_n(__first, __n - 1, *__val);
@@ -902,11 +925,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// __uninitialized_default
// Fills [first, last) with value-initialized value_types.
template<typename _ForwardIterator>
- _GLIBCXX26_CONSTEXPR
+ _GLIBCXX20_CONSTEXPR
inline void
__uninitialized_default(_ForwardIterator __first,
_ForwardIterator __last)
{
+#ifdef __cpp_lib_is_constant_evaluated
+ if (std::is_constant_evaluated())
+ return __uninitialized_default_1<false>::
+ __uninit_default(__first, __last);
+#endif
+
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
// trivial types can have deleted assignment
@@ -955,7 +984,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__alloc);
typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
for (; __first != __last; ++__first)
- __traits::construct(__alloc, std::__addressof(*__first));
+ __traits::construct(__alloc, std::addressof(*__first));
__guard.release();
}
@@ -980,7 +1009,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__alloc);
typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
for (; __n > 0; --__n, (void) ++__first)
- __traits::construct(__alloc, std::__addressof(*__first));
+ __traits::construct(__alloc, std::addressof(*__first));
__guard.release();
return __first;
}
@@ -1007,7 +1036,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_UninitDestroyGuard<_ForwardIterator> __guard(__first);
for (; __first != __last; ++__first)
- std::_Construct_novalue(std::__addressof(*__first));
+ std::_Construct_novalue(std::addressof(*__first));
__guard.release();
}
};
@@ -1033,7 +1062,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_UninitDestroyGuard<_ForwardIterator> __guard(__first);
for (; __n > 0; --__n, (void) ++__first)
- std::_Construct_novalue(std::__addressof(*__first));
+ std::_Construct_novalue(std::addressof(*__first));
__guard.release();
return __first;
}
@@ -1089,7 +1118,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_UninitDestroyGuard<_ForwardIterator> __guard(__result);
for (; __n > 0; --__n, (void) ++__first, ++__result)
- std::_Construct(std::__addressof(*__result), *__first);
+ std::_Construct(std::addressof(*__result), *__first);
__guard.release();
return __result;
}
@@ -1112,7 +1141,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_UninitDestroyGuard<_ForwardIterator> __guard(__result);
for (; __n > 0; --__n, (void) ++__first, ++__result)
- std::_Construct(std::__addressof(*__result), *__first);
+ std::_Construct(std::addressof(*__result), *__first);
__guard.release();
return {__first, __result};
}
@@ -1239,9 +1268,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
uninitialized_move(_InputIterator __first, _InputIterator __last,
_ForwardIterator __result)
{
- return std::uninitialized_copy
- (_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
- _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result);
+ return std::uninitialized_copy(std::make_move_iterator(__first),
+ std::make_move_iterator(__last),
+ __result);
}
/**
@@ -1258,9 +1287,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
uninitialized_move_n(_InputIterator __first, _Size __count,
_ForwardIterator __result)
{
- auto __res = std::__uninitialized_copy_n_pair
- (_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
- __count, __result);
+ auto __res
+ = std::__uninitialized_copy_n_pair(std::make_move_iterator(__first),
+ __count, __result);
return {__res.first.base(), __res.second};
}
#endif // __glibcxx_raw_memory_algorithms
@@ -1276,11 +1305,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept(noexcept(std::allocator_traits<_Allocator>::construct(__alloc,
__dest, std::move(*__orig)))
&& noexcept(std::allocator_traits<_Allocator>::destroy(
- __alloc, std::__addressof(*__orig))))
+ __alloc, std::addressof(*__orig))))
{
typedef std::allocator_traits<_Allocator> __traits;
__traits::construct(__alloc, __dest, std::move(*__orig));
- __traits::destroy(__alloc, std::__addressof(*__orig));
+ __traits::destroy(__alloc, std::addressof(*__orig));
}
// This class may be specialized for specific types.
@@ -1308,8 +1337,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"relocation is only possible for values of the same type");
_ForwardIterator __cur = __result;
for (; __first != __last; ++__first, (void)++__cur)
- std::__relocate_object_a(std::__addressof(*__cur),
- std::__addressof(*__first), __alloc);
+ std::__relocate_object_a(std::addressof(*__cur),
+ std::addressof(*__first), __alloc);
return __cur;
}
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index aff9d5d..7625333 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -372,8 +372,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX20_CONSTEXPR
~_Vector_base() _GLIBCXX_NOEXCEPT
{
- _M_deallocate(_M_impl._M_start,
- _M_impl._M_end_of_storage - _M_impl._M_start);
+ ptrdiff_t __n = _M_impl._M_end_of_storage - _M_impl._M_start;
+ if (__n < 0)
+ __builtin_unreachable();
+ _M_deallocate(_M_impl._M_start, size_t(__n));
}
public:
@@ -518,29 +520,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return _S_nothrow_relocate(__is_move_insertable<_Tp_alloc_type>{});
}
- static pointer
- _S_do_relocate(pointer __first, pointer __last, pointer __result,
- _Tp_alloc_type& __alloc, true_type) noexcept
- {
- return std::__relocate_a(__first, __last, __result, __alloc);
- }
-
- static pointer
- _S_do_relocate(pointer, pointer, pointer __result,
- _Tp_alloc_type&, false_type) noexcept
- { return __result; }
-
static _GLIBCXX20_CONSTEXPR pointer
_S_relocate(pointer __first, pointer __last, pointer __result,
_Tp_alloc_type& __alloc) noexcept
{
-#if __cpp_if_constexpr
- // All callers have already checked _S_use_relocate() so just do it.
- return std::__relocate_a(__first, __last, __result, __alloc);
-#else
- using __do_it = __bool_constant<_S_use_relocate()>;
- return _S_do_relocate(__first, __last, __result, __alloc, __do_it{});
-#endif
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ if constexpr (_S_use_relocate())
+ return std::__relocate_a(__first, __last, __result, __alloc);
+ else
+ return __result;
+#pragma GCC diagnostic pop
}
#endif // C++11
@@ -1118,7 +1108,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
ptrdiff_t __dif = this->_M_impl._M_finish - this->_M_impl._M_start;
if (__dif < 0)
- __builtin_unreachable ();
+ __builtin_unreachable();
return size_type(__dif);
}
@@ -1164,7 +1154,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
resize(size_type __new_size, const value_type& __x)
{
if (__new_size > size())
- _M_fill_insert(end(), __new_size - size(), __x);
+ _M_fill_append(__new_size - size(), __x);
else if (__new_size < size())
_M_erase_at_end(this->_M_impl._M_start + __new_size);
}
@@ -1185,7 +1175,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
resize(size_type __new_size, value_type __x = value_type())
{
if (__new_size > size())
- _M_fill_insert(end(), __new_size - size(), __x);
+ _M_fill_append(__new_size - size(), __x);
else if (__new_size < size())
_M_erase_at_end(this->_M_impl._M_start + __new_size);
}
@@ -1210,7 +1200,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
ptrdiff_t __dif = this->_M_impl._M_end_of_storage
- this->_M_impl._M_start;
if (__dif < 0)
- __builtin_unreachable ();
+ __builtin_unreachable();
return size_type(__dif);
}
@@ -1981,8 +1971,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_range_initialize_n(_Iterator __first, _Sentinel __last,
size_type __n)
{
- pointer __start = this->_M_impl._M_start =
+ pointer __start =
this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator()));
+ this->_M_impl._M_start = this->_M_impl._M_finish = __start;
this->_M_impl._M_end_of_storage = __start + __n;
this->_M_impl._M_finish
= std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
@@ -2097,6 +2088,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void
_M_fill_insert(iterator __pos, size_type __n, const value_type& __x);
+ // Called by resize(n,x), and the _M_fill_insert(end(), n, x)
+ _GLIBCXX20_CONSTEXPR
+ void
+ _M_fill_append(size_type __n, const value_type& __x);
+
#if __cplusplus >= 201103L
// Called by resize(n).
_GLIBCXX20_CONSTEXPR
diff --git a/libstdc++-v3/include/bits/this_thread_sleep.h b/libstdc++-v3/include/bits/this_thread_sleep.h
index 57f89f8..7c9d573 100644
--- a/libstdc++-v3/include/bits/this_thread_sleep.h
+++ b/libstdc++-v3/include/bits/this_thread_sleep.h
@@ -59,11 +59,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
#ifndef _GLIBCXX_NO_SLEEP
-#ifndef _GLIBCXX_USE_NANOSLEEP
- void
- __sleep_for(chrono::seconds, chrono::nanoseconds);
-#endif
-
/// this_thread::sleep_for
template<typename _Rep, typename _Period>
inline void
@@ -71,18 +66,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__rtime <= __rtime.zero())
return;
- auto __s = chrono::duration_cast<chrono::seconds>(__rtime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__rtime - __s);
+
+ struct timespec __ts = chrono::__to_timeout_timespec(__rtime);
#ifdef _GLIBCXX_USE_NANOSLEEP
- struct ::timespec __ts =
- {
- static_cast<std::time_t>(__s.count()),
- static_cast<long>(__ns.count())
- };
while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
{ }
#else
- __sleep_for(__s, __ns);
+ using chrono::seconds;
+ using chrono::nanoseconds;
+ void __sleep_for(seconds __s, nanoseconds __ns);
+ __sleep_for(seconds(__ts.tv_sec), nanoseconds(__ts.tv_nsec));
#endif
}
diff --git a/libstdc++-v3/include/bits/unicode-data.h b/libstdc++-v3/include/bits/unicode-data.h
index 0ab5ecb..45a68de 100644
--- a/libstdc++-v3/include/bits/unicode-data.h
+++ b/libstdc++-v3/include/bits/unicode-data.h
@@ -51,17 +51,17 @@
0x3250, 0xa48d, 0xa490, 0xa4c7, 0xa960, 0xa97d, 0xac00, 0xd7a4,
0xf900, 0xfb00, 0xfe10, 0xfe1a, 0xfe30, 0xfe53, 0xfe54, 0xfe67,
0xfe68, 0xfe6c, 0xff01, 0xff61, 0xffe0, 0xffe7, 0x16fe0, 0x16fe5,
- 0x16ff0, 0x16ff2, 0x17000, 0x187f8, 0x18800, 0x18cd6, 0x18cff, 0x18d09,
+ 0x16ff0, 0x16ff7, 0x17000, 0x18cd6, 0x18cff, 0x18d1f, 0x18d80, 0x18df3,
0x1aff0, 0x1aff4, 0x1aff5, 0x1affc, 0x1affd, 0x1afff, 0x1b000, 0x1b123,
0x1b132, 0x1b133, 0x1b150, 0x1b153, 0x1b155, 0x1b156, 0x1b164, 0x1b168,
0x1b170, 0x1b2fc, 0x1d300, 0x1d357, 0x1d360, 0x1d377, 0x1f004, 0x1f005,
0x1f0cf, 0x1f0d0, 0x1f18e, 0x1f18f, 0x1f191, 0x1f19b, 0x1f200, 0x1f203,
0x1f210, 0x1f23c, 0x1f240, 0x1f249, 0x1f250, 0x1f252, 0x1f260, 0x1f266,
0x1f300, 0x1f650, 0x1f680, 0x1f6c6, 0x1f6cc, 0x1f6cd, 0x1f6d0, 0x1f6d3,
- 0x1f6d5, 0x1f6d8, 0x1f6dc, 0x1f6e0, 0x1f6eb, 0x1f6ed, 0x1f6f4, 0x1f6fd,
+ 0x1f6d5, 0x1f6d9, 0x1f6dc, 0x1f6e0, 0x1f6eb, 0x1f6ed, 0x1f6f4, 0x1f6fd,
0x1f7e0, 0x1f7ec, 0x1f7f0, 0x1f7f1, 0x1f900, 0x1fa00, 0x1fa70, 0x1fa7d,
- 0x1fa80, 0x1fa8a, 0x1fa8f, 0x1fac7, 0x1face, 0x1fadd, 0x1fadf, 0x1faea,
- 0x1faf0, 0x1faf9, 0x20000, 0x2fffe, 0x30000, 0x3fffe,
+ 0x1fa80, 0x1fa8b, 0x1fa8e, 0x1fac7, 0x1fac8, 0x1fac9, 0x1facd, 0x1fadd,
+ 0x1fadf, 0x1faeb, 0x1faef, 0x1faf9, 0x20000, 0x2fffe, 0x30000, 0x3fffe,
};
// Values generated by contrib/unicode/gen_libstdcxx_unicode_data.py,
@@ -76,7 +76,7 @@
0xc39, 0xc3a, 0xdbb, 0xdbc, 0xe1d, 0xe20,
0xe97, 0xe9a, 0xf65, 0xf80, 0xff7, 0xffa,
0x105d, 0x1060, 0x107f, 0x1080, 0x10b9, 0x10bc,
- 0x10bf, 0x10c0, 0x10d7, 0x10e0, 0x111f, 0x112e,
+ 0x10bf, 0x10c0, 0x10d7, 0x10e0, 0x1121, 0x112e,
0x11c5, 0x11c6, 0x1309, 0x130a, 0x131b, 0x131e,
0x1323, 0x1326, 0x1353, 0x1354, 0x1363, 0x1364,
0x1367, 0x136c, 0x1375, 0x1378, 0x138b, 0x138e,
@@ -104,11 +104,11 @@
0x17a3, 0x17ae, 0x17b1, 0x17cc, 0x17f7, 0x1800,
0x181b, 0x181c, 0x1823, 0x1824, 0x1853, 0x1854,
0x1875, 0x1878, 0x188b, 0x188c, 0x1893, 0x1894,
- 0x189d, 0x18aa, 0x18af, 0x18b0, 0x18b7, 0x18ba,
+ 0x189d, 0x18aa, 0x18af, 0x18b0, 0x18b7, 0x18b8,
0x18bd, 0x18c0, 0x18c9, 0x18cc, 0x18e1, 0x18ee,
0x191b, 0x191c, 0x1923, 0x1924, 0x1953, 0x1954,
0x1969, 0x196a, 0x1975, 0x1978, 0x198b, 0x198c,
- 0x1993, 0x1994, 0x199d, 0x19aa, 0x19af, 0x19ba,
+ 0x1993, 0x1994, 0x199d, 0x19aa, 0x19af, 0x19b8,
0x19bf, 0x19c0, 0x19c9, 0x19cc, 0x19e1, 0x19e2,
0x19e9, 0x1a00, 0x1a1b, 0x1a1c, 0x1a23, 0x1a24,
0x1a8b, 0x1a8c, 0x1a93, 0x1a94, 0x1aa1, 0x1aa8,
@@ -141,19 +141,19 @@
0x32eb, 0x3300, 0x3359, 0x3360, 0x3395, 0x33a0,
0x33b7, 0x33bc, 0x3439, 0x343c, 0x34bf, 0x34c0,
0x34fb, 0x34fe, 0x3515, 0x3520, 0x3535, 0x3540,
- 0x355d, 0x3560, 0x359f, 0x3600, 0x369b, 0x369c,
- 0x37e9, 0x37f8, 0x3871, 0x3876, 0x3895, 0x389a,
- 0x3917, 0x3920, 0x3977, 0x397a, 0x3991, 0x39a0,
- 0x39f7, 0x3a00, 0x3e2d, 0x3e30, 0x3e3d, 0x3e40,
- 0x3e8d, 0x3e90, 0x3e9d, 0x3ea0, 0x3eb1, 0x3eb2,
- 0x3eb5, 0x3eb6, 0x3eb9, 0x3eba, 0x3ebd, 0x3ebe,
- 0x3efd, 0x3f00, 0x3f6b, 0x3f6c, 0x3f8b, 0x3f8c,
- 0x3fa9, 0x3fac, 0x3fb9, 0x3fba, 0x3fe1, 0x3fe4,
- 0x3feb, 0x3fec, 0x3fff, 0x4020, 0x4051, 0x4060,
- 0x40bf, 0x40e0, 0x40e5, 0x40e8, 0x411f, 0x4120,
- 0x413b, 0x4140, 0x4183, 0x41a0, 0x41e3, 0x4200,
- 0x4319, 0x4320, 0x4855, 0x4880, 0x4897, 0x48c0,
- 0x56e9, 0x56ec, 0x572d, 0x572e, 0x59e9, 0x59f2,
+ 0x355d, 0x3560, 0x35bd, 0x35c0, 0x35d9, 0x3600,
+ 0x369b, 0x369c, 0x37e9, 0x37f8, 0x3871, 0x3876,
+ 0x3895, 0x389a, 0x3917, 0x3920, 0x3977, 0x397a,
+ 0x3991, 0x39a0, 0x39f7, 0x3a00, 0x3e2d, 0x3e30,
+ 0x3e3d, 0x3e40, 0x3e8d, 0x3e90, 0x3e9d, 0x3ea0,
+ 0x3eb1, 0x3eb2, 0x3eb5, 0x3eb6, 0x3eb9, 0x3eba,
+ 0x3ebd, 0x3ebe, 0x3efd, 0x3f00, 0x3f6b, 0x3f6c,
+ 0x3f8b, 0x3f8c, 0x3fa9, 0x3fac, 0x3fb9, 0x3fba,
+ 0x3fe1, 0x3fe4, 0x3feb, 0x3fec, 0x3fff, 0x4020,
+ 0x4051, 0x4060, 0x40bf, 0x40e0, 0x40e5, 0x40e8,
+ 0x411f, 0x4120, 0x413b, 0x4140, 0x4185, 0x41a0,
+ 0x41e3, 0x4200, 0x4319, 0x4320, 0x4855, 0x4880,
+ 0x4897, 0x48c0, 0x56e9, 0x56ec, 0x59e9, 0x59f2,
0x5a4d, 0x5a4e, 0x5a51, 0x5a5a, 0x5a5d, 0x5a60,
0x5ad1, 0x5ade, 0x5ae3, 0x5afe, 0x5b2f, 0x5b40,
0x5b4f, 0x5b50, 0x5b5f, 0x5b60, 0x5b6f, 0x5b70,
@@ -164,8 +164,7 @@
0x6201, 0x620a, 0x6261, 0x6262, 0x631f, 0x6320,
0x63cd, 0x63de, 0x643f, 0x6440, 0x1491b, 0x14920,
0x1498f, 0x149a0, 0x14c59, 0x14c80, 0x14df1, 0x14e00,
- 0x14f9d, 0x14fa0, 0x14fa5, 0x14fa6, 0x14fa9, 0x14faa,
- 0x14fbb, 0x14fe4, 0x1505b, 0x15060, 0x15075, 0x15080,
+ 0x14fbb, 0x14fe2, 0x1505b, 0x15060, 0x15075, 0x15080,
0x150f1, 0x15100, 0x1518d, 0x1519c, 0x151b5, 0x151c0,
0x152a9, 0x152be, 0x152fb, 0x15300, 0x1539d, 0x1539e,
0x153b5, 0x153bc, 0x153ff, 0x15400, 0x1546f, 0x15480,
@@ -177,7 +176,6 @@
0x1f4dd, 0x1f4e0, 0x1f5b5, 0x1f600, 0x1f60f, 0x1f626,
0x1f631, 0x1f63a, 0x1f66f, 0x1f670, 0x1f67b, 0x1f67c,
0x1f67f, 0x1f680, 0x1f685, 0x1f686, 0x1f68b, 0x1f68c,
- 0x1f787, 0x1f7a6, 0x1fb21, 0x1fb24, 0x1fb91, 0x1fb9e,
0x1fba1, 0x1fbe0, 0x1fc35, 0x1fc40, 0x1fca7, 0x1fca8,
0x1fccf, 0x1fcd0, 0x1fcd9, 0x1fce0, 0x1fceb, 0x1fcec,
0x1fdfb, 0x1fe02, 0x1ff7f, 0x1ff84, 0x1ff91, 0x1ff94,
@@ -201,7 +199,7 @@
0x2106d, 0x2106e, 0x21073, 0x21078, 0x2107b, 0x2107e,
0x210ad, 0x210ae, 0x2113f, 0x2114e, 0x21161, 0x211c0,
0x211e7, 0x211e8, 0x211ed, 0x211f6, 0x21239, 0x2123e,
- 0x21275, 0x2127e, 0x21281, 0x21300, 0x21371, 0x21378,
+ 0x21275, 0x2127e, 0x212b5, 0x21300, 0x21371, 0x21378,
0x213a1, 0x213a4, 0x21409, 0x2140a, 0x2140f, 0x21418,
0x21429, 0x2142a, 0x21431, 0x21432, 0x2146d, 0x21470,
0x21477, 0x2147e, 0x21493, 0x214a0, 0x214b3, 0x214c0,
@@ -212,108 +210,112 @@
0x21a51, 0x21a60, 0x21a75, 0x21a80, 0x21acd, 0x21ad2,
0x21b0d, 0x21b1c, 0x21b21, 0x21cc0, 0x21cff, 0x21d00,
0x21d55, 0x21d56, 0x21d5d, 0x21d60, 0x21d65, 0x21d84,
- 0x21d8b, 0x21df8, 0x21e51, 0x21e60, 0x21eb5, 0x21ee0,
- 0x21f15, 0x21f60, 0x21f99, 0x21fc0, 0x21fef, 0x22000,
- 0x2209d, 0x220a4, 0x220ed, 0x220fe, 0x2217b, 0x2217c,
- 0x22187, 0x221a0, 0x221d3, 0x221e0, 0x221f5, 0x22200,
- 0x2226b, 0x2226c, 0x22291, 0x222a0, 0x222ef, 0x22300,
- 0x223c1, 0x223c2, 0x223eb, 0x22400, 0x22425, 0x22426,
- 0x22485, 0x22500, 0x2250f, 0x22510, 0x22513, 0x22514,
- 0x2251d, 0x2251e, 0x2253d, 0x2253e, 0x22555, 0x22560,
- 0x225d7, 0x225e0, 0x225f5, 0x22600, 0x22609, 0x2260a,
- 0x2261b, 0x2261e, 0x22623, 0x22626, 0x22653, 0x22654,
- 0x22663, 0x22664, 0x22669, 0x2266a, 0x22675, 0x22676,
- 0x2268b, 0x2268e, 0x22693, 0x22696, 0x2269d, 0x226a0,
- 0x226a3, 0x226ae, 0x226b1, 0x226ba, 0x226c9, 0x226cc,
- 0x226db, 0x226e0, 0x226eb, 0x22700, 0x22715, 0x22716,
- 0x22719, 0x2271c, 0x2271f, 0x22720, 0x2276d, 0x2276e,
- 0x22783, 0x22784, 0x22787, 0x2278a, 0x2278d, 0x2278e,
- 0x22797, 0x22798, 0x227ad, 0x227ae, 0x227b3, 0x227c2,
- 0x227c7, 0x22800, 0x228b9, 0x228ba, 0x228c5, 0x22900,
- 0x22991, 0x229a0, 0x229b5, 0x22b00, 0x22b6d, 0x22b70,
- 0x22bbd, 0x22c00, 0x22c8b, 0x22ca0, 0x22cb5, 0x22cc0,
- 0x22cdb, 0x22d00, 0x22d75, 0x22d80, 0x22d95, 0x22da0,
- 0x22dc9, 0x22e00, 0x22e37, 0x22e3a, 0x22e59, 0x22e60,
- 0x22e8f, 0x23000, 0x23079, 0x23140, 0x231e7, 0x231fe,
- 0x2320f, 0x23212, 0x23215, 0x23218, 0x23229, 0x2322a,
- 0x2322f, 0x23230, 0x2326d, 0x2326e, 0x23273, 0x23276,
- 0x2328f, 0x232a0, 0x232b5, 0x23340, 0x23351, 0x23354,
- 0x233b1, 0x233b4, 0x233cb, 0x23400, 0x23491, 0x234a0,
- 0x23547, 0x23560, 0x235f3, 0x23600, 0x23615, 0x23780,
- 0x237c5, 0x237e0, 0x237f5, 0x23800, 0x23813, 0x23814,
- 0x2386f, 0x23870, 0x2388d, 0x238a0, 0x238db, 0x238e0,
- 0x23921, 0x23924, 0x23951, 0x23952, 0x2396f, 0x23a00,
- 0x23a0f, 0x23a10, 0x23a15, 0x23a16, 0x23a6f, 0x23a74,
- 0x23a77, 0x23a78, 0x23a7d, 0x23a7e, 0x23a91, 0x23aa0,
- 0x23ab5, 0x23ac0, 0x23acd, 0x23ace, 0x23ad3, 0x23ad4,
- 0x23b1f, 0x23b20, 0x23b25, 0x23b26, 0x23b33, 0x23b40,
- 0x23b55, 0x23dc0, 0x23df3, 0x23e00, 0x23e23, 0x23e24,
- 0x23e77, 0x23e7c, 0x23eb7, 0x23f60, 0x23f63, 0x23f80,
- 0x23fe5, 0x23ffe, 0x24735, 0x24800, 0x248df, 0x248e0,
- 0x248eb, 0x24900, 0x24a89, 0x25f20, 0x25fe7, 0x26000,
- 0x26861, 0x26880, 0x268ad, 0x268c0, 0x287f7, 0x28800,
- 0x28c8f, 0x2c200, 0x2c275, 0x2d000, 0x2d473, 0x2d480,
- 0x2d4bf, 0x2d4c0, 0x2d4d5, 0x2d4dc, 0x2d57f, 0x2d580,
- 0x2d595, 0x2d5a0, 0x2d5dd, 0x2d5e0, 0x2d5ed, 0x2d600,
- 0x2d68d, 0x2d6a0, 0x2d6b5, 0x2d6b6, 0x2d6c5, 0x2d6c6,
- 0x2d6f1, 0x2d6fa, 0x2d721, 0x2da80, 0x2daf5, 0x2dc80,
- 0x2dd37, 0x2de00, 0x2de97, 0x2de9e, 0x2df11, 0x2df1e,
- 0x2df41, 0x2dfc0, 0x2dfcb, 0x2dfe0, 0x2dfe5, 0x2e000,
- 0x30ff1, 0x31000, 0x319ad, 0x319fe, 0x31a13, 0x35fe0,
+ 0x21d91, 0x21da0, 0x21db3, 0x21df4, 0x21e51, 0x21e60,
+ 0x21eb5, 0x21ee0, 0x21f15, 0x21f60, 0x21f99, 0x21fc0,
+ 0x21fef, 0x22000, 0x2209d, 0x220a4, 0x220ed, 0x220fe,
+ 0x2217b, 0x2217c, 0x22187, 0x221a0, 0x221d3, 0x221e0,
+ 0x221f5, 0x22200, 0x2226b, 0x2226c, 0x22291, 0x222a0,
+ 0x222ef, 0x22300, 0x223c1, 0x223c2, 0x223eb, 0x22400,
+ 0x22425, 0x22426, 0x22485, 0x22500, 0x2250f, 0x22510,
+ 0x22513, 0x22514, 0x2251d, 0x2251e, 0x2253d, 0x2253e,
+ 0x22555, 0x22560, 0x225d7, 0x225e0, 0x225f5, 0x22600,
+ 0x22609, 0x2260a, 0x2261b, 0x2261e, 0x22623, 0x22626,
+ 0x22653, 0x22654, 0x22663, 0x22664, 0x22669, 0x2266a,
+ 0x22675, 0x22676, 0x2268b, 0x2268e, 0x22693, 0x22696,
+ 0x2269d, 0x226a0, 0x226a3, 0x226ae, 0x226b1, 0x226ba,
+ 0x226c9, 0x226cc, 0x226db, 0x226e0, 0x226eb, 0x22700,
+ 0x22715, 0x22716, 0x22719, 0x2271c, 0x2271f, 0x22720,
+ 0x2276d, 0x2276e, 0x22783, 0x22784, 0x22787, 0x2278a,
+ 0x2278d, 0x2278e, 0x22797, 0x22798, 0x227ad, 0x227ae,
+ 0x227b3, 0x227c2, 0x227c7, 0x22800, 0x228b9, 0x228ba,
+ 0x228c5, 0x22900, 0x22991, 0x229a0, 0x229b5, 0x22b00,
+ 0x22b6d, 0x22b70, 0x22bbd, 0x22c00, 0x22c8b, 0x22ca0,
+ 0x22cb5, 0x22cc0, 0x22cdb, 0x22d00, 0x22d75, 0x22d80,
+ 0x22d95, 0x22da0, 0x22dc9, 0x22e00, 0x22e37, 0x22e3a,
+ 0x22e59, 0x22e60, 0x22e8f, 0x23000, 0x23079, 0x23140,
+ 0x231e7, 0x231fe, 0x2320f, 0x23212, 0x23215, 0x23218,
+ 0x23229, 0x2322a, 0x2322f, 0x23230, 0x2326d, 0x2326e,
+ 0x23273, 0x23276, 0x2328f, 0x232a0, 0x232b5, 0x23340,
+ 0x23351, 0x23354, 0x233b1, 0x233b4, 0x233cb, 0x23400,
+ 0x23491, 0x234a0, 0x23547, 0x23560, 0x235f3, 0x23600,
+ 0x23615, 0x236c0, 0x236d1, 0x23780, 0x237c5, 0x237e0,
+ 0x237f5, 0x23800, 0x23813, 0x23814, 0x2386f, 0x23870,
+ 0x2388d, 0x238a0, 0x238db, 0x238e0, 0x23921, 0x23924,
+ 0x23951, 0x23952, 0x2396f, 0x23a00, 0x23a0f, 0x23a10,
+ 0x23a15, 0x23a16, 0x23a6f, 0x23a74, 0x23a77, 0x23a78,
+ 0x23a7d, 0x23a7e, 0x23a91, 0x23aa0, 0x23ab5, 0x23ac0,
+ 0x23acd, 0x23ace, 0x23ad3, 0x23ad4, 0x23b1f, 0x23b20,
+ 0x23b25, 0x23b26, 0x23b33, 0x23b40, 0x23b55, 0x23b60,
+ 0x23bb9, 0x23bc0, 0x23bd5, 0x23dc0, 0x23df3, 0x23e00,
+ 0x23e23, 0x23e24, 0x23e77, 0x23e7c, 0x23eb7, 0x23f60,
+ 0x23f63, 0x23f80, 0x23fe5, 0x23ffe, 0x24735, 0x24800,
+ 0x248df, 0x248e0, 0x248eb, 0x24900, 0x24a89, 0x25f20,
+ 0x25fe7, 0x26000, 0x26861, 0x26880, 0x268ad, 0x268c0,
+ 0x287f7, 0x28800, 0x28c8f, 0x2c200, 0x2c275, 0x2d000,
+ 0x2d473, 0x2d480, 0x2d4bf, 0x2d4c0, 0x2d4d5, 0x2d4dc,
+ 0x2d57f, 0x2d580, 0x2d595, 0x2d5a0, 0x2d5dd, 0x2d5e0,
+ 0x2d5ed, 0x2d600, 0x2d68d, 0x2d6a0, 0x2d6b5, 0x2d6b6,
+ 0x2d6c5, 0x2d6c6, 0x2d6f1, 0x2d6fa, 0x2d721, 0x2da80,
+ 0x2daf5, 0x2dc80, 0x2dd37, 0x2dd40, 0x2dd73, 0x2dd76,
+ 0x2dda9, 0x2de00, 0x2de97, 0x2de9e, 0x2df11, 0x2df1e,
+ 0x2df41, 0x2dfc0, 0x2dfcb, 0x2dfe0, 0x2dfef, 0x2e000,
+ 0x319ad, 0x319fe, 0x31a3f, 0x31b00, 0x31be7, 0x35fe0,
0x35fe9, 0x35fea, 0x35ff9, 0x35ffa, 0x35fff, 0x36000,
0x36247, 0x36264, 0x36267, 0x362a0, 0x362a7, 0x362aa,
0x362ad, 0x362c8, 0x362d1, 0x362e0, 0x365f9, 0x37800,
0x378d7, 0x378e0, 0x378fb, 0x37900, 0x37913, 0x37920,
- 0x37935, 0x37938, 0x37941, 0x39800, 0x399f5, 0x39a00,
- 0x39d69, 0x39e00, 0x39e5d, 0x39e60, 0x39e8f, 0x39ea0,
- 0x39f89, 0x3a000, 0x3a1ed, 0x3a200, 0x3a24f, 0x3a252,
- 0x3a2e7, 0x3a2f6, 0x3a3d7, 0x3a400, 0x3a48d, 0x3a580,
- 0x3a5a9, 0x3a5c0, 0x3a5e9, 0x3a600, 0x3a6af, 0x3a6c0,
- 0x3a6f3, 0x3a800, 0x3a8ab, 0x3a8ac, 0x3a93b, 0x3a93c,
- 0x3a941, 0x3a944, 0x3a947, 0x3a94a, 0x3a94f, 0x3a952,
- 0x3a95b, 0x3a95c, 0x3a975, 0x3a976, 0x3a979, 0x3a97a,
- 0x3a989, 0x3a98a, 0x3aa0d, 0x3aa0e, 0x3aa17, 0x3aa1a,
- 0x3aa2b, 0x3aa2c, 0x3aa3b, 0x3aa3c, 0x3aa75, 0x3aa76,
- 0x3aa7f, 0x3aa80, 0x3aa8b, 0x3aa8c, 0x3aa8f, 0x3aa94,
- 0x3aaa3, 0x3aaa4, 0x3ad4d, 0x3ad50, 0x3af99, 0x3af9c,
- 0x3b519, 0x3b536, 0x3b541, 0x3b542, 0x3b561, 0x3be00,
- 0x3be3f, 0x3be4a, 0x3be57, 0x3c000, 0x3c00f, 0x3c010,
- 0x3c033, 0x3c036, 0x3c045, 0x3c046, 0x3c04b, 0x3c04c,
- 0x3c057, 0x3c060, 0x3c0dd, 0x3c11e, 0x3c121, 0x3c200,
- 0x3c25b, 0x3c260, 0x3c27d, 0x3c280, 0x3c295, 0x3c29c,
- 0x3c2a1, 0x3c520, 0x3c55f, 0x3c580, 0x3c5f5, 0x3c5fe,
- 0x3c601, 0x3c9a0, 0x3c9f5, 0x3cba0, 0x3cbf7, 0x3cbfe,
- 0x3cc01, 0x3cfc0, 0x3cfcf, 0x3cfd0, 0x3cfd9, 0x3cfda,
- 0x3cfdf, 0x3cfe0, 0x3cfff, 0x3d000, 0x3d18b, 0x3d18e,
- 0x3d1af, 0x3d200, 0x3d299, 0x3d2a0, 0x3d2b5, 0x3d2bc,
- 0x3d2c1, 0x3d8e2, 0x3d96b, 0x3da02, 0x3da7d, 0x3dc00,
- 0x3dc09, 0x3dc0a, 0x3dc41, 0x3dc42, 0x3dc47, 0x3dc48,
- 0x3dc4b, 0x3dc4e, 0x3dc51, 0x3dc52, 0x3dc67, 0x3dc68,
- 0x3dc71, 0x3dc72, 0x3dc75, 0x3dc76, 0x3dc79, 0x3dc84,
- 0x3dc87, 0x3dc8e, 0x3dc91, 0x3dc92, 0x3dc95, 0x3dc96,
- 0x3dc99, 0x3dc9a, 0x3dca1, 0x3dca2, 0x3dca7, 0x3dca8,
- 0x3dcab, 0x3dcae, 0x3dcb1, 0x3dcb2, 0x3dcb5, 0x3dcb6,
- 0x3dcb9, 0x3dcba, 0x3dcbd, 0x3dcbe, 0x3dcc1, 0x3dcc2,
- 0x3dcc7, 0x3dcc8, 0x3dccb, 0x3dcce, 0x3dcd7, 0x3dcd8,
- 0x3dce7, 0x3dce8, 0x3dcf1, 0x3dcf2, 0x3dcfb, 0x3dcfc,
- 0x3dcff, 0x3dd00, 0x3dd15, 0x3dd16, 0x3dd39, 0x3dd42,
- 0x3dd49, 0x3dd4a, 0x3dd55, 0x3dd56, 0x3dd79, 0x3dde0,
- 0x3dde5, 0x3e000, 0x3e059, 0x3e060, 0x3e129, 0x3e140,
- 0x3e15f, 0x3e162, 0x3e181, 0x3e182, 0x3e1a1, 0x3e1a2,
- 0x3e1ed, 0x3e200, 0x3e35d, 0x3e3cc, 0x3e407, 0x3e420,
- 0x3e479, 0x3e480, 0x3e493, 0x3e4a0, 0x3e4a5, 0x3e4c0,
- 0x3e4cd, 0x3e600, 0x3edb1, 0x3edb8, 0x3eddb, 0x3ede0,
- 0x3edfb, 0x3ee00, 0x3eeef, 0x3eef6, 0x3efb5, 0x3efc0,
- 0x3efd9, 0x3efe0, 0x3efe3, 0x3f000, 0x3f019, 0x3f020,
- 0x3f091, 0x3f0a0, 0x3f0b5, 0x3f0c0, 0x3f111, 0x3f120,
- 0x3f15d, 0x3f160, 0x3f179, 0x3f180, 0x3f185, 0x3f200,
- 0x3f4a9, 0x3f4c0, 0x3f4dd, 0x3f4e0, 0x3f4fb, 0x3f500,
- 0x3f515, 0x3f51e, 0x3f58f, 0x3f59c, 0x3f5bb, 0x3f5be,
- 0x3f5d5, 0x3f5e0, 0x3f5f3, 0x3f600, 0x3f727, 0x3f728,
- 0x3f7f5, 0x40000, 0x54dc1, 0x54e00, 0x56e75, 0x56e80,
- 0x5703d, 0x57040, 0x59d45, 0x59d60, 0x5d7c3, 0x5d7e0,
- 0x5dcbd, 0x5f000, 0x5f43d, 0x60000, 0x62697, 0x626a0,
- 0x64761, 0x1c0200, 0x1c03e1,
+ 0x37935, 0x37938, 0x37941, 0x39800, 0x399fb, 0x39a00,
+ 0x39d69, 0x39d74, 0x39da3, 0x39dc0, 0x39de3, 0x39e00,
+ 0x39e5d, 0x39e60, 0x39e8f, 0x39ea0, 0x39f89, 0x3a000,
+ 0x3a1ed, 0x3a200, 0x3a24f, 0x3a252, 0x3a2e7, 0x3a2f6,
+ 0x3a3d7, 0x3a400, 0x3a48d, 0x3a580, 0x3a5a9, 0x3a5c0,
+ 0x3a5e9, 0x3a600, 0x3a6af, 0x3a6c0, 0x3a6f3, 0x3a800,
+ 0x3a8ab, 0x3a8ac, 0x3a93b, 0x3a93c, 0x3a941, 0x3a944,
+ 0x3a947, 0x3a94a, 0x3a94f, 0x3a952, 0x3a95b, 0x3a95c,
+ 0x3a975, 0x3a976, 0x3a979, 0x3a97a, 0x3a989, 0x3a98a,
+ 0x3aa0d, 0x3aa0e, 0x3aa17, 0x3aa1a, 0x3aa2b, 0x3aa2c,
+ 0x3aa3b, 0x3aa3c, 0x3aa75, 0x3aa76, 0x3aa7f, 0x3aa80,
+ 0x3aa8b, 0x3aa8c, 0x3aa8f, 0x3aa94, 0x3aaa3, 0x3aaa4,
+ 0x3ad4d, 0x3ad50, 0x3af99, 0x3af9c, 0x3b519, 0x3b536,
+ 0x3b541, 0x3b542, 0x3b561, 0x3be00, 0x3be3f, 0x3be4a,
+ 0x3be57, 0x3c000, 0x3c00f, 0x3c010, 0x3c033, 0x3c036,
+ 0x3c045, 0x3c046, 0x3c04b, 0x3c04c, 0x3c057, 0x3c060,
+ 0x3c0dd, 0x3c11e, 0x3c121, 0x3c200, 0x3c25b, 0x3c260,
+ 0x3c27d, 0x3c280, 0x3c295, 0x3c29c, 0x3c2a1, 0x3c520,
+ 0x3c55f, 0x3c580, 0x3c5f5, 0x3c5fe, 0x3c601, 0x3c9a0,
+ 0x3c9f5, 0x3cba0, 0x3cbf7, 0x3cbfe, 0x3cc01, 0x3cd80,
+ 0x3cdbf, 0x3cdc0, 0x3cded, 0x3cdfc, 0x3ce01, 0x3cfc0,
+ 0x3cfcf, 0x3cfd0, 0x3cfd9, 0x3cfda, 0x3cfdf, 0x3cfe0,
+ 0x3cfff, 0x3d000, 0x3d18b, 0x3d18e, 0x3d1af, 0x3d200,
+ 0x3d299, 0x3d2a0, 0x3d2b5, 0x3d2bc, 0x3d2c1, 0x3d8e2,
+ 0x3d96b, 0x3da02, 0x3da7d, 0x3dc00, 0x3dc09, 0x3dc0a,
+ 0x3dc41, 0x3dc42, 0x3dc47, 0x3dc48, 0x3dc4b, 0x3dc4e,
+ 0x3dc51, 0x3dc52, 0x3dc67, 0x3dc68, 0x3dc71, 0x3dc72,
+ 0x3dc75, 0x3dc76, 0x3dc79, 0x3dc84, 0x3dc87, 0x3dc8e,
+ 0x3dc91, 0x3dc92, 0x3dc95, 0x3dc96, 0x3dc99, 0x3dc9a,
+ 0x3dca1, 0x3dca2, 0x3dca7, 0x3dca8, 0x3dcab, 0x3dcae,
+ 0x3dcb1, 0x3dcb2, 0x3dcb5, 0x3dcb6, 0x3dcb9, 0x3dcba,
+ 0x3dcbd, 0x3dcbe, 0x3dcc1, 0x3dcc2, 0x3dcc7, 0x3dcc8,
+ 0x3dccb, 0x3dcce, 0x3dcd7, 0x3dcd8, 0x3dce7, 0x3dce8,
+ 0x3dcf1, 0x3dcf2, 0x3dcfb, 0x3dcfc, 0x3dcff, 0x3dd00,
+ 0x3dd15, 0x3dd16, 0x3dd39, 0x3dd42, 0x3dd49, 0x3dd4a,
+ 0x3dd55, 0x3dd56, 0x3dd79, 0x3dde0, 0x3dde5, 0x3e000,
+ 0x3e059, 0x3e060, 0x3e129, 0x3e140, 0x3e15f, 0x3e162,
+ 0x3e181, 0x3e182, 0x3e1a1, 0x3e1a2, 0x3e1ed, 0x3e200,
+ 0x3e35d, 0x3e3cc, 0x3e407, 0x3e420, 0x3e479, 0x3e480,
+ 0x3e493, 0x3e4a0, 0x3e4a5, 0x3e4c0, 0x3e4cd, 0x3e600,
+ 0x3edb3, 0x3edb8, 0x3eddb, 0x3ede0, 0x3edfb, 0x3ee00,
+ 0x3efb5, 0x3efc0, 0x3efd9, 0x3efe0, 0x3efe3, 0x3f000,
+ 0x3f019, 0x3f020, 0x3f091, 0x3f0a0, 0x3f0b5, 0x3f0c0,
+ 0x3f111, 0x3f120, 0x3f15d, 0x3f160, 0x3f179, 0x3f180,
+ 0x3f185, 0x3f1a0, 0x3f1b3, 0x3f200, 0x3f4b1, 0x3f4c0,
+ 0x3f4dd, 0x3f4e0, 0x3f4fb, 0x3f500, 0x3f517, 0x3f51c,
+ 0x3f58f, 0x3f590, 0x3f593, 0x3f59a, 0x3f5bb, 0x3f5be,
+ 0x3f5d7, 0x3f5de, 0x3f5f3, 0x3f600, 0x3f727, 0x3f728,
+ 0x3f7f7, 0x40000, 0x54dc1, 0x54e00, 0x5703d, 0x57040,
+ 0x59d5d, 0x59d60, 0x5d7c3, 0x5d7e0, 0x5dcbd, 0x5f000,
+ 0x5f43d, 0x60000, 0x62697, 0x626a0, 0x668f5, 0x1c0200,
+ 0x1c03e1,
};
enum class _Gcb_property {
@@ -399,236 +401,238 @@
0x19336, 0x19394, 0x193c0, 0x1a174, 0x1a196, 0x1a1b4,
0x1a1c0, 0x1a556, 0x1a564, 0x1a576, 0x1a584, 0x1a5f0,
0x1a604, 0x1a610, 0x1a624, 0x1a630, 0x1a654, 0x1a6d6,
- 0x1a734, 0x1a7d0, 0x1a7f4, 0x1a800, 0x1ab04, 0x1acf0,
- 0x1b004, 0x1b046, 0x1b050, 0x1b344, 0x1b3e6, 0x1b424,
- 0x1b450, 0x1b6b4, 0x1b740, 0x1b804, 0x1b826, 0x1b830,
- 0x1ba16, 0x1ba24, 0x1ba66, 0x1ba84, 0x1bae0, 0x1be64,
- 0x1be76, 0x1be84, 0x1bea6, 0x1bed4, 0x1bee6, 0x1bef4,
- 0x1bf40, 0x1c246, 0x1c2c4, 0x1c346, 0x1c364, 0x1c380,
- 0x1cd04, 0x1cd30, 0x1cd44, 0x1ce16, 0x1ce24, 0x1ce90,
- 0x1ced4, 0x1cee0, 0x1cf44, 0x1cf50, 0x1cf76, 0x1cf84,
- 0x1cfa0, 0x1dc04, 0x1e000, 0x200b1, 0x200c4, 0x200da,
- 0x200e1, 0x20100, 0x20281, 0x202f0, 0x20601, 0x20700,
- 0x20d04, 0x20f10, 0x2cef4, 0x2cf20, 0x2d7f4, 0x2d800,
- 0x2de04, 0x2e000, 0x302a4, 0x30300, 0x30994, 0x309b0,
- 0xa66f4, 0xa6730, 0xa6744, 0xa67e0, 0xa69e4, 0xa6a00,
- 0xa6f04, 0xa6f20, 0xa8024, 0xa8030, 0xa8064, 0xa8070,
- 0xa80b4, 0xa80c0, 0xa8236, 0xa8254, 0xa8276, 0xa8280,
- 0xa82c4, 0xa82d0, 0xa8806, 0xa8820, 0xa8b46, 0xa8c44,
- 0xa8c60, 0xa8e04, 0xa8f20, 0xa8ff4, 0xa9000, 0xa9264,
- 0xa92e0, 0xa9474, 0xa9526, 0xa9534, 0xa9540, 0xa9607,
- 0xa97d0, 0xa9804, 0xa9836, 0xa9840, 0xa9b34, 0xa9b46,
- 0xa9b64, 0xa9ba6, 0xa9bc4, 0xa9be6, 0xa9c04, 0xa9c10,
- 0xa9e54, 0xa9e60, 0xaa294, 0xaa2f6, 0xaa314, 0xaa336,
- 0xaa354, 0xaa370, 0xaa434, 0xaa440, 0xaa4c4, 0xaa4d6,
- 0xaa4e0, 0xaa7c4, 0xaa7d0, 0xaab04, 0xaab10, 0xaab24,
- 0xaab50, 0xaab74, 0xaab90, 0xaabe4, 0xaac00, 0xaac14,
- 0xaac20, 0xaaeb6, 0xaaec4, 0xaaee6, 0xaaf00, 0xaaf56,
- 0xaaf64, 0xaaf70, 0xabe36, 0xabe54, 0xabe66, 0xabe84,
- 0xabe96, 0xabeb0, 0xabec6, 0xabed4, 0xabee0, 0xac00b,
- 0xac01c, 0xac1cb, 0xac1dc, 0xac38b, 0xac39c, 0xac54b,
- 0xac55c, 0xac70b, 0xac71c, 0xac8cb, 0xac8dc, 0xaca8b,
- 0xaca9c, 0xacc4b, 0xacc5c, 0xace0b, 0xace1c, 0xacfcb,
- 0xacfdc, 0xad18b, 0xad19c, 0xad34b, 0xad35c, 0xad50b,
- 0xad51c, 0xad6cb, 0xad6dc, 0xad88b, 0xad89c, 0xada4b,
- 0xada5c, 0xadc0b, 0xadc1c, 0xaddcb, 0xadddc, 0xadf8b,
- 0xadf9c, 0xae14b, 0xae15c, 0xae30b, 0xae31c, 0xae4cb,
- 0xae4dc, 0xae68b, 0xae69c, 0xae84b, 0xae85c, 0xaea0b,
- 0xaea1c, 0xaebcb, 0xaebdc, 0xaed8b, 0xaed9c, 0xaef4b,
- 0xaef5c, 0xaf10b, 0xaf11c, 0xaf2cb, 0xaf2dc, 0xaf48b,
- 0xaf49c, 0xaf64b, 0xaf65c, 0xaf80b, 0xaf81c, 0xaf9cb,
- 0xaf9dc, 0xafb8b, 0xafb9c, 0xafd4b, 0xafd5c, 0xaff0b,
- 0xaff1c, 0xb00cb, 0xb00dc, 0xb028b, 0xb029c, 0xb044b,
- 0xb045c, 0xb060b, 0xb061c, 0xb07cb, 0xb07dc, 0xb098b,
- 0xb099c, 0xb0b4b, 0xb0b5c, 0xb0d0b, 0xb0d1c, 0xb0ecb,
- 0xb0edc, 0xb108b, 0xb109c, 0xb124b, 0xb125c, 0xb140b,
- 0xb141c, 0xb15cb, 0xb15dc, 0xb178b, 0xb179c, 0xb194b,
- 0xb195c, 0xb1b0b, 0xb1b1c, 0xb1ccb, 0xb1cdc, 0xb1e8b,
- 0xb1e9c, 0xb204b, 0xb205c, 0xb220b, 0xb221c, 0xb23cb,
- 0xb23dc, 0xb258b, 0xb259c, 0xb274b, 0xb275c, 0xb290b,
- 0xb291c, 0xb2acb, 0xb2adc, 0xb2c8b, 0xb2c9c, 0xb2e4b,
- 0xb2e5c, 0xb300b, 0xb301c, 0xb31cb, 0xb31dc, 0xb338b,
- 0xb339c, 0xb354b, 0xb355c, 0xb370b, 0xb371c, 0xb38cb,
- 0xb38dc, 0xb3a8b, 0xb3a9c, 0xb3c4b, 0xb3c5c, 0xb3e0b,
- 0xb3e1c, 0xb3fcb, 0xb3fdc, 0xb418b, 0xb419c, 0xb434b,
- 0xb435c, 0xb450b, 0xb451c, 0xb46cb, 0xb46dc, 0xb488b,
- 0xb489c, 0xb4a4b, 0xb4a5c, 0xb4c0b, 0xb4c1c, 0xb4dcb,
- 0xb4ddc, 0xb4f8b, 0xb4f9c, 0xb514b, 0xb515c, 0xb530b,
- 0xb531c, 0xb54cb, 0xb54dc, 0xb568b, 0xb569c, 0xb584b,
- 0xb585c, 0xb5a0b, 0xb5a1c, 0xb5bcb, 0xb5bdc, 0xb5d8b,
- 0xb5d9c, 0xb5f4b, 0xb5f5c, 0xb610b, 0xb611c, 0xb62cb,
- 0xb62dc, 0xb648b, 0xb649c, 0xb664b, 0xb665c, 0xb680b,
- 0xb681c, 0xb69cb, 0xb69dc, 0xb6b8b, 0xb6b9c, 0xb6d4b,
- 0xb6d5c, 0xb6f0b, 0xb6f1c, 0xb70cb, 0xb70dc, 0xb728b,
- 0xb729c, 0xb744b, 0xb745c, 0xb760b, 0xb761c, 0xb77cb,
- 0xb77dc, 0xb798b, 0xb799c, 0xb7b4b, 0xb7b5c, 0xb7d0b,
- 0xb7d1c, 0xb7ecb, 0xb7edc, 0xb808b, 0xb809c, 0xb824b,
- 0xb825c, 0xb840b, 0xb841c, 0xb85cb, 0xb85dc, 0xb878b,
- 0xb879c, 0xb894b, 0xb895c, 0xb8b0b, 0xb8b1c, 0xb8ccb,
- 0xb8cdc, 0xb8e8b, 0xb8e9c, 0xb904b, 0xb905c, 0xb920b,
- 0xb921c, 0xb93cb, 0xb93dc, 0xb958b, 0xb959c, 0xb974b,
- 0xb975c, 0xb990b, 0xb991c, 0xb9acb, 0xb9adc, 0xb9c8b,
- 0xb9c9c, 0xb9e4b, 0xb9e5c, 0xba00b, 0xba01c, 0xba1cb,
- 0xba1dc, 0xba38b, 0xba39c, 0xba54b, 0xba55c, 0xba70b,
- 0xba71c, 0xba8cb, 0xba8dc, 0xbaa8b, 0xbaa9c, 0xbac4b,
- 0xbac5c, 0xbae0b, 0xbae1c, 0xbafcb, 0xbafdc, 0xbb18b,
- 0xbb19c, 0xbb34b, 0xbb35c, 0xbb50b, 0xbb51c, 0xbb6cb,
- 0xbb6dc, 0xbb88b, 0xbb89c, 0xbba4b, 0xbba5c, 0xbbc0b,
- 0xbbc1c, 0xbbdcb, 0xbbddc, 0xbbf8b, 0xbbf9c, 0xbc14b,
- 0xbc15c, 0xbc30b, 0xbc31c, 0xbc4cb, 0xbc4dc, 0xbc68b,
- 0xbc69c, 0xbc84b, 0xbc85c, 0xbca0b, 0xbca1c, 0xbcbcb,
- 0xbcbdc, 0xbcd8b, 0xbcd9c, 0xbcf4b, 0xbcf5c, 0xbd10b,
- 0xbd11c, 0xbd2cb, 0xbd2dc, 0xbd48b, 0xbd49c, 0xbd64b,
- 0xbd65c, 0xbd80b, 0xbd81c, 0xbd9cb, 0xbd9dc, 0xbdb8b,
- 0xbdb9c, 0xbdd4b, 0xbdd5c, 0xbdf0b, 0xbdf1c, 0xbe0cb,
- 0xbe0dc, 0xbe28b, 0xbe29c, 0xbe44b, 0xbe45c, 0xbe60b,
- 0xbe61c, 0xbe7cb, 0xbe7dc, 0xbe98b, 0xbe99c, 0xbeb4b,
- 0xbeb5c, 0xbed0b, 0xbed1c, 0xbeecb, 0xbeedc, 0xbf08b,
- 0xbf09c, 0xbf24b, 0xbf25c, 0xbf40b, 0xbf41c, 0xbf5cb,
- 0xbf5dc, 0xbf78b, 0xbf79c, 0xbf94b, 0xbf95c, 0xbfb0b,
- 0xbfb1c, 0xbfccb, 0xbfcdc, 0xbfe8b, 0xbfe9c, 0xc004b,
- 0xc005c, 0xc020b, 0xc021c, 0xc03cb, 0xc03dc, 0xc058b,
- 0xc059c, 0xc074b, 0xc075c, 0xc090b, 0xc091c, 0xc0acb,
- 0xc0adc, 0xc0c8b, 0xc0c9c, 0xc0e4b, 0xc0e5c, 0xc100b,
- 0xc101c, 0xc11cb, 0xc11dc, 0xc138b, 0xc139c, 0xc154b,
- 0xc155c, 0xc170b, 0xc171c, 0xc18cb, 0xc18dc, 0xc1a8b,
- 0xc1a9c, 0xc1c4b, 0xc1c5c, 0xc1e0b, 0xc1e1c, 0xc1fcb,
- 0xc1fdc, 0xc218b, 0xc219c, 0xc234b, 0xc235c, 0xc250b,
- 0xc251c, 0xc26cb, 0xc26dc, 0xc288b, 0xc289c, 0xc2a4b,
- 0xc2a5c, 0xc2c0b, 0xc2c1c, 0xc2dcb, 0xc2ddc, 0xc2f8b,
- 0xc2f9c, 0xc314b, 0xc315c, 0xc330b, 0xc331c, 0xc34cb,
- 0xc34dc, 0xc368b, 0xc369c, 0xc384b, 0xc385c, 0xc3a0b,
- 0xc3a1c, 0xc3bcb, 0xc3bdc, 0xc3d8b, 0xc3d9c, 0xc3f4b,
- 0xc3f5c, 0xc410b, 0xc411c, 0xc42cb, 0xc42dc, 0xc448b,
- 0xc449c, 0xc464b, 0xc465c, 0xc480b, 0xc481c, 0xc49cb,
- 0xc49dc, 0xc4b8b, 0xc4b9c, 0xc4d4b, 0xc4d5c, 0xc4f0b,
- 0xc4f1c, 0xc50cb, 0xc50dc, 0xc528b, 0xc529c, 0xc544b,
- 0xc545c, 0xc560b, 0xc561c, 0xc57cb, 0xc57dc, 0xc598b,
- 0xc599c, 0xc5b4b, 0xc5b5c, 0xc5d0b, 0xc5d1c, 0xc5ecb,
- 0xc5edc, 0xc608b, 0xc609c, 0xc624b, 0xc625c, 0xc640b,
- 0xc641c, 0xc65cb, 0xc65dc, 0xc678b, 0xc679c, 0xc694b,
- 0xc695c, 0xc6b0b, 0xc6b1c, 0xc6ccb, 0xc6cdc, 0xc6e8b,
- 0xc6e9c, 0xc704b, 0xc705c, 0xc720b, 0xc721c, 0xc73cb,
- 0xc73dc, 0xc758b, 0xc759c, 0xc774b, 0xc775c, 0xc790b,
- 0xc791c, 0xc7acb, 0xc7adc, 0xc7c8b, 0xc7c9c, 0xc7e4b,
- 0xc7e5c, 0xc800b, 0xc801c, 0xc81cb, 0xc81dc, 0xc838b,
- 0xc839c, 0xc854b, 0xc855c, 0xc870b, 0xc871c, 0xc88cb,
- 0xc88dc, 0xc8a8b, 0xc8a9c, 0xc8c4b, 0xc8c5c, 0xc8e0b,
- 0xc8e1c, 0xc8fcb, 0xc8fdc, 0xc918b, 0xc919c, 0xc934b,
- 0xc935c, 0xc950b, 0xc951c, 0xc96cb, 0xc96dc, 0xc988b,
- 0xc989c, 0xc9a4b, 0xc9a5c, 0xc9c0b, 0xc9c1c, 0xc9dcb,
- 0xc9ddc, 0xc9f8b, 0xc9f9c, 0xca14b, 0xca15c, 0xca30b,
- 0xca31c, 0xca4cb, 0xca4dc, 0xca68b, 0xca69c, 0xca84b,
- 0xca85c, 0xcaa0b, 0xcaa1c, 0xcabcb, 0xcabdc, 0xcad8b,
- 0xcad9c, 0xcaf4b, 0xcaf5c, 0xcb10b, 0xcb11c, 0xcb2cb,
- 0xcb2dc, 0xcb48b, 0xcb49c, 0xcb64b, 0xcb65c, 0xcb80b,
- 0xcb81c, 0xcb9cb, 0xcb9dc, 0xcbb8b, 0xcbb9c, 0xcbd4b,
- 0xcbd5c, 0xcbf0b, 0xcbf1c, 0xcc0cb, 0xcc0dc, 0xcc28b,
- 0xcc29c, 0xcc44b, 0xcc45c, 0xcc60b, 0xcc61c, 0xcc7cb,
- 0xcc7dc, 0xcc98b, 0xcc99c, 0xccb4b, 0xccb5c, 0xccd0b,
- 0xccd1c, 0xccecb, 0xccedc, 0xcd08b, 0xcd09c, 0xcd24b,
- 0xcd25c, 0xcd40b, 0xcd41c, 0xcd5cb, 0xcd5dc, 0xcd78b,
- 0xcd79c, 0xcd94b, 0xcd95c, 0xcdb0b, 0xcdb1c, 0xcdccb,
- 0xcdcdc, 0xcde8b, 0xcde9c, 0xce04b, 0xce05c, 0xce20b,
- 0xce21c, 0xce3cb, 0xce3dc, 0xce58b, 0xce59c, 0xce74b,
- 0xce75c, 0xce90b, 0xce91c, 0xceacb, 0xceadc, 0xcec8b,
- 0xcec9c, 0xcee4b, 0xcee5c, 0xcf00b, 0xcf01c, 0xcf1cb,
- 0xcf1dc, 0xcf38b, 0xcf39c, 0xcf54b, 0xcf55c, 0xcf70b,
- 0xcf71c, 0xcf8cb, 0xcf8dc, 0xcfa8b, 0xcfa9c, 0xcfc4b,
- 0xcfc5c, 0xcfe0b, 0xcfe1c, 0xcffcb, 0xcffdc, 0xd018b,
- 0xd019c, 0xd034b, 0xd035c, 0xd050b, 0xd051c, 0xd06cb,
- 0xd06dc, 0xd088b, 0xd089c, 0xd0a4b, 0xd0a5c, 0xd0c0b,
- 0xd0c1c, 0xd0dcb, 0xd0ddc, 0xd0f8b, 0xd0f9c, 0xd114b,
- 0xd115c, 0xd130b, 0xd131c, 0xd14cb, 0xd14dc, 0xd168b,
- 0xd169c, 0xd184b, 0xd185c, 0xd1a0b, 0xd1a1c, 0xd1bcb,
- 0xd1bdc, 0xd1d8b, 0xd1d9c, 0xd1f4b, 0xd1f5c, 0xd210b,
- 0xd211c, 0xd22cb, 0xd22dc, 0xd248b, 0xd249c, 0xd264b,
- 0xd265c, 0xd280b, 0xd281c, 0xd29cb, 0xd29dc, 0xd2b8b,
- 0xd2b9c, 0xd2d4b, 0xd2d5c, 0xd2f0b, 0xd2f1c, 0xd30cb,
- 0xd30dc, 0xd328b, 0xd329c, 0xd344b, 0xd345c, 0xd360b,
- 0xd361c, 0xd37cb, 0xd37dc, 0xd398b, 0xd399c, 0xd3b4b,
- 0xd3b5c, 0xd3d0b, 0xd3d1c, 0xd3ecb, 0xd3edc, 0xd408b,
- 0xd409c, 0xd424b, 0xd425c, 0xd440b, 0xd441c, 0xd45cb,
- 0xd45dc, 0xd478b, 0xd479c, 0xd494b, 0xd495c, 0xd4b0b,
- 0xd4b1c, 0xd4ccb, 0xd4cdc, 0xd4e8b, 0xd4e9c, 0xd504b,
- 0xd505c, 0xd520b, 0xd521c, 0xd53cb, 0xd53dc, 0xd558b,
- 0xd559c, 0xd574b, 0xd575c, 0xd590b, 0xd591c, 0xd5acb,
- 0xd5adc, 0xd5c8b, 0xd5c9c, 0xd5e4b, 0xd5e5c, 0xd600b,
- 0xd601c, 0xd61cb, 0xd61dc, 0xd638b, 0xd639c, 0xd654b,
- 0xd655c, 0xd670b, 0xd671c, 0xd68cb, 0xd68dc, 0xd6a8b,
- 0xd6a9c, 0xd6c4b, 0xd6c5c, 0xd6e0b, 0xd6e1c, 0xd6fcb,
- 0xd6fdc, 0xd718b, 0xd719c, 0xd734b, 0xd735c, 0xd750b,
- 0xd751c, 0xd76cb, 0xd76dc, 0xd788b, 0xd789c, 0xd7a40,
- 0xd7b08, 0xd7c70, 0xd7cb9, 0xd7fc0, 0xfb1e4, 0xfb1f0,
- 0xfe004, 0xfe100, 0xfe204, 0xfe300, 0xfeff1, 0xff000,
- 0xff9e4, 0xffa00, 0xfff01, 0xfffc0, 0x101fd4, 0x101fe0,
- 0x102e04, 0x102e10, 0x103764, 0x1037b0, 0x10a014, 0x10a040,
- 0x10a054, 0x10a070, 0x10a0c4, 0x10a100, 0x10a384, 0x10a3b0,
- 0x10a3f4, 0x10a400, 0x10ae54, 0x10ae70, 0x10d244, 0x10d280,
- 0x10d694, 0x10d6e0, 0x10eab4, 0x10ead0, 0x10efc4, 0x10f000,
- 0x10f464, 0x10f510, 0x10f824, 0x10f860, 0x110006, 0x110014,
- 0x110026, 0x110030, 0x110384, 0x110470, 0x110704, 0x110710,
- 0x110734, 0x110750, 0x1107f4, 0x110826, 0x110830, 0x110b06,
- 0x110b34, 0x110b76, 0x110b94, 0x110bb0, 0x110bd5, 0x110be0,
- 0x110c24, 0x110c30, 0x110cd5, 0x110ce0, 0x111004, 0x111030,
- 0x111274, 0x1112c6, 0x1112d4, 0x111350, 0x111456, 0x111470,
- 0x111734, 0x111740, 0x111804, 0x111826, 0x111830, 0x111b36,
- 0x111b64, 0x111bf6, 0x111c04, 0x111c10, 0x111c25, 0x111c40,
- 0x111c94, 0x111cd0, 0x111ce6, 0x111cf4, 0x111d00, 0x1122c6,
- 0x1122f4, 0x112326, 0x112344, 0x112380, 0x1123e4, 0x1123f0,
- 0x112414, 0x112420, 0x112df4, 0x112e06, 0x112e34, 0x112eb0,
- 0x113004, 0x113026, 0x113040, 0x1133b4, 0x1133d0, 0x1133e4,
- 0x1133f6, 0x113404, 0x113416, 0x113450, 0x113476, 0x113490,
- 0x1134b6, 0x1134d4, 0x1134e0, 0x113574, 0x113580, 0x113626,
- 0x113640, 0x113664, 0x1136d0, 0x113704, 0x113750, 0x113b84,
- 0x113b96, 0x113bb4, 0x113c10, 0x113c24, 0x113c30, 0x113c54,
- 0x113c60, 0x113c74, 0x113ca6, 0x113cb0, 0x113cc6, 0x113ce4,
- 0x113d15, 0x113d24, 0x113d30, 0x113e14, 0x113e30, 0x114356,
- 0x114384, 0x114406, 0x114424, 0x114456, 0x114464, 0x114470,
- 0x1145e4, 0x1145f0, 0x114b04, 0x114b16, 0x114b34, 0x114b96,
- 0x114ba4, 0x114bb6, 0x114bd4, 0x114be6, 0x114bf4, 0x114c16,
- 0x114c24, 0x114c40, 0x115af4, 0x115b06, 0x115b24, 0x115b60,
- 0x115b86, 0x115bc4, 0x115be6, 0x115bf4, 0x115c10, 0x115dc4,
- 0x115de0, 0x116306, 0x116334, 0x1163b6, 0x1163d4, 0x1163e6,
- 0x1163f4, 0x116410, 0x116ab4, 0x116ac6, 0x116ad4, 0x116ae6,
- 0x116b04, 0x116b80, 0x1171d4, 0x1171e6, 0x1171f4, 0x117200,
- 0x117224, 0x117266, 0x117274, 0x1172c0, 0x1182c6, 0x1182f4,
- 0x118386, 0x118394, 0x1183b0, 0x119304, 0x119316, 0x119360,
- 0x119376, 0x119390, 0x1193b4, 0x1193f5, 0x119406, 0x119415,
- 0x119426, 0x119434, 0x119440, 0x119d16, 0x119d44, 0x119d80,
- 0x119da4, 0x119dc6, 0x119e04, 0x119e10, 0x119e46, 0x119e50,
- 0x11a014, 0x11a0b0, 0x11a334, 0x11a396, 0x11a3a5, 0x11a3b4,
- 0x11a3f0, 0x11a474, 0x11a480, 0x11a514, 0x11a576, 0x11a594,
- 0x11a5c0, 0x11a845, 0x11a8a4, 0x11a976, 0x11a984, 0x11a9a0,
- 0x11c2f6, 0x11c304, 0x11c370, 0x11c384, 0x11c3e6, 0x11c3f4,
- 0x11c400, 0x11c924, 0x11ca80, 0x11ca96, 0x11caa4, 0x11cb16,
- 0x11cb24, 0x11cb46, 0x11cb54, 0x11cb70, 0x11d314, 0x11d370,
- 0x11d3a4, 0x11d3b0, 0x11d3c4, 0x11d3e0, 0x11d3f4, 0x11d465,
- 0x11d474, 0x11d480, 0x11d8a6, 0x11d8f0, 0x11d904, 0x11d920,
- 0x11d936, 0x11d954, 0x11d966, 0x11d974, 0x11d980, 0x11ef34,
- 0x11ef56, 0x11ef70, 0x11f004, 0x11f025, 0x11f036, 0x11f040,
- 0x11f346, 0x11f364, 0x11f3b0, 0x11f3e6, 0x11f404, 0x11f430,
- 0x11f5a4, 0x11f5b0, 0x134301, 0x134404, 0x134410, 0x134474,
- 0x134560, 0x1611e4, 0x1612a6, 0x1612d4, 0x161300, 0x16af04,
- 0x16af50, 0x16b304, 0x16b370, 0x16d638, 0x16d640, 0x16d678,
- 0x16d6b0, 0x16f4f4, 0x16f500, 0x16f516, 0x16f880, 0x16f8f4,
- 0x16f930, 0x16fe44, 0x16fe50, 0x16ff04, 0x16ff20, 0x1bc9d4,
- 0x1bc9f0, 0x1bca01, 0x1bca40, 0x1cf004, 0x1cf2e0, 0x1cf304,
- 0x1cf470, 0x1d1654, 0x1d16a0, 0x1d16d4, 0x1d1731, 0x1d17b4,
- 0x1d1830, 0x1d1854, 0x1d18c0, 0x1d1aa4, 0x1d1ae0, 0x1d2424,
- 0x1d2450, 0x1da004, 0x1da370, 0x1da3b4, 0x1da6d0, 0x1da754,
- 0x1da760, 0x1da844, 0x1da850, 0x1da9b4, 0x1daa00, 0x1daa14,
- 0x1dab00, 0x1e0004, 0x1e0070, 0x1e0084, 0x1e0190, 0x1e01b4,
- 0x1e0220, 0x1e0234, 0x1e0250, 0x1e0264, 0x1e02b0, 0x1e08f4,
- 0x1e0900, 0x1e1304, 0x1e1370, 0x1e2ae4, 0x1e2af0, 0x1e2ec4,
- 0x1e2f00, 0x1e4ec4, 0x1e4f00, 0x1e5ee4, 0x1e5f00, 0x1e8d04,
- 0x1e8d70, 0x1e9444, 0x1e94b0, 0x1f1e6d, 0x1f2000, 0x1f3fb4,
- 0x1f4000, 0xe00001, 0xe00204, 0xe00801, 0xe01004, 0xe01f01,
- 0xe10000,
+ 0x1a734, 0x1a7d0, 0x1a7f4, 0x1a800, 0x1ab04, 0x1ade0,
+ 0x1ae04, 0x1aec0, 0x1b004, 0x1b046, 0x1b050, 0x1b344,
+ 0x1b3e6, 0x1b424, 0x1b450, 0x1b6b4, 0x1b740, 0x1b804,
+ 0x1b826, 0x1b830, 0x1ba16, 0x1ba24, 0x1ba66, 0x1ba84,
+ 0x1bae0, 0x1be64, 0x1be76, 0x1be84, 0x1bea6, 0x1bed4,
+ 0x1bee6, 0x1bef4, 0x1bf40, 0x1c246, 0x1c2c4, 0x1c346,
+ 0x1c364, 0x1c380, 0x1cd04, 0x1cd30, 0x1cd44, 0x1ce16,
+ 0x1ce24, 0x1ce90, 0x1ced4, 0x1cee0, 0x1cf44, 0x1cf50,
+ 0x1cf76, 0x1cf84, 0x1cfa0, 0x1dc04, 0x1e000, 0x200b1,
+ 0x200c4, 0x200da, 0x200e1, 0x20100, 0x20281, 0x202f0,
+ 0x20601, 0x20700, 0x20d04, 0x20f10, 0x2cef4, 0x2cf20,
+ 0x2d7f4, 0x2d800, 0x2de04, 0x2e000, 0x302a4, 0x30300,
+ 0x30994, 0x309b0, 0xa66f4, 0xa6730, 0xa6744, 0xa67e0,
+ 0xa69e4, 0xa6a00, 0xa6f04, 0xa6f20, 0xa8024, 0xa8030,
+ 0xa8064, 0xa8070, 0xa80b4, 0xa80c0, 0xa8236, 0xa8254,
+ 0xa8276, 0xa8280, 0xa82c4, 0xa82d0, 0xa8806, 0xa8820,
+ 0xa8b46, 0xa8c44, 0xa8c60, 0xa8e04, 0xa8f20, 0xa8ff4,
+ 0xa9000, 0xa9264, 0xa92e0, 0xa9474, 0xa9526, 0xa9534,
+ 0xa9540, 0xa9607, 0xa97d0, 0xa9804, 0xa9836, 0xa9840,
+ 0xa9b34, 0xa9b46, 0xa9b64, 0xa9ba6, 0xa9bc4, 0xa9be6,
+ 0xa9c04, 0xa9c10, 0xa9e54, 0xa9e60, 0xaa294, 0xaa2f6,
+ 0xaa314, 0xaa336, 0xaa354, 0xaa370, 0xaa434, 0xaa440,
+ 0xaa4c4, 0xaa4d6, 0xaa4e0, 0xaa7c4, 0xaa7d0, 0xaab04,
+ 0xaab10, 0xaab24, 0xaab50, 0xaab74, 0xaab90, 0xaabe4,
+ 0xaac00, 0xaac14, 0xaac20, 0xaaeb6, 0xaaec4, 0xaaee6,
+ 0xaaf00, 0xaaf56, 0xaaf64, 0xaaf70, 0xabe36, 0xabe54,
+ 0xabe66, 0xabe84, 0xabe96, 0xabeb0, 0xabec6, 0xabed4,
+ 0xabee0, 0xac00b, 0xac01c, 0xac1cb, 0xac1dc, 0xac38b,
+ 0xac39c, 0xac54b, 0xac55c, 0xac70b, 0xac71c, 0xac8cb,
+ 0xac8dc, 0xaca8b, 0xaca9c, 0xacc4b, 0xacc5c, 0xace0b,
+ 0xace1c, 0xacfcb, 0xacfdc, 0xad18b, 0xad19c, 0xad34b,
+ 0xad35c, 0xad50b, 0xad51c, 0xad6cb, 0xad6dc, 0xad88b,
+ 0xad89c, 0xada4b, 0xada5c, 0xadc0b, 0xadc1c, 0xaddcb,
+ 0xadddc, 0xadf8b, 0xadf9c, 0xae14b, 0xae15c, 0xae30b,
+ 0xae31c, 0xae4cb, 0xae4dc, 0xae68b, 0xae69c, 0xae84b,
+ 0xae85c, 0xaea0b, 0xaea1c, 0xaebcb, 0xaebdc, 0xaed8b,
+ 0xaed9c, 0xaef4b, 0xaef5c, 0xaf10b, 0xaf11c, 0xaf2cb,
+ 0xaf2dc, 0xaf48b, 0xaf49c, 0xaf64b, 0xaf65c, 0xaf80b,
+ 0xaf81c, 0xaf9cb, 0xaf9dc, 0xafb8b, 0xafb9c, 0xafd4b,
+ 0xafd5c, 0xaff0b, 0xaff1c, 0xb00cb, 0xb00dc, 0xb028b,
+ 0xb029c, 0xb044b, 0xb045c, 0xb060b, 0xb061c, 0xb07cb,
+ 0xb07dc, 0xb098b, 0xb099c, 0xb0b4b, 0xb0b5c, 0xb0d0b,
+ 0xb0d1c, 0xb0ecb, 0xb0edc, 0xb108b, 0xb109c, 0xb124b,
+ 0xb125c, 0xb140b, 0xb141c, 0xb15cb, 0xb15dc, 0xb178b,
+ 0xb179c, 0xb194b, 0xb195c, 0xb1b0b, 0xb1b1c, 0xb1ccb,
+ 0xb1cdc, 0xb1e8b, 0xb1e9c, 0xb204b, 0xb205c, 0xb220b,
+ 0xb221c, 0xb23cb, 0xb23dc, 0xb258b, 0xb259c, 0xb274b,
+ 0xb275c, 0xb290b, 0xb291c, 0xb2acb, 0xb2adc, 0xb2c8b,
+ 0xb2c9c, 0xb2e4b, 0xb2e5c, 0xb300b, 0xb301c, 0xb31cb,
+ 0xb31dc, 0xb338b, 0xb339c, 0xb354b, 0xb355c, 0xb370b,
+ 0xb371c, 0xb38cb, 0xb38dc, 0xb3a8b, 0xb3a9c, 0xb3c4b,
+ 0xb3c5c, 0xb3e0b, 0xb3e1c, 0xb3fcb, 0xb3fdc, 0xb418b,
+ 0xb419c, 0xb434b, 0xb435c, 0xb450b, 0xb451c, 0xb46cb,
+ 0xb46dc, 0xb488b, 0xb489c, 0xb4a4b, 0xb4a5c, 0xb4c0b,
+ 0xb4c1c, 0xb4dcb, 0xb4ddc, 0xb4f8b, 0xb4f9c, 0xb514b,
+ 0xb515c, 0xb530b, 0xb531c, 0xb54cb, 0xb54dc, 0xb568b,
+ 0xb569c, 0xb584b, 0xb585c, 0xb5a0b, 0xb5a1c, 0xb5bcb,
+ 0xb5bdc, 0xb5d8b, 0xb5d9c, 0xb5f4b, 0xb5f5c, 0xb610b,
+ 0xb611c, 0xb62cb, 0xb62dc, 0xb648b, 0xb649c, 0xb664b,
+ 0xb665c, 0xb680b, 0xb681c, 0xb69cb, 0xb69dc, 0xb6b8b,
+ 0xb6b9c, 0xb6d4b, 0xb6d5c, 0xb6f0b, 0xb6f1c, 0xb70cb,
+ 0xb70dc, 0xb728b, 0xb729c, 0xb744b, 0xb745c, 0xb760b,
+ 0xb761c, 0xb77cb, 0xb77dc, 0xb798b, 0xb799c, 0xb7b4b,
+ 0xb7b5c, 0xb7d0b, 0xb7d1c, 0xb7ecb, 0xb7edc, 0xb808b,
+ 0xb809c, 0xb824b, 0xb825c, 0xb840b, 0xb841c, 0xb85cb,
+ 0xb85dc, 0xb878b, 0xb879c, 0xb894b, 0xb895c, 0xb8b0b,
+ 0xb8b1c, 0xb8ccb, 0xb8cdc, 0xb8e8b, 0xb8e9c, 0xb904b,
+ 0xb905c, 0xb920b, 0xb921c, 0xb93cb, 0xb93dc, 0xb958b,
+ 0xb959c, 0xb974b, 0xb975c, 0xb990b, 0xb991c, 0xb9acb,
+ 0xb9adc, 0xb9c8b, 0xb9c9c, 0xb9e4b, 0xb9e5c, 0xba00b,
+ 0xba01c, 0xba1cb, 0xba1dc, 0xba38b, 0xba39c, 0xba54b,
+ 0xba55c, 0xba70b, 0xba71c, 0xba8cb, 0xba8dc, 0xbaa8b,
+ 0xbaa9c, 0xbac4b, 0xbac5c, 0xbae0b, 0xbae1c, 0xbafcb,
+ 0xbafdc, 0xbb18b, 0xbb19c, 0xbb34b, 0xbb35c, 0xbb50b,
+ 0xbb51c, 0xbb6cb, 0xbb6dc, 0xbb88b, 0xbb89c, 0xbba4b,
+ 0xbba5c, 0xbbc0b, 0xbbc1c, 0xbbdcb, 0xbbddc, 0xbbf8b,
+ 0xbbf9c, 0xbc14b, 0xbc15c, 0xbc30b, 0xbc31c, 0xbc4cb,
+ 0xbc4dc, 0xbc68b, 0xbc69c, 0xbc84b, 0xbc85c, 0xbca0b,
+ 0xbca1c, 0xbcbcb, 0xbcbdc, 0xbcd8b, 0xbcd9c, 0xbcf4b,
+ 0xbcf5c, 0xbd10b, 0xbd11c, 0xbd2cb, 0xbd2dc, 0xbd48b,
+ 0xbd49c, 0xbd64b, 0xbd65c, 0xbd80b, 0xbd81c, 0xbd9cb,
+ 0xbd9dc, 0xbdb8b, 0xbdb9c, 0xbdd4b, 0xbdd5c, 0xbdf0b,
+ 0xbdf1c, 0xbe0cb, 0xbe0dc, 0xbe28b, 0xbe29c, 0xbe44b,
+ 0xbe45c, 0xbe60b, 0xbe61c, 0xbe7cb, 0xbe7dc, 0xbe98b,
+ 0xbe99c, 0xbeb4b, 0xbeb5c, 0xbed0b, 0xbed1c, 0xbeecb,
+ 0xbeedc, 0xbf08b, 0xbf09c, 0xbf24b, 0xbf25c, 0xbf40b,
+ 0xbf41c, 0xbf5cb, 0xbf5dc, 0xbf78b, 0xbf79c, 0xbf94b,
+ 0xbf95c, 0xbfb0b, 0xbfb1c, 0xbfccb, 0xbfcdc, 0xbfe8b,
+ 0xbfe9c, 0xc004b, 0xc005c, 0xc020b, 0xc021c, 0xc03cb,
+ 0xc03dc, 0xc058b, 0xc059c, 0xc074b, 0xc075c, 0xc090b,
+ 0xc091c, 0xc0acb, 0xc0adc, 0xc0c8b, 0xc0c9c, 0xc0e4b,
+ 0xc0e5c, 0xc100b, 0xc101c, 0xc11cb, 0xc11dc, 0xc138b,
+ 0xc139c, 0xc154b, 0xc155c, 0xc170b, 0xc171c, 0xc18cb,
+ 0xc18dc, 0xc1a8b, 0xc1a9c, 0xc1c4b, 0xc1c5c, 0xc1e0b,
+ 0xc1e1c, 0xc1fcb, 0xc1fdc, 0xc218b, 0xc219c, 0xc234b,
+ 0xc235c, 0xc250b, 0xc251c, 0xc26cb, 0xc26dc, 0xc288b,
+ 0xc289c, 0xc2a4b, 0xc2a5c, 0xc2c0b, 0xc2c1c, 0xc2dcb,
+ 0xc2ddc, 0xc2f8b, 0xc2f9c, 0xc314b, 0xc315c, 0xc330b,
+ 0xc331c, 0xc34cb, 0xc34dc, 0xc368b, 0xc369c, 0xc384b,
+ 0xc385c, 0xc3a0b, 0xc3a1c, 0xc3bcb, 0xc3bdc, 0xc3d8b,
+ 0xc3d9c, 0xc3f4b, 0xc3f5c, 0xc410b, 0xc411c, 0xc42cb,
+ 0xc42dc, 0xc448b, 0xc449c, 0xc464b, 0xc465c, 0xc480b,
+ 0xc481c, 0xc49cb, 0xc49dc, 0xc4b8b, 0xc4b9c, 0xc4d4b,
+ 0xc4d5c, 0xc4f0b, 0xc4f1c, 0xc50cb, 0xc50dc, 0xc528b,
+ 0xc529c, 0xc544b, 0xc545c, 0xc560b, 0xc561c, 0xc57cb,
+ 0xc57dc, 0xc598b, 0xc599c, 0xc5b4b, 0xc5b5c, 0xc5d0b,
+ 0xc5d1c, 0xc5ecb, 0xc5edc, 0xc608b, 0xc609c, 0xc624b,
+ 0xc625c, 0xc640b, 0xc641c, 0xc65cb, 0xc65dc, 0xc678b,
+ 0xc679c, 0xc694b, 0xc695c, 0xc6b0b, 0xc6b1c, 0xc6ccb,
+ 0xc6cdc, 0xc6e8b, 0xc6e9c, 0xc704b, 0xc705c, 0xc720b,
+ 0xc721c, 0xc73cb, 0xc73dc, 0xc758b, 0xc759c, 0xc774b,
+ 0xc775c, 0xc790b, 0xc791c, 0xc7acb, 0xc7adc, 0xc7c8b,
+ 0xc7c9c, 0xc7e4b, 0xc7e5c, 0xc800b, 0xc801c, 0xc81cb,
+ 0xc81dc, 0xc838b, 0xc839c, 0xc854b, 0xc855c, 0xc870b,
+ 0xc871c, 0xc88cb, 0xc88dc, 0xc8a8b, 0xc8a9c, 0xc8c4b,
+ 0xc8c5c, 0xc8e0b, 0xc8e1c, 0xc8fcb, 0xc8fdc, 0xc918b,
+ 0xc919c, 0xc934b, 0xc935c, 0xc950b, 0xc951c, 0xc96cb,
+ 0xc96dc, 0xc988b, 0xc989c, 0xc9a4b, 0xc9a5c, 0xc9c0b,
+ 0xc9c1c, 0xc9dcb, 0xc9ddc, 0xc9f8b, 0xc9f9c, 0xca14b,
+ 0xca15c, 0xca30b, 0xca31c, 0xca4cb, 0xca4dc, 0xca68b,
+ 0xca69c, 0xca84b, 0xca85c, 0xcaa0b, 0xcaa1c, 0xcabcb,
+ 0xcabdc, 0xcad8b, 0xcad9c, 0xcaf4b, 0xcaf5c, 0xcb10b,
+ 0xcb11c, 0xcb2cb, 0xcb2dc, 0xcb48b, 0xcb49c, 0xcb64b,
+ 0xcb65c, 0xcb80b, 0xcb81c, 0xcb9cb, 0xcb9dc, 0xcbb8b,
+ 0xcbb9c, 0xcbd4b, 0xcbd5c, 0xcbf0b, 0xcbf1c, 0xcc0cb,
+ 0xcc0dc, 0xcc28b, 0xcc29c, 0xcc44b, 0xcc45c, 0xcc60b,
+ 0xcc61c, 0xcc7cb, 0xcc7dc, 0xcc98b, 0xcc99c, 0xccb4b,
+ 0xccb5c, 0xccd0b, 0xccd1c, 0xccecb, 0xccedc, 0xcd08b,
+ 0xcd09c, 0xcd24b, 0xcd25c, 0xcd40b, 0xcd41c, 0xcd5cb,
+ 0xcd5dc, 0xcd78b, 0xcd79c, 0xcd94b, 0xcd95c, 0xcdb0b,
+ 0xcdb1c, 0xcdccb, 0xcdcdc, 0xcde8b, 0xcde9c, 0xce04b,
+ 0xce05c, 0xce20b, 0xce21c, 0xce3cb, 0xce3dc, 0xce58b,
+ 0xce59c, 0xce74b, 0xce75c, 0xce90b, 0xce91c, 0xceacb,
+ 0xceadc, 0xcec8b, 0xcec9c, 0xcee4b, 0xcee5c, 0xcf00b,
+ 0xcf01c, 0xcf1cb, 0xcf1dc, 0xcf38b, 0xcf39c, 0xcf54b,
+ 0xcf55c, 0xcf70b, 0xcf71c, 0xcf8cb, 0xcf8dc, 0xcfa8b,
+ 0xcfa9c, 0xcfc4b, 0xcfc5c, 0xcfe0b, 0xcfe1c, 0xcffcb,
+ 0xcffdc, 0xd018b, 0xd019c, 0xd034b, 0xd035c, 0xd050b,
+ 0xd051c, 0xd06cb, 0xd06dc, 0xd088b, 0xd089c, 0xd0a4b,
+ 0xd0a5c, 0xd0c0b, 0xd0c1c, 0xd0dcb, 0xd0ddc, 0xd0f8b,
+ 0xd0f9c, 0xd114b, 0xd115c, 0xd130b, 0xd131c, 0xd14cb,
+ 0xd14dc, 0xd168b, 0xd169c, 0xd184b, 0xd185c, 0xd1a0b,
+ 0xd1a1c, 0xd1bcb, 0xd1bdc, 0xd1d8b, 0xd1d9c, 0xd1f4b,
+ 0xd1f5c, 0xd210b, 0xd211c, 0xd22cb, 0xd22dc, 0xd248b,
+ 0xd249c, 0xd264b, 0xd265c, 0xd280b, 0xd281c, 0xd29cb,
+ 0xd29dc, 0xd2b8b, 0xd2b9c, 0xd2d4b, 0xd2d5c, 0xd2f0b,
+ 0xd2f1c, 0xd30cb, 0xd30dc, 0xd328b, 0xd329c, 0xd344b,
+ 0xd345c, 0xd360b, 0xd361c, 0xd37cb, 0xd37dc, 0xd398b,
+ 0xd399c, 0xd3b4b, 0xd3b5c, 0xd3d0b, 0xd3d1c, 0xd3ecb,
+ 0xd3edc, 0xd408b, 0xd409c, 0xd424b, 0xd425c, 0xd440b,
+ 0xd441c, 0xd45cb, 0xd45dc, 0xd478b, 0xd479c, 0xd494b,
+ 0xd495c, 0xd4b0b, 0xd4b1c, 0xd4ccb, 0xd4cdc, 0xd4e8b,
+ 0xd4e9c, 0xd504b, 0xd505c, 0xd520b, 0xd521c, 0xd53cb,
+ 0xd53dc, 0xd558b, 0xd559c, 0xd574b, 0xd575c, 0xd590b,
+ 0xd591c, 0xd5acb, 0xd5adc, 0xd5c8b, 0xd5c9c, 0xd5e4b,
+ 0xd5e5c, 0xd600b, 0xd601c, 0xd61cb, 0xd61dc, 0xd638b,
+ 0xd639c, 0xd654b, 0xd655c, 0xd670b, 0xd671c, 0xd68cb,
+ 0xd68dc, 0xd6a8b, 0xd6a9c, 0xd6c4b, 0xd6c5c, 0xd6e0b,
+ 0xd6e1c, 0xd6fcb, 0xd6fdc, 0xd718b, 0xd719c, 0xd734b,
+ 0xd735c, 0xd750b, 0xd751c, 0xd76cb, 0xd76dc, 0xd788b,
+ 0xd789c, 0xd7a40, 0xd7b08, 0xd7c70, 0xd7cb9, 0xd7fc0,
+ 0xfb1e4, 0xfb1f0, 0xfe004, 0xfe100, 0xfe204, 0xfe300,
+ 0xfeff1, 0xff000, 0xff9e4, 0xffa00, 0xfff01, 0xfffc0,
+ 0x101fd4, 0x101fe0, 0x102e04, 0x102e10, 0x103764, 0x1037b0,
+ 0x10a014, 0x10a040, 0x10a054, 0x10a070, 0x10a0c4, 0x10a100,
+ 0x10a384, 0x10a3b0, 0x10a3f4, 0x10a400, 0x10ae54, 0x10ae70,
+ 0x10d244, 0x10d280, 0x10d694, 0x10d6e0, 0x10eab4, 0x10ead0,
+ 0x10efa4, 0x10f000, 0x10f464, 0x10f510, 0x10f824, 0x10f860,
+ 0x110006, 0x110014, 0x110026, 0x110030, 0x110384, 0x110470,
+ 0x110704, 0x110710, 0x110734, 0x110750, 0x1107f4, 0x110826,
+ 0x110830, 0x110b06, 0x110b34, 0x110b76, 0x110b94, 0x110bb0,
+ 0x110bd5, 0x110be0, 0x110c24, 0x110c30, 0x110cd5, 0x110ce0,
+ 0x111004, 0x111030, 0x111274, 0x1112c6, 0x1112d4, 0x111350,
+ 0x111456, 0x111470, 0x111734, 0x111740, 0x111804, 0x111826,
+ 0x111830, 0x111b36, 0x111b64, 0x111bf6, 0x111c04, 0x111c10,
+ 0x111c25, 0x111c40, 0x111c94, 0x111cd0, 0x111ce6, 0x111cf4,
+ 0x111d00, 0x1122c6, 0x1122f4, 0x112326, 0x112344, 0x112380,
+ 0x1123e4, 0x1123f0, 0x112414, 0x112420, 0x112df4, 0x112e06,
+ 0x112e34, 0x112eb0, 0x113004, 0x113026, 0x113040, 0x1133b4,
+ 0x1133d0, 0x1133e4, 0x1133f6, 0x113404, 0x113416, 0x113450,
+ 0x113476, 0x113490, 0x1134b6, 0x1134d4, 0x1134e0, 0x113574,
+ 0x113580, 0x113626, 0x113640, 0x113664, 0x1136d0, 0x113704,
+ 0x113750, 0x113b84, 0x113b96, 0x113bb4, 0x113c10, 0x113c24,
+ 0x113c30, 0x113c54, 0x113c60, 0x113c74, 0x113ca6, 0x113cb0,
+ 0x113cc6, 0x113ce4, 0x113d15, 0x113d24, 0x113d30, 0x113e14,
+ 0x113e30, 0x114356, 0x114384, 0x114406, 0x114424, 0x114456,
+ 0x114464, 0x114470, 0x1145e4, 0x1145f0, 0x114b04, 0x114b16,
+ 0x114b34, 0x114b96, 0x114ba4, 0x114bb6, 0x114bd4, 0x114be6,
+ 0x114bf4, 0x114c16, 0x114c24, 0x114c40, 0x115af4, 0x115b06,
+ 0x115b24, 0x115b60, 0x115b86, 0x115bc4, 0x115be6, 0x115bf4,
+ 0x115c10, 0x115dc4, 0x115de0, 0x116306, 0x116334, 0x1163b6,
+ 0x1163d4, 0x1163e6, 0x1163f4, 0x116410, 0x116ab4, 0x116ac6,
+ 0x116ad4, 0x116ae6, 0x116b04, 0x116b80, 0x1171d4, 0x1171e6,
+ 0x1171f4, 0x117200, 0x117224, 0x117266, 0x117274, 0x1172c0,
+ 0x1182c6, 0x1182f4, 0x118386, 0x118394, 0x1183b0, 0x119304,
+ 0x119316, 0x119360, 0x119376, 0x119390, 0x1193b4, 0x1193f5,
+ 0x119406, 0x119415, 0x119426, 0x119434, 0x119440, 0x119d16,
+ 0x119d44, 0x119d80, 0x119da4, 0x119dc6, 0x119e04, 0x119e10,
+ 0x119e46, 0x119e50, 0x11a014, 0x11a0b0, 0x11a334, 0x11a396,
+ 0x11a3a0, 0x11a3b4, 0x11a3f0, 0x11a474, 0x11a480, 0x11a514,
+ 0x11a576, 0x11a594, 0x11a5c0, 0x11a845, 0x11a8a4, 0x11a976,
+ 0x11a984, 0x11a9a0, 0x11b604, 0x11b616, 0x11b624, 0x11b656,
+ 0x11b664, 0x11b676, 0x11b680, 0x11c2f6, 0x11c304, 0x11c370,
+ 0x11c384, 0x11c3e6, 0x11c3f4, 0x11c400, 0x11c924, 0x11ca80,
+ 0x11ca96, 0x11caa4, 0x11cb16, 0x11cb24, 0x11cb46, 0x11cb54,
+ 0x11cb70, 0x11d314, 0x11d370, 0x11d3a4, 0x11d3b0, 0x11d3c4,
+ 0x11d3e0, 0x11d3f4, 0x11d465, 0x11d474, 0x11d480, 0x11d8a6,
+ 0x11d8f0, 0x11d904, 0x11d920, 0x11d936, 0x11d954, 0x11d966,
+ 0x11d974, 0x11d980, 0x11ef34, 0x11ef56, 0x11ef70, 0x11f004,
+ 0x11f025, 0x11f036, 0x11f040, 0x11f346, 0x11f364, 0x11f3b0,
+ 0x11f3e6, 0x11f404, 0x11f430, 0x11f5a4, 0x11f5b0, 0x134301,
+ 0x134404, 0x134410, 0x134474, 0x134560, 0x1611e4, 0x1612a6,
+ 0x1612d4, 0x161300, 0x16af04, 0x16af50, 0x16b304, 0x16b370,
+ 0x16d638, 0x16d640, 0x16d678, 0x16d6b0, 0x16f4f4, 0x16f500,
+ 0x16f516, 0x16f880, 0x16f8f4, 0x16f930, 0x16fe44, 0x16fe50,
+ 0x16ff04, 0x16ff20, 0x1bc9d4, 0x1bc9f0, 0x1bca01, 0x1bca40,
+ 0x1cf004, 0x1cf2e0, 0x1cf304, 0x1cf470, 0x1d1654, 0x1d16a0,
+ 0x1d16d4, 0x1d1731, 0x1d17b4, 0x1d1830, 0x1d1854, 0x1d18c0,
+ 0x1d1aa4, 0x1d1ae0, 0x1d2424, 0x1d2450, 0x1da004, 0x1da370,
+ 0x1da3b4, 0x1da6d0, 0x1da754, 0x1da760, 0x1da844, 0x1da850,
+ 0x1da9b4, 0x1daa00, 0x1daa14, 0x1dab00, 0x1e0004, 0x1e0070,
+ 0x1e0084, 0x1e0190, 0x1e01b4, 0x1e0220, 0x1e0234, 0x1e0250,
+ 0x1e0264, 0x1e02b0, 0x1e08f4, 0x1e0900, 0x1e1304, 0x1e1370,
+ 0x1e2ae4, 0x1e2af0, 0x1e2ec4, 0x1e2f00, 0x1e4ec4, 0x1e4f00,
+ 0x1e5ee4, 0x1e5f00, 0x1e6e34, 0x1e6e40, 0x1e6e64, 0x1e6e70,
+ 0x1e6ee4, 0x1e6f00, 0x1e6f54, 0x1e6f60, 0x1e8d04, 0x1e8d70,
+ 0x1e9444, 0x1e94b0, 0x1f1e6d, 0x1f2000, 0x1f3fb4, 0x1f4000,
+ 0xe00001, 0xe00204, 0xe00801, 0xe01004, 0xe01f01, 0xe10000,
};
inline constexpr char32_t __incb_linkers[] = {
- 0x094d, 0x09cd, 0x0acd, 0x0b4d, 0x0c4d, 0x0d4d,
+ 0x094d, 0x09cd, 0x0acd, 0x0b4d, 0x0c4d, 0x0d4d, 0x1039, 0x17d2, 0x1a60, 0x1b44, 0x1bab, 0xa9c0, 0xaaf6, 0x10a3f, 0x11133, 0x113d0, 0x1193e, 0x11a47, 0x11a99, 0x11f42,
};
enum class _InCB { _Consonant = 1, _Extend = 2 };
@@ -681,94 +685,109 @@
0x3cd6, 0x3cd8, 0x3cde, 0x3ce0, 0x3ce6, 0x3ce8,
0x3dc6, 0x3dfc, 0x3e02, 0x3e14, 0x3e1a, 0x3e20,
0x3e36, 0x3e60, 0x3e66, 0x3ef4, 0x3f1a, 0x3f1c,
- 0x40b6, 0x40c4, 0x40ca, 0x40e0, 0x40e6, 0x40ec,
- 0x40f6, 0x40fc, 0x4162, 0x4168, 0x417a, 0x4184,
- 0x41c6, 0x41d4, 0x420a, 0x420c, 0x4216, 0x421c,
- 0x4236, 0x4238, 0x4276, 0x4278, 0x4d76, 0x4d80,
- 0x5c4a, 0x5c58, 0x5cca, 0x5cd4, 0x5d4a, 0x5d50,
- 0x5dca, 0x5dd0, 0x5ed2, 0x5ed8, 0x5ede, 0x5ef8,
- 0x5f1a, 0x5f1c, 0x5f26, 0x5f50, 0x5f76, 0x5f78,
- 0x602e, 0x6038, 0x603e, 0x6040, 0x6216, 0x621c,
- 0x62a6, 0x62a8, 0x6482, 0x648c, 0x649e, 0x64a4,
- 0x64ca, 0x64cc, 0x64e6, 0x64f0, 0x685e, 0x6864,
- 0x686e, 0x6870, 0x695a, 0x695c, 0x6962, 0x697c,
- 0x6982, 0x6984, 0x698a, 0x698c, 0x6996, 0x69b4,
- 0x69ce, 0x69f4, 0x69fe, 0x6a00, 0x6ac2, 0x6b3c,
- 0x6c02, 0x6c10, 0x6cd2, 0x6cf8, 0x6d0a, 0x6d14,
- 0x6dae, 0x6dd0, 0x6e02, 0x6e08, 0x6e8a, 0x6e98,
- 0x6ea2, 0x6eb8, 0x6f9a, 0x6f9c, 0x6fa2, 0x6fa8,
- 0x6fb6, 0x6fb8, 0x6fbe, 0x6fd0, 0x70b2, 0x70d0,
- 0x70da, 0x70e0, 0x7342, 0x734c, 0x7352, 0x7384,
- 0x738a, 0x73a4, 0x73b6, 0x73b8, 0x73d2, 0x73d4,
- 0x73e2, 0x73e8, 0x7702, 0x7800, 0x8036, 0x8038,
- 0x8342, 0x83c4, 0xb3be, 0xb3c8, 0xb5fe, 0xb600,
- 0xb782, 0xb800, 0xc0aa, 0xc0c0, 0xc266, 0xc26c,
- 0x299be, 0x299cc, 0x299d2, 0x299f8, 0x29a7a, 0x29a80,
- 0x29bc2, 0x29bc8, 0x2a00a, 0x2a00c, 0x2a01a, 0x2a01c,
- 0x2a02e, 0x2a030, 0x2a096, 0x2a09c, 0x2a0b2, 0x2a0b4,
- 0x2a312, 0x2a318, 0x2a382, 0x2a3c8, 0x2a3fe, 0x2a400,
- 0x2a49a, 0x2a4b8, 0x2a51e, 0x2a548, 0x2a54e, 0x2a550,
- 0x2a602, 0x2a60c, 0x2a6ce, 0x2a6d0, 0x2a6da, 0x2a6e8,
- 0x2a6f2, 0x2a6f8, 0x2a702, 0x2a704, 0x2a796, 0x2a798,
- 0x2a8a6, 0x2a8bc, 0x2a8c6, 0x2a8cc, 0x2a8d6, 0x2a8dc,
- 0x2a90e, 0x2a910, 0x2a932, 0x2a934, 0x2a9f2, 0x2a9f4,
- 0x2aac2, 0x2aac4, 0x2aaca, 0x2aad4, 0x2aade, 0x2aae4,
- 0x2aafa, 0x2ab00, 0x2ab06, 0x2ab08, 0x2abb2, 0x2abb8,
- 0x2abda, 0x2abdc, 0x2af96, 0x2af98, 0x2afa2, 0x2afa4,
- 0x2afb6, 0x2afb8, 0x3ec7a, 0x3ec7c, 0x3f802, 0x3f840,
- 0x3f882, 0x3f8c0, 0x3fe7a, 0x3fe80, 0x407f6, 0x407f8,
- 0x40b82, 0x40b84, 0x40dda, 0x40dec, 0x42806, 0x42810,
- 0x42816, 0x4281c, 0x42832, 0x42840, 0x428e2, 0x428ec,
- 0x428fe, 0x42900, 0x42b96, 0x42b9c, 0x43492, 0x434a0,
- 0x435a6, 0x435b8, 0x43aae, 0x43ab4, 0x43bf2, 0x43c00,
- 0x43d1a, 0x43d44, 0x43e0a, 0x43e18, 0x44006, 0x44008,
- 0x440e2, 0x4411c, 0x441c2, 0x441c4, 0x441ce, 0x441d4,
- 0x441fe, 0x44208, 0x442ce, 0x442dc, 0x442e6, 0x442ec,
- 0x4430a, 0x4430c, 0x44402, 0x4440c, 0x4449e, 0x444b0,
- 0x444b6, 0x444d4, 0x445ce, 0x445d0, 0x44602, 0x44608,
- 0x446da, 0x446fc, 0x44702, 0x44704, 0x44726, 0x44734,
- 0x4473e, 0x44740, 0x448be, 0x448c8, 0x448d2, 0x448e0,
- 0x448fa, 0x448fc, 0x44906, 0x44908, 0x44b7e, 0x44b80,
- 0x44b8e, 0x44bac, 0x44c02, 0x44c08, 0x44cee, 0x44cf4,
- 0x44cfa, 0x44cfc, 0x44d02, 0x44d04, 0x44d36, 0x44d38,
- 0x44d5e, 0x44d60, 0x44d9a, 0x44db4, 0x44dc2, 0x44dd4,
- 0x44ee2, 0x44ee4, 0x44eee, 0x44f04, 0x44f0a, 0x44f0c,
- 0x44f16, 0x44f18, 0x44f1e, 0x44f28, 0x44f3a, 0x44f44,
- 0x44f4a, 0x44f4c, 0x44f86, 0x44f8c, 0x450e2, 0x45100,
- 0x4510a, 0x45114, 0x4511a, 0x4511c, 0x4517a, 0x4517c,
- 0x452c2, 0x452c4, 0x452ce, 0x452e4, 0x452ea, 0x452ec,
- 0x452f6, 0x452f8, 0x452fe, 0x45304, 0x4530a, 0x45310,
- 0x456be, 0x456c0, 0x456ca, 0x456d8, 0x456f2, 0x456f8,
- 0x456fe, 0x45704, 0x45772, 0x45778, 0x458ce, 0x458ec,
- 0x458f6, 0x458f8, 0x458fe, 0x45904, 0x45aae, 0x45ab0,
- 0x45ab6, 0x45ab8, 0x45ac2, 0x45ae0, 0x45c76, 0x45c78,
- 0x45c7e, 0x45c80, 0x45c8a, 0x45c98, 0x45c9e, 0x45cb0,
- 0x460be, 0x460e0, 0x460e6, 0x460ec, 0x464c2, 0x464c4,
- 0x464ee, 0x464fc, 0x4650e, 0x46510, 0x46752, 0x46760,
- 0x4676a, 0x46770, 0x46782, 0x46784, 0x46806, 0x4682c,
- 0x468ce, 0x468e4, 0x468ee, 0x468fc, 0x4691e, 0x46920,
- 0x46946, 0x4695c, 0x46966, 0x46970, 0x46a2a, 0x46a5c,
- 0x46a62, 0x46a68, 0x470c2, 0x470dc, 0x470e2, 0x470f8,
- 0x470fe, 0x47100, 0x4724a, 0x472a0, 0x472aa, 0x472c4,
- 0x472ca, 0x472d0, 0x472d6, 0x472dc, 0x474c6, 0x474dc,
- 0x474ea, 0x474ec, 0x474f2, 0x474f8, 0x474fe, 0x47518,
- 0x4751e, 0x47520, 0x47642, 0x47648, 0x47656, 0x47658,
- 0x4765e, 0x47660, 0x47bce, 0x47bd4, 0x47c02, 0x47c08,
- 0x47cda, 0x47cec, 0x47d02, 0x47d0c, 0x47d6a, 0x47d6c,
- 0x4d102, 0x4d104, 0x4d11e, 0x4d158, 0x5847a, 0x584a8,
- 0x584b6, 0x584c0, 0x5abc2, 0x5abd4, 0x5acc2, 0x5acdc,
- 0x5bd3e, 0x5bd40, 0x5be3e, 0x5be4c, 0x5bf92, 0x5bf94,
- 0x5bfc2, 0x5bfc8, 0x6f276, 0x6f27c, 0x73c02, 0x73cb8,
- 0x73cc2, 0x73d1c, 0x74596, 0x745a8, 0x745b6, 0x745cc,
- 0x745ee, 0x7460c, 0x74616, 0x74630, 0x746aa, 0x746b8,
- 0x7490a, 0x74914, 0x76802, 0x768dc, 0x768ee, 0x769b4,
- 0x769d6, 0x769d8, 0x76a12, 0x76a14, 0x76a6e, 0x76a80,
- 0x76a86, 0x76ac0, 0x78002, 0x7801c, 0x78022, 0x78064,
- 0x7806e, 0x78088, 0x7808e, 0x78094, 0x7809a, 0x780ac,
- 0x7823e, 0x78240, 0x784c2, 0x784dc, 0x78aba, 0x78abc,
- 0x78bb2, 0x78bc0, 0x793b2, 0x793c0, 0x797ba, 0x797c0,
- 0x7a342, 0x7a35c, 0x7a512, 0x7a52c, 0x7cfee, 0x7d000,
- 0x380082, 0x380200, 0x380402, 0x3807c0,
+ 0x4001, 0x40ac, 0x40b6, 0x40c4, 0x40ca, 0x40e0,
+ 0x40ea, 0x40ec, 0x40f6, 0x40fd, 0x4100, 0x4141,
+ 0x4158, 0x4162, 0x4169, 0x417a, 0x4185, 0x4188,
+ 0x4195, 0x419c, 0x41b9, 0x41c6, 0x41d5, 0x420a,
+ 0x420c, 0x4216, 0x421c, 0x4236, 0x4239, 0x423c,
+ 0x4276, 0x4278, 0x4d76, 0x4d80, 0x5c4a, 0x5c58,
+ 0x5cca, 0x5cd4, 0x5d4a, 0x5d50, 0x5dca, 0x5dd0,
+ 0x5e01, 0x5ed2, 0x5ed8, 0x5ede, 0x5ef8, 0x5f1a,
+ 0x5f1c, 0x5f26, 0x5f48, 0x5f4e, 0x5f50, 0x5f76,
+ 0x5f78, 0x602e, 0x6038, 0x603e, 0x6040, 0x6216,
+ 0x621c, 0x62a6, 0x62a8, 0x6482, 0x648c, 0x649e,
+ 0x64a4, 0x64ca, 0x64cc, 0x64e6, 0x64f0, 0x685e,
+ 0x6864, 0x686e, 0x6870, 0x6881, 0x6954, 0x695a,
+ 0x695c, 0x6962, 0x697c, 0x698a, 0x698c, 0x6996,
+ 0x69b4, 0x69ce, 0x69f4, 0x69fe, 0x6a00, 0x6ac2,
+ 0x6b78, 0x6b82, 0x6bb0, 0x6c02, 0x6c10, 0x6c2d,
+ 0x6c34, 0x6c4d, 0x6cd2, 0x6cf8, 0x6d0a, 0x6d10,
+ 0x6d15, 0x6d34, 0x6dae, 0x6dd0, 0x6e02, 0x6e08,
+ 0x6e0d, 0x6e84, 0x6e8a, 0x6e98, 0x6ea2, 0x6eac,
+ 0x6eb2, 0x6eb9, 0x6ec0, 0x6eed, 0x6ef8, 0x6f9a,
+ 0x6f9c, 0x6fa2, 0x6fa8, 0x6fb6, 0x6fb8, 0x6fbe,
+ 0x6fd0, 0x70b2, 0x70d0, 0x70da, 0x70e0, 0x7342,
+ 0x734c, 0x7352, 0x7384, 0x738a, 0x73a4, 0x73b6,
+ 0x73b8, 0x73d2, 0x73d4, 0x73e2, 0x73e8, 0x7702,
+ 0x7800, 0x8036, 0x8038, 0x8342, 0x83c4, 0xb3be,
+ 0xb3c8, 0xb5fe, 0xb600, 0xb782, 0xb800, 0xc0aa,
+ 0xc0c0, 0xc266, 0xc26c, 0x299be, 0x299cc, 0x299d2,
+ 0x299f8, 0x29a7a, 0x29a80, 0x29bc2, 0x29bc8, 0x2a00a,
+ 0x2a00c, 0x2a01a, 0x2a01c, 0x2a02e, 0x2a030, 0x2a096,
+ 0x2a09c, 0x2a0b2, 0x2a0b4, 0x2a312, 0x2a318, 0x2a382,
+ 0x2a3c8, 0x2a3fe, 0x2a400, 0x2a49a, 0x2a4b8, 0x2a51e,
+ 0x2a548, 0x2a54e, 0x2a550, 0x2a602, 0x2a60c, 0x2a625,
+ 0x2a630, 0x2a63d, 0x2a6ce, 0x2a6d0, 0x2a6da, 0x2a6e8,
+ 0x2a6f2, 0x2a6f8, 0x2a781, 0x2a796, 0x2a798, 0x2a79d,
+ 0x2a7c0, 0x2a7e9, 0x2a7fc, 0x2a8a6, 0x2a8bc, 0x2a8c6,
+ 0x2a8cc, 0x2a8d6, 0x2a8dc, 0x2a90e, 0x2a910, 0x2a932,
+ 0x2a934, 0x2a981, 0x2a9c0, 0x2a9c5, 0x2a9d0, 0x2a9e9,
+ 0x2a9ec, 0x2a9f2, 0x2a9f4, 0x2a9f9, 0x2aa00, 0x2aac2,
+ 0x2aac4, 0x2aaca, 0x2aad4, 0x2aade, 0x2aae4, 0x2aafa,
+ 0x2ab00, 0x2ab06, 0x2ab08, 0x2ab81, 0x2abac, 0x2abb2,
+ 0x2abb8, 0x2af01, 0x2af6c, 0x2af96, 0x2af98, 0x2afa2,
+ 0x2afa4, 0x2afb6, 0x2afb8, 0x3ec7a, 0x3ec7c, 0x3f802,
+ 0x3f840, 0x3f882, 0x3f8c0, 0x3fe7a, 0x3fe80, 0x407f6,
+ 0x407f8, 0x40b82, 0x40b84, 0x40dda, 0x40dec, 0x42801,
+ 0x42806, 0x42810, 0x42816, 0x4281c, 0x42832, 0x42841,
+ 0x42850, 0x42855, 0x42860, 0x42865, 0x428d8, 0x428e2,
+ 0x428ec, 0x42b96, 0x42b9c, 0x43492, 0x434a0, 0x435a6,
+ 0x435b8, 0x43aae, 0x43ab4, 0x43bea, 0x43c00, 0x43d1a,
+ 0x43d44, 0x43e0a, 0x43e18, 0x44006, 0x44008, 0x440e2,
+ 0x4411c, 0x441c2, 0x441c4, 0x441ce, 0x441d4, 0x441fe,
+ 0x44208, 0x442ce, 0x442dc, 0x442e6, 0x442ec, 0x4430a,
+ 0x4430c, 0x44402, 0x4440d, 0x4449e, 0x444b0, 0x444b6,
+ 0x444cc, 0x444d2, 0x444d4, 0x44511, 0x44514, 0x4451d,
+ 0x44520, 0x445ce, 0x445d0, 0x44602, 0x44608, 0x446da,
+ 0x446fc, 0x44702, 0x44704, 0x44726, 0x44734, 0x4473e,
+ 0x44740, 0x448be, 0x448c8, 0x448d2, 0x448e0, 0x448fa,
+ 0x448fc, 0x44906, 0x44908, 0x44b7e, 0x44b80, 0x44b8e,
+ 0x44bac, 0x44c02, 0x44c08, 0x44cee, 0x44cf4, 0x44cfa,
+ 0x44cfc, 0x44d02, 0x44d04, 0x44d36, 0x44d38, 0x44d5e,
+ 0x44d60, 0x44d9a, 0x44db4, 0x44dc2, 0x44dd4, 0x44e01,
+ 0x44e28, 0x44e2d, 0x44e30, 0x44e39, 0x44e3c, 0x44e41,
+ 0x44ed8, 0x44ee2, 0x44ee4, 0x44eee, 0x44f04, 0x44f0a,
+ 0x44f0c, 0x44f16, 0x44f18, 0x44f1e, 0x44f28, 0x44f3a,
+ 0x44f40, 0x44f4a, 0x44f4c, 0x44f86, 0x44f8c, 0x450e2,
+ 0x45100, 0x4510a, 0x45114, 0x4511a, 0x4511c, 0x4517a,
+ 0x4517c, 0x452c2, 0x452c4, 0x452ce, 0x452e4, 0x452ea,
+ 0x452ec, 0x452f6, 0x452f8, 0x452fe, 0x45304, 0x4530a,
+ 0x45310, 0x456be, 0x456c0, 0x456ca, 0x456d8, 0x456f2,
+ 0x456f8, 0x456fe, 0x45704, 0x45772, 0x45778, 0x458ce,
+ 0x458ec, 0x458f6, 0x458f8, 0x458fe, 0x45904, 0x45aae,
+ 0x45ab0, 0x45ab6, 0x45ab8, 0x45ac2, 0x45ae0, 0x45c76,
+ 0x45c78, 0x45c7e, 0x45c80, 0x45c8a, 0x45c98, 0x45c9e,
+ 0x45cb0, 0x460be, 0x460e0, 0x460e6, 0x460ec, 0x46401,
+ 0x4641c, 0x46425, 0x46428, 0x46431, 0x46450, 0x46455,
+ 0x4645c, 0x46461, 0x464c2, 0x464c4, 0x464ee, 0x464f8,
+ 0x4650e, 0x46510, 0x46752, 0x46760, 0x4676a, 0x46770,
+ 0x46782, 0x46784, 0x46801, 0x46806, 0x4682d, 0x468ce,
+ 0x468e4, 0x468ee, 0x468fc, 0x46941, 0x46946, 0x4695c,
+ 0x46966, 0x46971, 0x46a10, 0x46a2a, 0x46a5c, 0x46a62,
+ 0x46a64, 0x46d82, 0x46d84, 0x46d8a, 0x46d94, 0x46d9a,
+ 0x46d9c, 0x470c2, 0x470dc, 0x470e2, 0x470f8, 0x470fe,
+ 0x47100, 0x4724a, 0x472a0, 0x472aa, 0x472c4, 0x472ca,
+ 0x472d0, 0x472d6, 0x472dc, 0x474c6, 0x474dc, 0x474ea,
+ 0x474ec, 0x474f2, 0x474f8, 0x474fe, 0x47518, 0x4751e,
+ 0x47520, 0x47642, 0x47648, 0x47656, 0x47658, 0x4765e,
+ 0x47660, 0x47bce, 0x47bd4, 0x47c02, 0x47c08, 0x47c11,
+ 0x47c44, 0x47c49, 0x47cd0, 0x47cda, 0x47cec, 0x47d02,
+ 0x47d08, 0x47d6a, 0x47d6c, 0x4d102, 0x4d104, 0x4d11e,
+ 0x4d158, 0x5847a, 0x584a8, 0x584b6, 0x584c0, 0x5abc2,
+ 0x5abd4, 0x5acc2, 0x5acdc, 0x5bd3e, 0x5bd40, 0x5be3e,
+ 0x5be4c, 0x5bf92, 0x5bf94, 0x5bfc2, 0x5bfc8, 0x6f276,
+ 0x6f27c, 0x73c02, 0x73cb8, 0x73cc2, 0x73d1c, 0x74596,
+ 0x745a8, 0x745b6, 0x745cc, 0x745ee, 0x7460c, 0x74616,
+ 0x74630, 0x746aa, 0x746b8, 0x7490a, 0x74914, 0x76802,
+ 0x768dc, 0x768ee, 0x769b4, 0x769d6, 0x769d8, 0x76a12,
+ 0x76a14, 0x76a6e, 0x76a80, 0x76a86, 0x76ac0, 0x78002,
+ 0x7801c, 0x78022, 0x78064, 0x7806e, 0x78088, 0x7808e,
+ 0x78094, 0x7809a, 0x780ac, 0x7823e, 0x78240, 0x784c2,
+ 0x784dc, 0x78aba, 0x78abc, 0x78bb2, 0x78bc0, 0x793b2,
+ 0x793c0, 0x797ba, 0x797c0, 0x79b8e, 0x79b90, 0x79b9a,
+ 0x79b9c, 0x79bba, 0x79bc0, 0x79bd6, 0x79bd8, 0x7a342,
+ 0x7a35c, 0x7a512, 0x7a52c, 0x7cfee, 0x7d000, 0x380082,
+ 0x380200, 0x380402, 0x3807c0,
};
// Table generated by contrib/unicode/gen_libstdcxx_unicode_data.py,
@@ -776,24 +795,43 @@
inline constexpr char32_t __xpicto_edges[] = {
0xa9, 0xaa, 0xae, 0xaf, 0x203c, 0x203d, 0x2049, 0x204a,
0x2122, 0x2123, 0x2139, 0x213a, 0x2194, 0x219a, 0x21a9, 0x21ab,
- 0x231a, 0x231c, 0x2328, 0x2329, 0x2388, 0x2389, 0x23cf, 0x23d0,
- 0x23e9, 0x23f4, 0x23f8, 0x23fb, 0x24c2, 0x24c3, 0x25aa, 0x25ac,
- 0x25b6, 0x25b7, 0x25c0, 0x25c1, 0x25fb, 0x25ff, 0x2600, 0x2606,
- 0x2607, 0x2613, 0x2614, 0x2686, 0x2690, 0x2706, 0x2708, 0x2713,
- 0x2714, 0x2715, 0x2716, 0x2717, 0x271d, 0x271e, 0x2721, 0x2722,
- 0x2728, 0x2729, 0x2733, 0x2735, 0x2744, 0x2745, 0x2747, 0x2748,
- 0x274c, 0x274d, 0x274e, 0x274f, 0x2753, 0x2756, 0x2757, 0x2758,
- 0x2763, 0x2768, 0x2795, 0x2798, 0x27a1, 0x27a2, 0x27b0, 0x27b1,
- 0x27bf, 0x27c0, 0x2934, 0x2936, 0x2b05, 0x2b08, 0x2b1b, 0x2b1d,
- 0x2b50, 0x2b51, 0x2b55, 0x2b56, 0x3030, 0x3031, 0x303d, 0x303e,
- 0x3297, 0x3298, 0x3299, 0x329a, 0x1f000, 0x1f100, 0x1f10d, 0x1f110,
- 0x1f12f, 0x1f130, 0x1f16c, 0x1f172, 0x1f17e, 0x1f180, 0x1f18e, 0x1f18f,
- 0x1f191, 0x1f19b, 0x1f1ad, 0x1f1e6, 0x1f201, 0x1f210, 0x1f21a, 0x1f21b,
- 0x1f22f, 0x1f230, 0x1f232, 0x1f23b, 0x1f23c, 0x1f240, 0x1f249, 0x1f3fb,
- 0x1f400, 0x1f53e, 0x1f546, 0x1f650, 0x1f680, 0x1f700, 0x1f774, 0x1f780,
- 0x1f7d5, 0x1f800, 0x1f80c, 0x1f810, 0x1f848, 0x1f850, 0x1f85a, 0x1f860,
- 0x1f888, 0x1f890, 0x1f8ae, 0x1f900, 0x1f90c, 0x1f93b, 0x1f93c, 0x1f946,
- 0x1f947, 0x1fb00, 0x1fc00, 0x1fffe,
+ 0x231a, 0x231c, 0x2328, 0x2329, 0x23cf, 0x23d0, 0x23e9, 0x23f4,
+ 0x23f8, 0x23fb, 0x24c2, 0x24c3, 0x25aa, 0x25ac, 0x25b6, 0x25b7,
+ 0x25c0, 0x25c1, 0x25fb, 0x25ff, 0x2600, 0x2605, 0x260e, 0x260f,
+ 0x2611, 0x2612, 0x2614, 0x2616, 0x2618, 0x2619, 0x261d, 0x261e,
+ 0x2620, 0x2621, 0x2622, 0x2624, 0x2626, 0x2627, 0x262a, 0x262b,
+ 0x262e, 0x2630, 0x2638, 0x263b, 0x2640, 0x2641, 0x2642, 0x2643,
+ 0x2648, 0x2654, 0x265f, 0x2661, 0x2663, 0x2664, 0x2665, 0x2667,
+ 0x2668, 0x2669, 0x267b, 0x267c, 0x267e, 0x2680, 0x2692, 0x2698,
+ 0x2699, 0x269a, 0x269b, 0x269d, 0x26a0, 0x26a2, 0x26a7, 0x26a8,
+ 0x26aa, 0x26ac, 0x26b0, 0x26b2, 0x26bd, 0x26bf, 0x26c4, 0x26c6,
+ 0x26c8, 0x26c9, 0x26ce, 0x26d0, 0x26d1, 0x26d2, 0x26d3, 0x26d5,
+ 0x26e9, 0x26eb, 0x26f0, 0x26f6, 0x26f7, 0x26fb, 0x26fd, 0x26fe,
+ 0x2702, 0x2703, 0x2705, 0x2706, 0x2708, 0x270e, 0x270f, 0x2710,
+ 0x2712, 0x2713, 0x2714, 0x2715, 0x2716, 0x2717, 0x271d, 0x271e,
+ 0x2721, 0x2722, 0x2728, 0x2729, 0x2733, 0x2735, 0x2744, 0x2745,
+ 0x2747, 0x2748, 0x274c, 0x274d, 0x274e, 0x274f, 0x2753, 0x2756,
+ 0x2757, 0x2758, 0x2763, 0x2765, 0x2795, 0x2798, 0x27a1, 0x27a2,
+ 0x27b0, 0x27b1, 0x27bf, 0x27c0, 0x2934, 0x2936, 0x2b05, 0x2b08,
+ 0x2b1b, 0x2b1d, 0x2b50, 0x2b51, 0x2b55, 0x2b56, 0x3030, 0x3031,
+ 0x303d, 0x303e, 0x3297, 0x3298, 0x3299, 0x329a, 0x1f004, 0x1f005,
+ 0x1f02c, 0x1f030, 0x1f094, 0x1f0a0, 0x1f0af, 0x1f0b1, 0x1f0c0, 0x1f0c1,
+ 0x1f0cf, 0x1f0d1, 0x1f0f6, 0x1f100, 0x1f170, 0x1f172, 0x1f17e, 0x1f180,
+ 0x1f18e, 0x1f18f, 0x1f191, 0x1f19b, 0x1f1ae, 0x1f1e6, 0x1f201, 0x1f210,
+ 0x1f21a, 0x1f21b, 0x1f22f, 0x1f230, 0x1f232, 0x1f23b, 0x1f23c, 0x1f240,
+ 0x1f249, 0x1f260, 0x1f266, 0x1f322, 0x1f324, 0x1f394, 0x1f396, 0x1f398,
+ 0x1f399, 0x1f39c, 0x1f39e, 0x1f3f1, 0x1f3f3, 0x1f3f6, 0x1f3f7, 0x1f3fb,
+ 0x1f400, 0x1f4fe, 0x1f4ff, 0x1f53e, 0x1f549, 0x1f54f, 0x1f550, 0x1f568,
+ 0x1f56f, 0x1f571, 0x1f573, 0x1f57b, 0x1f587, 0x1f588, 0x1f58a, 0x1f58e,
+ 0x1f590, 0x1f591, 0x1f595, 0x1f597, 0x1f5a4, 0x1f5a6, 0x1f5a8, 0x1f5a9,
+ 0x1f5b1, 0x1f5b3, 0x1f5bc, 0x1f5bd, 0x1f5c2, 0x1f5c5, 0x1f5d1, 0x1f5d4,
+ 0x1f5dc, 0x1f5df, 0x1f5e1, 0x1f5e2, 0x1f5e3, 0x1f5e4, 0x1f5e8, 0x1f5e9,
+ 0x1f5ef, 0x1f5f0, 0x1f5f3, 0x1f5f4, 0x1f5fa, 0x1f650, 0x1f680, 0x1f6c6,
+ 0x1f6cb, 0x1f6d3, 0x1f6d5, 0x1f6e6, 0x1f6e9, 0x1f6ea, 0x1f6eb, 0x1f6f1,
+ 0x1f6f3, 0x1f700, 0x1f7da, 0x1f800, 0x1f80c, 0x1f810, 0x1f848, 0x1f850,
+ 0x1f85a, 0x1f860, 0x1f888, 0x1f890, 0x1f8ae, 0x1f8b0, 0x1f8bc, 0x1f8c0,
+ 0x1f8c2, 0x1f8d0, 0x1f8d9, 0x1f900, 0x1f90c, 0x1f93b, 0x1f93c, 0x1f946,
+ 0x1f947, 0x1fa00, 0x1fa58, 0x1fa60, 0x1fa6e, 0x1fb00, 0x1fc00, 0x1fffe,
};
#undef _GLIBCXX_GET_UNICODE_DATA
diff --git a/libstdc++-v3/include/bits/unicode.h b/libstdc++-v3/include/bits/unicode.h
index f1b6bf4..09f7c2d 100644
--- a/libstdc++-v3/include/bits/unicode.h
+++ b/libstdc++-v3/include/bits/unicode.h
@@ -61,7 +61,7 @@ namespace __unicode
__is_single_code_unit(char32_t __c)
{
if constexpr (__gnu_cxx::__int_traits<_CharT>::__max <= 0xFF)
- return __c < 0x7F; // ASCII character
+ return __c <= 0x7F; // ASCII character
else
return __c < __gnu_cxx::__int_traits<_CharT>::__max
&& __is_scalar_value(__c);
@@ -86,6 +86,25 @@ namespace __unicode
{ return *__it == iter_value_t<_It>{}; }
};
+ // An iterator over an input range of FromFmt code units that yields either
+ // UTF-8, UTF-16, or UTF-32, as a range of ToFmt code units.
+ // The code units from the input range are interpreted as Unicode code points
+ // and the iterator produces the individual code unit for each code point.
+ // Invalid sequences in the input are replaced with U+FFDD so that the result
+ // is always valid UTF-8, UTF-16, or UTF-32.
+ //
+ // The iterator knows the bounds of the underlying input range and will not
+ // read outside those bounds (incrementing or decrementing at the boundary
+ // is erroneously idempotent).
+ //
+ // On construction, the iterator attemps to decode a single code point from
+ // the input range and then encode it into an internal buffer in the output
+ // format, e.g. if the input is UTF-8 and the output is UTF-16, it might read
+ // three char8_t code units from the input and store two char16_t code units
+ // in its buffer. Incrementing the iterator will first iterate over buffer,
+ // yielding each code unit in turn, and then extract another code point from
+ // the input. Failure to extract a valid code point from the input will store
+ // U+FFFD in the buffer, encoded as the appropriate code units of type ToFmt.
template<typename _FromFmt, typename _ToFmt,
input_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter,
typename _ErrorHandler = _Repl>
@@ -162,17 +181,20 @@ namespace __unicode
constexpr _Utf_iterator&
operator++()
{
- if (_M_buf_index + 1 == _M_buf_last && _M_curr() != _M_last)
+ if (_M_buf_index + 1 < _M_buf_last)
+ ++_M_buf_index; // Move to the next code unit in the buffer.
+ else if (_M_curr() != _M_last)
{
+ // Advance past the current code point (for non-forward iterators
+ // we already moved there after decoding the last code point).
if constexpr (forward_iterator<_Iter>)
std::advance(_M_curr(), _M_to_increment);
if (_M_curr() == _M_last)
_M_buf_index = 0;
- else
+ else // Decode next code point from the input and update buffer.
_M_read();
}
- else if (_M_buf_index + 1 < _M_buf_last)
- ++_M_buf_index;
+ // else erroneous, but ignored for now.
return *this;
}
@@ -187,10 +209,15 @@ namespace __unicode
constexpr _Utf_iterator&
operator--() requires bidirectional_iterator<_Iter>
{
- if (!_M_buf_index && _M_curr() != _M_first())
- _M_read_reverse();
- else if (_M_buf_index)
+ if (_M_buf_index > 0)
--_M_buf_index;
+ else if (_M_curr() != _M_first())
+ {
+ _M_read_reverse();
+ _M_buf_index = _M_buf_last - 1;
+ ranges::advance(_M_curr(), -_M_to_increment);
+ }
+ // else erroneous, but ignored for now.
return *this;
}
@@ -247,7 +274,18 @@ namespace __unicode
}
constexpr void
- _M_read_reverse(); // TODO
+ _M_read_reverse() requires bidirectional_iterator<_Iter>
+ {
+ if constexpr (sizeof(_FromFmt) == sizeof(uint8_t))
+ _M_read_reverse_utf8();
+ else if constexpr (sizeof(_FromFmt) == sizeof(uint16_t))
+ _M_read_reverse_utf16();
+ else
+ {
+ static_assert(sizeof(_FromFmt) == sizeof(uint32_t));
+ _M_read_reverse_utf32();
+ }
+ }
template<typename>
struct _Guard
@@ -263,7 +301,7 @@ namespace __unicode
_It _M_orig;
};
- constexpr void
+ constexpr char32_t
_M_read_utf8()
{
_Guard<_Iter> __g{this, _M_curr()};
@@ -361,6 +399,8 @@ namespace __unicode
__c = _S_error();
_M_update(__c, __to_incr);
+
+ return __c;
}
constexpr void
@@ -403,6 +443,116 @@ namespace __unicode
_M_update(__c, 1);
}
+ constexpr void
+ _M_read_reverse_utf8() requires bidirectional_iterator<_Iter>
+ {
+ const auto __first = _M_first();
+ auto __curr = _M_curr();
+ // The code point we decode:
+ char32_t __c{};
+ // The last code unit read:
+ uint8_t __u = *--__curr;
+ // Count of bytes read:
+ uint8_t __to_incr = 1;
+
+ if (__u <= 0x7F) [[likely]]
+ {
+ _M_update(__u, 1);
+ return;
+ }
+
+ // Continuation bytes match 10xxxxxx
+ auto __is_continuation = [](uint8_t __b) {
+ return (__b & 0xC0) == 0x80;
+ };
+ // 0xC0 and 0xC1 would produce overlong encodings of ASCII characters.
+ // 0xF5-0xFF would produce code points above U+10FFFF
+ auto __is_invalid = [](uint8_t __b) {
+ return (__b & 0xFE) == 0xC0 || __b >= 0xF5;
+ };
+
+ // No valid or invalid multibyte sequence is longer than 4 bytes,
+ // so skip back over at most four bytes.
+ while (__is_continuation(__u) && __to_incr < 4 && __curr != __first)
+ {
+ ++__to_incr;
+ __u = *--__curr;
+ }
+
+ // If the last byte read was a continuation byte then either we read
+ // four continuation bytes, or stopped at the start of the sequence.
+ // Either way, the maximal subparts are the individual continuation
+ // bytes so each one should be replaced with U+FFFD.
+ if (__is_continuation(__u) || __is_invalid(__u)) [[unlikely]]
+ {
+ // Either found four continuation bytes (maximum allowed is three)
+ // or first non-continuation byte is an invalid UTF-8 code unit.
+ _M_update(_S_error(), 1);
+ return;
+ }
+ // __u is a valid start byte so use countl_one to get the expected
+ // length of the multibyte sequence that starts with this byte.
+ int __seq_length = std::countl_one((unsigned char)__u);
+ if (__seq_length < __to_incr) [[unlikely]]
+ {
+ // If the expected number of continuation bytes is less than
+ // the number we found, then the last continuation byte is a
+ // maximal subpart and the decremented iterator points to it.
+ _M_update(_S_error(), 1);
+ return;
+ }
+
+ auto __orig = std::__exchange(_M_curr(), std::move(__curr));
+ if (_M_read_utf8() == _S_error()) [[unlikely]]
+ {
+ if (_M_to_increment < __to_incr) // Read truncated sequence, set
+ _M_to_increment = 1; // curr to last continuation byte.
+ }
+
+ _M_curr() = std::move(__orig);
+ // operator--() will move back by _M_to_increment
+ }
+
+ constexpr void
+ _M_read_reverse_utf16() requires bidirectional_iterator<_Iter>
+ {
+ _Guard<_Iter> __g{this, _M_curr()};
+ char32_t __c{};
+ uint16_t __u = *--_M_curr();
+ uint8_t __to_incr = 1;
+
+ if (__u < 0xD800 || __u > 0xDFFF) [[likely]]
+ __c = __u;
+ else if (__u >= 0xDC00 && _M_curr() != _M_first()) [[likely]]
+ {
+ // read a low surrogate, expect a high surrogate before it.
+ uint16_t __u2 = *--_M_curr();
+ if (__u2 < 0xD800 || __u2 >= 0xDC00) [[unlikely]]
+ __c = _S_error(); // unpaired low surrogate
+ else
+ {
+ __to_incr = 2;
+ uint32_t __x = (__u2 & 0x3F) << 10 | (__u & 0x3FF);
+ uint32_t __w = (__u2 >> 6) & 0x1F;
+ __c = (__w + 1) << 16 | __x;
+ }
+ }
+ else
+ __c = _S_error(); // unpaired surrogate
+
+ _M_update(__c, __to_incr);
+ }
+
+ constexpr void
+ _M_read_reverse_utf32() requires bidirectional_iterator<_Iter>
+ {
+ _Guard<_Iter> __g{this, _M_curr()};
+ char32_t __c = *--_M_curr();
+ if (!__is_scalar_value(__c)) [[unlikely]]
+ __c = _S_error();
+ _M_update(__c, 1);
+ }
+
// Encode the code point __c as one or more code units in _M_buf.
constexpr void
_M_update(char32_t __c, uint8_t __to_incr)
@@ -487,8 +637,7 @@ namespace __unicode
constexpr _Iter
_M_curr() const { return _M_first_and_curr._M_curr; }
- array<value_type, 4 / sizeof(_ToFmt)> _M_buf;
-
+ // _M_first is not needed for non-bidirectional ranges.
template<typename _It>
struct _First_and_curr
{
@@ -502,6 +651,8 @@ namespace __unicode
_First_and_curr(const _First_and_curr<_It2>& __other)
: _M_curr(__other._M_curr) { }
+ // First code unit of the current code point for forward iterators,
+ // past-the-end of the current code point for input iterators.
_It _M_curr;
};
@@ -519,18 +670,24 @@ namespace __unicode
_First_and_curr(const _First_and_curr<_It2>& __other)
: _M_first(__other._M_first), _M_curr(__other._M_curr) { }
- _It _M_first;
- _It _M_curr;
+ _It _M_first; // Start of the underlying range.
+ _It _M_curr; // First code unit of the current code point.
};
+ // Iterators pointing to the start of the underlying range and to the
+ // start (or end, for non-forward iterators) of the current code point.
_First_and_curr<_Iter> _M_first_and_curr;
- uint8_t _M_buf_index = 0;
- uint8_t _M_buf_last = 0;
- uint8_t _M_to_increment = 0;
-
+ // The end of the underlying input range.
[[no_unique_address]] _Sent _M_last;
+ // Buffer holding the individual code units of the current code point.
+ array<value_type, 4 / sizeof(_ToFmt)> _M_buf;
+
+ uint8_t _M_buf_index = 0; // Index of current code unit in the buffer.
+ uint8_t _M_buf_last = 0; // Number of code units in the buffer.
+ uint8_t _M_to_increment = 0; // How far to advance _M_curr on increment.
+
template<typename _FromFmt2, typename _ToFmt2,
input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
typename _ErrHandler>
@@ -538,13 +695,14 @@ namespace __unicode
friend class _Utf_iterator;
};
- template<typename _ToFormat, ranges::input_range _Range>
+ template<typename _ToFormat, ranges::input_range _View>
+ requires ranges::view<_View>
class _Utf_view
- : public ranges::view_interface<_Utf_view<_ToFormat, _Range>>
+ : public ranges::view_interface<_Utf_view<_ToFormat, _View>>
{
- using _Iterator = _Utf_iterator<ranges::range_value_t<_Range>,
- _ToFormat, ranges::iterator_t<_Range>,
- ranges::sentinel_t<_Range>>;
+ using _Iterator = _Utf_iterator<ranges::range_value_t<_View>,
+ _ToFormat, ranges::iterator_t<_View>,
+ ranges::sentinel_t<_View>>;
template<typename _Iter, typename _Sent>
constexpr auto
@@ -568,11 +726,11 @@ namespace __unicode
return _Iterator(__last, __last);
}
- _Range _M_base;
+ _View _M_base;
public:
constexpr explicit
- _Utf_view(_Range&& __r) : _M_base(std::forward<_Range>(__r)) { }
+ _Utf_view(_View __r) : _M_base(std::move(__r)) { }
constexpr auto begin()
{ return _M_begin(ranges::begin(_M_base), ranges::end(_M_base)); }
diff --git a/libstdc++-v3/include/bits/uniform_int_dist.h b/libstdc++-v3/include/bits/uniform_int_dist.h
index d96dcbd..77b1e96 100644
--- a/libstdc++-v3/include/bits/uniform_int_dist.h
+++ b/libstdc++-v3/include/bits/uniform_int_dist.h
@@ -308,9 +308,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const __uctype __uerange = __urange + 1; // __urange can be zero
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
#if defined __UINT64_TYPE__ && defined __UINT32_TYPE__
#if __SIZEOF_INT128__
- if _GLIBCXX17_CONSTEXPR (__urngrange == __UINT64_MAX__)
+ if constexpr (__urngrange == __UINT64_MAX__)
{
// __urng produces values that use exactly 64-bits,
// so use 128-bit integers to downscale to desired range.
@@ -320,7 +322,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
else
#endif
- if _GLIBCXX17_CONSTEXPR (__urngrange == __UINT32_MAX__)
+ if constexpr (__urngrange == __UINT32_MAX__)
{
// __urng produces values that use exactly 32-bits,
// so use 64-bit integers to downscale to desired range.
@@ -338,6 +340,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
while (__ret >= __past);
__ret /= __scaling;
}
+#pragma GCC diagnostic pop
}
else if (__urngrange < __urange)
{
diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h
index 6ae46a9..978deb3 100644
--- a/libstdc++-v3/include/bits/unique_ptr.h
+++ b/libstdc++-v3/include/bits/unique_ptr.h
@@ -1,4 +1,3 @@
-
// unique_ptr implementation -*- C++ -*-
// Copyright (C) 2008-2025 Free Software Foundation, Inc.
@@ -832,6 +831,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ __x.swap(__y); }
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2766. Swapping non-swappable types
template<typename _Tp, typename _Dp>
typename enable_if<!__is_swappable<_Dp>::value>::type
swap(unique_ptr<_Tp, _Dp>&,
diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h
index 5bc58e8..b9b2772 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -91,9 +91,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*
* @tparam _Key Type of key objects.
* @tparam _Tp Type of mapped objects.
- * @tparam _Hash Hashing function object type, defaults to hash<_Value>.
+ * @tparam _Hash Hashing function object type, defaults to hash<_Key>.
* @tparam _Pred Predicate function object type, defaults
- * to equal_to<_Value>.
+ * to equal_to<_Key>.
* @tparam _Alloc Allocator type, defaults to
* std::allocator<std::pair<const _Key, _Tp>>.
*
@@ -251,6 +251,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: unordered_map(__n, __hf, key_equal(), __a)
{ }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered containers
+ template<typename _InputIterator>
+ unordered_map(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a)
+ : unordered_map(__first, __last, 0, hasher(), key_equal(), __a)
+ { }
+
template<typename _InputIterator>
unordered_map(_InputIterator __first, _InputIterator __last,
size_type __n,
@@ -271,6 +279,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: unordered_map(__l, __n, hasher(), key_equal(), __a)
{ }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered containers
+ unordered_map(initializer_list<value_type> __l,
+ const allocator_type& __a)
+ : unordered_map(__l, 0, hasher(), key_equal(), __a)
+ { }
+
unordered_map(initializer_list<value_type> __l,
size_type __n, const hasher& __hf,
const allocator_type& __a)
@@ -946,7 +961,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x)
{ return _M_h.find(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
find(const _Kt& __x) -> decltype(_M_h._M_find_tr(__x))
@@ -957,7 +972,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x) const
{ return _M_h.find(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
find(const _Kt& __x) const -> decltype(_M_h._M_find_tr(__x))
@@ -979,7 +994,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_h.count(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
count(const _Kt& __x) const -> decltype(_M_h._M_count_tr(__x))
@@ -1019,7 +1034,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x)
{ return _M_h.equal_range(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
equal_range(const _Kt& __x)
@@ -1031,7 +1046,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x) const
{ return _M_h.equal_range(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
equal_range(const _Kt& __x) const
@@ -1345,9 +1360,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*
* @tparam _Key Type of key objects.
* @tparam _Tp Type of mapped objects.
- * @tparam _Hash Hashing function object type, defaults to hash<_Value>.
+ * @tparam _Hash Hashing function object type, defaults to hash<_Key>.
* @tparam _Pred Predicate function object type, defaults
- * to equal_to<_Value>.
+ * to equal_to<_Key>.
* @tparam _Alloc Allocator type, defaults to
* std::allocator<std::pair<const _Key, _Tp>>.
*
@@ -1504,6 +1519,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: unordered_multimap(__n, __hf, key_equal(), __a)
{ }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered containers
+ template<typename _InputIterator>
+ unordered_multimap(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a)
+ : unordered_multimap(__first, __last, 0, hasher(), key_equal(), __a)
+ { }
+
template<typename _InputIterator>
unordered_multimap(_InputIterator __first, _InputIterator __last,
size_type __n,
@@ -1518,6 +1541,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: unordered_multimap(__first, __last, __n, __hf, key_equal(), __a)
{ }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered containers
+ unordered_multimap(initializer_list<value_type> __l,
+ const allocator_type& __a)
+ : unordered_multimap(__l, 0, hasher(), key_equal(), __a)
+ { }
+
unordered_multimap(initializer_list<value_type> __l,
size_type __n,
const allocator_type& __a)
@@ -2009,7 +2039,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x)
{ return _M_h.find(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
find(const _Kt& __x) -> decltype(_M_h._M_find_tr(__x))
@@ -2020,7 +2050,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x) const
{ return _M_h.find(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
find(const _Kt& __x) const -> decltype(_M_h._M_find_tr(__x))
@@ -2038,7 +2068,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_h.count(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
count(const _Kt& __x) const -> decltype(_M_h._M_count_tr(__x))
@@ -2076,7 +2106,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x)
{ return _M_h.equal_range(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
equal_range(const _Kt& __x)
@@ -2088,7 +2118,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x) const
{ return _M_h.equal_range(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
equal_range(const _Kt& __x) const
diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h
index 091bae6..29bc49a 100644
--- a/libstdc++-v3/include/bits/unordered_set.h
+++ b/libstdc++-v3/include/bits/unordered_set.h
@@ -245,6 +245,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: unordered_set(__n, __hf, key_equal(), __a)
{ }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered container
+ template<typename _InputIterator>
+ unordered_set(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a)
+ : unordered_set(__first, __last, 0, hasher(), key_equal(), __a)
+ { }
+
template<typename _InputIterator>
unordered_set(_InputIterator __first, _InputIterator __last,
size_type __n,
@@ -259,6 +267,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: unordered_set(__first, __last, __n, __hf, key_equal(), __a)
{ }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered container
+ unordered_set(initializer_list<value_type> __l,
+ const allocator_type& __a)
+ : unordered_set(__l, 0, hasher(), key_equal(), __a)
+ { }
+
unordered_set(initializer_list<value_type> __l,
size_type __n,
const allocator_type& __a)
@@ -728,7 +744,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x)
{ return _M_h.find(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
find(const _Kt& __k)
@@ -740,7 +756,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x) const
{ return _M_h.find(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
find(const _Kt& __k) const
@@ -763,7 +779,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_h.count(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
count(const _Kt& __k) const
@@ -804,7 +820,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x)
{ return _M_h.equal_range(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
equal_range(const _Kt& __k)
@@ -816,7 +832,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x) const
{ return _M_h.equal_range(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
equal_range(const _Kt& __k) const
@@ -987,6 +1003,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typename iterator_traits<_InputIterator>::value_type>,
_Allocator>;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered container
+ template<typename _InputIterator, typename _Allocator,
+ typename = _RequireInputIter<_InputIterator>,
+ typename = _RequireAllocator<_Allocator>>
+ unordered_set(_InputIterator, _InputIterator, _Allocator)
+ -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
+ hash<
+ typename iterator_traits<_InputIterator>::value_type>,
+ equal_to<
+ typename iterator_traits<_InputIterator>::value_type>,
+ _Allocator>;
+
template<typename _InputIterator, typename _Hash, typename _Allocator,
typename = _RequireInputIter<_InputIterator>,
typename = _RequireNotAllocatorOrIntegral<_Hash>,
@@ -1006,6 +1035,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
unordered_set<int>::size_type, _Allocator)
-> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered container
+ template<typename _Tp, typename _Allocator,
+ typename = _RequireAllocator<_Allocator>>
+ unordered_set(initializer_list<_Tp>, _Allocator)
+ -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
+
template<typename _Tp, typename _Hash, typename _Allocator,
typename = _RequireNotAllocatorOrIntegral<_Hash>,
typename = _RequireAllocator<_Allocator>>
@@ -1223,6 +1259,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: unordered_multiset(__n, __hf, key_equal(), __a)
{ }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered container
+ template<typename _InputIterator>
+ unordered_multiset(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a)
+ : unordered_multiset(__first, __last, 0, hasher(), key_equal(), __a)
+ { }
+
template<typename _InputIterator>
unordered_multiset(_InputIterator __first, _InputIterator __last,
size_type __n,
@@ -1237,6 +1281,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: unordered_multiset(__first, __last, __n, __hf, key_equal(), __a)
{ }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered container
+ unordered_multiset(initializer_list<value_type> __l,
+ const allocator_type& __a)
+ : unordered_multiset(__l, 0, hasher(), key_equal(), __a)
+ { }
+
unordered_multiset(initializer_list<value_type> __l,
size_type __n,
const allocator_type& __a)
@@ -1694,7 +1745,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x)
{ return _M_h.find(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
find(const _Kt& __x)
@@ -1706,7 +1757,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x) const
{ return _M_h.find(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
find(const _Kt& __x) const
@@ -1725,7 +1776,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_h.count(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
count(const _Kt& __x) const -> decltype(_M_h._M_count_tr(__x))
@@ -1763,7 +1814,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x)
{ return _M_h.equal_range(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
equal_range(const _Kt& __x)
@@ -1775,7 +1826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x) const
{ return _M_h.equal_range(__x); }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt>
auto
equal_range(const _Kt& __x) const
@@ -1949,6 +2000,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator_traits<_InputIterator>::value_type>,
_Allocator>;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered container
+ template<typename _InputIterator, typename _Allocator,
+ typename = _RequireInputIter<_InputIterator>,
+ typename = _RequireAllocator<_Allocator>>
+ unordered_multiset(_InputIterator, _InputIterator, _Allocator)
+ -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
+ hash<typename
+ iterator_traits<_InputIterator>::value_type>,
+ equal_to<typename
+ iterator_traits<_InputIterator>::value_type>,
+ _Allocator>;
+
template<typename _InputIterator, typename _Hash, typename _Allocator,
typename = _RequireInputIter<_InputIterator>,
typename = _RequireNotAllocatorOrIntegral<_Hash>,
@@ -1970,6 +2034,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
unordered_multiset<int>::size_type, _Allocator)
-> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2713. More missing allocator-extended constructors for unordered container
+ template<typename _Tp, typename _Allocator,
+ typename = _RequireAllocator<_Allocator>>
+ unordered_multiset(initializer_list<_Tp>, _Allocator)
+ -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
+
template<typename _Tp, typename _Hash, typename _Allocator,
typename = _RequireNotAllocatorOrIntegral<_Hash>,
typename = _RequireAllocator<_Allocator>>
diff --git a/libstdc++-v3/include/bits/utility.h b/libstdc++-v3/include/bits/utility.h
index 6fa6b67..96ac698 100644
--- a/libstdc++-v3/include/bits/utility.h
+++ b/libstdc++-v3/include/bits/utility.h
@@ -137,26 +137,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using tuple_element_t = typename tuple_element<__i, _Tp>::type;
#endif
- // Stores a tuple of indices. Used by tuple and pair, and by bind() to
- // extract the elements in a tuple.
- template<size_t... _Indexes> struct _Index_tuple { };
-
- // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
- template<size_t _Num>
- struct _Build_index_tuple
- {
-#if __has_builtin(__make_integer_seq)
- template<typename, size_t... _Indices>
- using _IdxTuple = _Index_tuple<_Indices...>;
-
- // Clang defines __make_integer_seq for this purpose.
- using __type = __make_integer_seq<_IdxTuple, size_t, _Num>;
-#else
- // For GCC and other compilers, use __integer_pack instead.
- using __type = _Index_tuple<__integer_pack(_Num)...>;
-#endif
- };
-
#ifdef __glibcxx_integer_sequence // C++ >= 14
/// Class template integer_sequence
@@ -192,6 +172,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using index_sequence_for = make_index_sequence<sizeof...(_Types)>;
#endif // __glibcxx_integer_sequence
+#if __cpp_structured_bindings >= 202411L
+#if __has_builtin(__integer_pack)
+ template <auto _Num, typename _Tp = decltype(_Num)>
+ inline constexpr _Tp
+ _IotaArray[_Num] = {__integer_pack(_Tp(_Num))...};
+#elif defined __glibcxx_integer_sequence
+ template <auto _Num, typename _Tp = decltype(_Num), typename = make_integer_sequence<_Tp, _Num>>
+ inline constexpr _Tp
+ _IotaArray[_Num];
+
+ template <auto _Num, typename _Tp, _Tp... _Is>
+ inline constexpr _Tp
+ _IotaArray<_Num, _Tp, integer_sequence<_Tp, _Is...>>[_Num] = {_Is...};
+#endif // __integer_pack
+#endif // __cpp_structured_bindings >= 202411L
+
#if __cplusplus >= 201703L
struct in_place_t {
@@ -316,6 +312,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline constexpr sorted_equivalent_t sorted_equivalent{};
#endif
+#if __glibcxx_function_ref // >= C++26
+ template<auto>
+ struct nontype_t
+ {
+ explicit nontype_t() = default;
+ };
+
+ template<auto __val>
+ constexpr nontype_t<__val> nontype{};
+
+ template<typename>
+ inline constexpr bool __is_nontype_v = false;
+
+ template<auto __val>
+ inline constexpr bool __is_nontype_v<nontype_t<__val>> = true;
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/bits/valarray_array.h b/libstdc++-v3/include/bits/valarray_array.h
index 03b6f1e..d1b712c 100644
--- a/libstdc++-v3/include/bits/valarray_array.h
+++ b/libstdc++-v3/include/bits/valarray_array.h
@@ -38,6 +38,7 @@
#include <bits/c++config.h>
#include <bits/cpp_type_traits.h>
+#include <bits/new_allocator.h>
#include <cstdlib>
#include <new>
@@ -57,12 +58,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
inline _Tp*
__valarray_get_storage(size_t __n)
- { return static_cast<_Tp*>(operator new(__n * sizeof(_Tp))); }
+ { return std::__new_allocator<_Tp>().allocate(__n); }
// Return memory to the system
- inline void
- __valarray_release_memory(void* __p)
- { operator delete(__p); }
+ template<typename _Tp>
+ inline void
+ __valarray_release_memory(_Tp* __p, size_t __n)
+ { std::__new_allocator<_Tp>().deallocate(__p, __n); }
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
// Turn raw-memory into an array of _Tp filled with _Tp().
// This is used in `valarray<T> v(n);` and in `valarray<T>::shift(n)`.
@@ -70,7 +75,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline void
__valarray_default_construct(_Tp* __b, _Tp* __e)
{
- if _GLIBCXX17_CONSTEXPR (__is_trivial(_Tp))
+ if _GLIBCXX_CONSTEXPR (__is_trivial(_Tp))
__builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp));
else
while (__b != __e)
@@ -94,7 +99,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__valarray_copy_construct(const _Tp* __b, const _Tp* __e,
_Tp* __restrict__ __o)
{
- if _GLIBCXX17_CONSTEXPR (__is_trivial(_Tp))
+ if _GLIBCXX_CONSTEXPR (__is_trivial(_Tp))
{
if (__b)
__builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp));
@@ -110,7 +115,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n,
size_t __s, _Tp* __restrict__ __o)
{
- if _GLIBCXX17_CONSTEXPR (__is_trivial(_Tp))
+ if _GLIBCXX_CONSTEXPR (__is_trivial(_Tp))
while (__n--)
{
*__o++ = *__a;
@@ -131,7 +136,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const size_t* __restrict__ __i,
_Tp* __restrict__ __o, size_t __n)
{
- if (__is_trivial(_Tp))
+ if _GLIBCXX_CONSTEXPR (__is_trivial(_Tp))
while (__n--)
*__o++ = __a[*__i++];
else
@@ -144,7 +149,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline void
__valarray_destroy_elements(_Tp* __b, _Tp* __e)
{
- if (!__is_trivial(_Tp))
+ if _GLIBCXX_CONSTEXPR (!__is_trivial(_Tp))
while (__b != __e)
{
__b->~_Tp();
@@ -152,6 +157,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
+#pragma GCC diagnostic pop
+
// Fill a plain array __a[<__n>] with __t
template<typename _Tp>
inline void
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index b21e1d3..642edb5 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -61,6 +61,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+
template<typename _Tp, typename _Alloc>
_GLIBCXX20_CONSTEXPR
void
@@ -74,11 +77,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const size_type __old_size = size();
pointer __tmp;
#if __cplusplus >= 201103L
- if _GLIBCXX17_CONSTEXPR (_S_use_relocate())
+ if constexpr (_S_use_relocate())
{
__tmp = this->_M_allocate(__n);
- _S_relocate(this->_M_impl._M_start, this->_M_impl._M_finish,
- __tmp, _M_get_Tp_allocator());
+ std::__relocate_a(this->_M_impl._M_start, this->_M_impl._M_finish,
+ __tmp, _M_get_Tp_allocator());
}
else
#endif
@@ -98,6 +101,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
}
}
+#pragma GCC diagnostic pop
#if __cplusplus >= 201103L
template<typename _Tp, typename _Alloc>
@@ -444,6 +448,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
#if __cplusplus >= 201103L
template<typename _Tp, typename _Alloc>
template<typename... _Args>
@@ -460,7 +466,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
const size_type __len = _M_check_len(1u, "vector::_M_realloc_insert");
if (__len <= 0)
- __builtin_unreachable ();
+ __builtin_unreachable();
pointer __old_start = this->_M_impl._M_start;
pointer __old_finish = this->_M_impl._M_finish;
const size_type __elems_before = __position - begin();
@@ -488,14 +494,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
#if __cplusplus >= 201103L
- if _GLIBCXX17_CONSTEXPR (_S_use_relocate())
+ if constexpr (_S_use_relocate())
{
// Relocation cannot throw.
- __new_finish = _S_relocate(__old_start, __position.base(),
- __new_start, _M_get_Tp_allocator());
+ __new_finish = std::__relocate_a(__old_start, __position.base(),
+ __new_start,
+ _M_get_Tp_allocator());
++__new_finish;
- __new_finish = _S_relocate(__position.base(), __old_finish,
- __new_finish, _M_get_Tp_allocator());
+ __new_finish = std::__relocate_a(__position.base(), __old_finish,
+ __new_finish,
+ _M_get_Tp_allocator());
}
else
#endif
@@ -565,10 +573,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
const size_type __len = _M_check_len(1u, "vector::_M_realloc_append");
if (__len <= 0)
- __builtin_unreachable ();
+ __builtin_unreachable();
pointer __old_start = this->_M_impl._M_start;
pointer __old_finish = this->_M_impl._M_finish;
- const size_type __elems = end() - begin();
+ const size_type __elems = size();
pointer __new_start(this->_M_allocate(__len));
pointer __new_finish(__new_start);
@@ -593,11 +601,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
#if __cplusplus >= 201103L
- if _GLIBCXX17_CONSTEXPR (_S_use_relocate())
+ if constexpr (_S_use_relocate())
{
// Relocation cannot throw.
- __new_finish = _S_relocate(__old_start, __old_finish,
- __new_start, _M_get_Tp_allocator());
+ __new_finish = std::__relocate_a(__old_start, __old_finish,
+ __new_start,
+ _M_get_Tp_allocator());
++__new_finish;
}
else
@@ -645,6 +654,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
this->_M_impl._M_finish = __new_finish;
this->_M_impl._M_end_of_storage = __new_start + __len;
}
+#pragma GCC diagnostic pop
template<typename _Tp, typename _Alloc>
_GLIBCXX20_CONSTEXPR
@@ -654,8 +664,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
if (__n != 0)
{
- if (size_type(this->_M_impl._M_end_of_storage
- - this->_M_impl._M_finish) >= __n)
+ if (__position.base() == this->_M_impl._M_finish)
+ _M_fill_append(__n, __x);
+ else if (size_type(this->_M_impl._M_end_of_storage
+ - this->_M_impl._M_finish) >= __n)
{
#if __cplusplus < 201103L
value_type __x_copy = __x;
@@ -750,7 +762,63 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
}
+ template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
+ void
+ vector<_Tp, _Alloc>::
+ _M_fill_append(size_type __n, const value_type& __x)
+ {
+ if (size_type(this->_M_impl._M_end_of_storage
+ - this->_M_impl._M_finish) >= __n)
+ {
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
+ this->_M_impl._M_finish =
+ std::__uninitialized_fill_n_a(this->_M_impl._M_finish, __n, __x,
+ _M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
+ }
+ else
+ {
+ // Make local copies of these members because the compiler thinks
+ // the allocator can alter them if 'this' is globally reachable.
+ pointer __old_start = this->_M_impl._M_start;
+ pointer __old_finish = this->_M_impl._M_finish;
+ const size_type __old_size = __old_finish - __old_start;
+
+ const size_type __len =
+ _M_check_len(__n, "vector::_M_fill_append");
+ pointer __new_start(this->_M_allocate(__len));
+ pointer __new_finish(__new_start + __old_size);
+ __try
+ {
+ // See _M_realloc_insert above.
+ __new_finish = std::__uninitialized_fill_n_a(
+ __new_finish, __n, __x,
+ _M_get_Tp_allocator());
+ std::__uninitialized_move_if_noexcept_a(
+ __old_start, __old_finish, __new_start,
+ _M_get_Tp_allocator());
+ }
+ __catch(...)
+ {
+ std::_Destroy(__new_start + __old_size, __new_finish,
+ _M_get_Tp_allocator());
+ _M_deallocate(__new_start, __len);
+ __throw_exception_again;
+ }
+ std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
+ _M_deallocate(__old_start,
+ this->_M_impl._M_end_of_storage - __old_start);
+ this->_M_impl._M_start = __new_start;
+ this->_M_impl._M_finish = __new_finish;
+ this->_M_impl._M_end_of_storage = __new_start + __len;
+ }
+ }
+
#if __cplusplus >= 201103L
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
template<typename _Tp, typename _Alloc>
_GLIBCXX20_CONSTEXPR
void
@@ -794,10 +862,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::__uninitialized_default_n_a(__new_start + __size, __n,
_M_get_Tp_allocator());
- if _GLIBCXX17_CONSTEXPR (_S_use_relocate())
+ if constexpr (_S_use_relocate())
{
- _S_relocate(__old_start, __old_finish,
- __new_start, _M_get_Tp_allocator());
+ std::__relocate_a(__old_start, __old_finish,
+ __new_start, _M_get_Tp_allocator());
}
else
{
@@ -842,6 +910,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
}
}
+#pragma GCC diagnostic pop
template<typename _Tp, typename _Alloc>
_GLIBCXX20_CONSTEXPR
@@ -994,15 +1063,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if constexpr (ranges::forward_range<_Rg>)
{
+ const auto __ins_idx = __pos - cbegin();
+ // Number of new elements to insert:
+ const auto __n = size_type(ranges::distance(__rg));
+ if (__n == 0)
+ return begin() + __ins_idx;
+
// Start of existing elements:
pointer __old_start = this->_M_impl._M_start;
// End of existing elements:
pointer __old_finish = this->_M_impl._M_finish;
// Insertion point:
- const auto __ins_idx = __pos - cbegin();
pointer __ins = __old_start + __ins_idx;
- // Number of new elements to insert:
- const auto __n = size_type(ranges::distance(__rg));
// Number of elements that can fit in unused capacity:
const auto __cap = this->_M_impl._M_end_of_storage - __old_finish;
if (__cap >= __n)
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 0afaf0d..5c010a4 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -394,6 +394,14 @@ ftms = {
};
ftms = {
+ name = constant_wrapper;
+ values = {
+ v = 202506;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
name = has_unique_object_representations;
values = {
v = 201606;
@@ -464,6 +472,10 @@ ftms = {
ftms = {
name = not_fn;
values = {
+ v = 202306;
+ cxxmin = 26;
+ };
+ values = {
v = 201603;
cxxmin = 17;
};
@@ -582,6 +594,12 @@ ftms = {
ftms = {
name = chrono;
values = {
+ v = 202306;
+ cxxmin = 26;
+ hosted = yes;
+ cxx11abi = yes;
+ };
+ values = {
v = 201907;
cxxmin = 20;
hosted = yes;
@@ -595,6 +613,21 @@ ftms = {
};
ftms = {
+ // Unofficial macro for chrono features supported for old string ABI.
+ name = chrono_cxx20;
+ values = {
+ v = 202306;
+ cxxmin = 26;
+ no_stdname = yes;
+ };
+ values = {
+ v = 201800;
+ cxxmin = 20;
+ no_stdname = yes;
+ };
+};
+
+ftms = {
name = execution;
values = {
v = 201902; // FIXME: should be 201603L
@@ -649,7 +682,7 @@ ftms = {
};
values = {
v = 1;
- /* For when there's no gthread. */
+ // For when there is no gthread.
cxxmin = 17;
hosted = yes;
gthread = no;
@@ -679,8 +712,6 @@ ftms = {
values = {
v = 201703;
cxxmin = 17;
- hosted = yes;
- gthread = yes;
};
};
@@ -735,6 +766,14 @@ ftms = {
};
ftms = {
+ name = is_sufficiently_aligned;
+ values = {
+ v = 202411;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
name = atomic_flag_test;
values = {
v = 201907;
@@ -762,6 +801,10 @@ ftms = {
ftms = {
name = atomic_ref;
values = {
+ v = 202411;
+ cxxmin = 26;
+ };
+ values = {
v = 201806;
cxxmin = 20;
};
@@ -779,6 +822,10 @@ ftms = {
ftms = {
name = bind_front;
values = {
+ v = 202306;
+ cxxmin = 26;
+ };
+ values = {
v = 201907;
cxxmin = 20;
};
@@ -787,6 +834,10 @@ ftms = {
ftms = {
name = bind_back;
values = {
+ v = 202306;
+ cxxmin = 26;
+ };
+ values = {
v = 202202;
cxxmin = 23;
extra_cond = "__cpp_explicit_this_parameter";
@@ -828,8 +879,12 @@ ftms = {
ftms = {
name = concepts;
+ // 201806 P0898R3 Standard Library Concepts
+ // 201907 P1754R1 Rename concepts to standard_case for C++20
+ // 202002 P1964R2 Wording for boolean-testable
+ // 202207 P2404R3 Move-only types for equality_comparable_with, etc.
values = {
- v = 202002;
+ v = 202207;
cxxmin = 20;
extra_cond = "__cpp_concepts >= 201907L";
};
@@ -838,12 +893,17 @@ ftms = {
// Moved down here (after concepts) by topological sort.
ftms = {
name = optional;
- values = {
+ values = { // optional<T&>
+ v = 202506;
+ cxxmin = 26;
+ extra_cond = "__glibcxx_concepts";
+ };
+ values = { // monadic operations
v = 202110;
cxxmin = 23;
extra_cond = "__glibcxx_concepts";
};
- values = {
+ values = { // full constexpr support
v = 202106;
cxxmin = 20;
};
@@ -854,6 +914,14 @@ ftms = {
};
ftms = {
+ name = optional_range_support;
+ values = {
+ v = 202406;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
name = destroying_delete;
values = {
v = 201806;
@@ -959,6 +1027,7 @@ ftms = {
ftms = {
name = make_obj_using_allocator;
+ no_stdname = true;
values = {
// Not specified by C++20, used internally
v = 201811;
@@ -999,6 +1068,47 @@ ftms = {
};
ftms = {
+ name = mdspan;
+ values = {
+ v = 202406;
+ cxxmin = 26;
+ };
+ values = {
+ v = 202207;
+ cxxmin = 23;
+ };
+};
+
+ftms = {
+ name = aligned_accessor;
+ values = {
+ v = 202411;
+ cxxmin = 26;
+ extra_cond = "__glibcxx_assume_aligned "
+ "&& __glibcxx_is_sufficiently_aligned";
+ };
+};
+
+// Purely internal macro padded layouts.
+ftms = {
+ name = padded_layouts;
+ no_stdname = true; // internal
+ values = {
+ v = 202403;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
+ name = submdspan;
+ values = {
+ v = 202411;
+ cxxmin = 26;
+ extra_cond = "__glibcxx_constant_wrapper >= 202506L";
+ };
+};
+
+ftms = {
name = ssize;
values = {
v = 201902;
@@ -1076,6 +1186,10 @@ ftms = {
ftms = {
name = shift;
values = {
+ v = 202202;
+ cxxmin = 23;
+ };
+ values = {
v = 201806;
cxxmin = 20;
};
@@ -1355,7 +1469,7 @@ ftms = {
v = 201907;
cxxmin = 20;
hosted = yes;
- extra_cond = "__glibcxx_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE";
+ extra_cond = "__glibcxx_atomic_wait";
};
};
@@ -1416,9 +1530,8 @@ ftms = {
// 202207 P2286R8 Formatting Ranges
// 202207 P2585R1 Improving default container formatting
// LWG3750 Too many papers bump __cpp_lib_format
- no_stdname = true; // TODO remove
values = {
- v = 1; // TODO 202207
+ v = 202207;
cxxmin = 23;
hosted = yes;
};
@@ -1654,6 +1767,22 @@ ftms = {
};
ftms = {
+ name = ranges_starts_ends_with;
+ values = {
+ v = 202106;
+ cxxmin = 23;
+ };
+};
+
+ftms = {
+ name = ranges_indices;
+ values = {
+ v = 202506;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
name = constexpr_bitset;
values = {
v = 202202;
@@ -1697,6 +1826,22 @@ ftms = {
};
ftms = {
+ name = common_reference;
+ values = {
+ v = 202302;
+ cxxmin = 20; // We treat P2655R3 as a DR against C++20.
+ };
+};
+
+ftms = {
+ name = common_reference_wrapper;
+ values = {
+ v = 202302;
+ cxxmin = 20; // We treat P2655R3 as a DR against C++20.
+ };
+};
+
+ftms = {
name = formatters;
values = {
v = 202302;
@@ -1741,6 +1886,23 @@ ftms = {
};
ftms = {
+ name = copyable_function;
+ values = {
+ v = 202306;
+ cxxmin = 26;
+ hosted = yes;
+ };
+};
+
+ftms = {
+ name = function_ref;
+ values = {
+ v = 202306;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
name = out_ptr;
values = {
v = 202311;
@@ -1751,7 +1913,7 @@ ftms = {
ftms = {
name = print;
values = {
- v = 202211;
+ v = 202406;
cxxmin = 23;
hosted = yes;
};
@@ -1778,6 +1940,14 @@ ftms = {
};
ftms = {
+ name = start_lifetime_as;
+ values = {
+ v = 202207;
+ cxxmin = 23;
+ };
+};
+
+ftms = {
name = string_contains;
values = {
v = 202011;
@@ -1796,6 +1966,14 @@ ftms = {
};
ftms = {
+ name = string_subview;
+ values = {
+ v = 202506;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
name = to_underlying;
values = {
v = 202102;
@@ -1825,6 +2003,15 @@ ftms = {
};
ftms = {
+ name = observable_checkpoint;
+ values = {
+ v = 202506;
+ cxxmin = 26;
+ extra_cond = "__has_builtin(__builtin_observable_checkpoint)";
+ };
+};
+
+ftms = {
name = algorithm_default_value_type;
values = {
v = 202403;
@@ -1842,6 +2029,14 @@ ftms = {
};
ftms = {
+ name = debugging;
+ values = {
+ v = 202403;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
name = fstream_native_handle;
values = {
v = 202306;
@@ -1945,6 +2140,105 @@ ftms = {
};
};
+ftms = {
+ name = inplace_vector;
+ values = {
+ v = 202406;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
+ name = indirect;
+ values = {
+ v = 202502;
+ cxxmin = 26;
+ hosted = yes;
+ };
+};
+
+ftms = {
+ name = polymorphic;
+ values = {
+ v = 202502;
+ cxxmin = 26;
+ hosted = yes;
+ };
+};
+
+ftms = {
+ name = smart_ptr_owner_equality;
+ values = {
+ v = 202306;
+ cxxmin = 26;
+ hosted = yes;
+ };
+};
+
+ftms = {
+ name = sstream_from_string_view;
+ values = {
+ v = 202306;
+ cxxmin = 26;
+ hosted = yes;
+ };
+};
+
+ftms = {
+ name = type_order;
+ values = {
+ v = 202506;
+ cxxmin = 26;
+ extra_cond = "__has_builtin(__builtin_type_order) "
+ "&& __cpp_lib_three_way_comparison >= 201907L";
+ };
+};
+
+ftms = {
+ name = exception_ptr_cast;
+ values = {
+ v = 202506;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
+ name = bitset; // ...construct from string_view
+ values = {
+ v = 202306;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
+ name = constexpr_exceptions;
+ // TODO Remove when PR121114 is resolved
+ no_stdname = true;
+ values = {
+ v = 1; // TODO 202411;
+ cxxmin = 26;
+ extra_cond = "__cpp_constexpr_exceptions >= 202411L";
+ };
+};
+
+ftms = {
+ name = philox_engine;
+ values = {
+ v = 202406;
+ cxxmin = 26;
+ extra_cond = "__SIZEOF_INT128__";
+ };
+};
+
+ftms = {
+ name = is_implicit_lifetime;
+ values = {
+ v = 202302;
+ cxxmin = 23;
+ extra_cond = "__has_builtin(__builtin_is_implicit_lifetime)";
+ };
+};
+
// Standard test specifications.
stds[97] = ">= 199711L";
stds[03] = ">= 199711L";
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 980fee6..26d0689 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -57,7 +57,7 @@
# define __cpp_lib_incomplete_container_elements 201505L
# endif
# endif
-#endif /* !defined(__cpp_lib_incomplete_container_elements) && defined(__glibcxx_want_incomplete_container_elements) */
+#endif /* !defined(__cpp_lib_incomplete_container_elements) */
#undef __glibcxx_want_incomplete_container_elements
#if !defined(__cpp_lib_uncaught_exceptions)
@@ -67,7 +67,7 @@
# define __cpp_lib_uncaught_exceptions 201411L
# endif
# endif
-#endif /* !defined(__cpp_lib_uncaught_exceptions) && defined(__glibcxx_want_uncaught_exceptions) */
+#endif /* !defined(__cpp_lib_uncaught_exceptions) */
#undef __glibcxx_want_uncaught_exceptions
#if !defined(__cpp_lib_allocator_traits_is_always_equal)
@@ -77,7 +77,7 @@
# define __cpp_lib_allocator_traits_is_always_equal 201411L
# endif
# endif
-#endif /* !defined(__cpp_lib_allocator_traits_is_always_equal) && defined(__glibcxx_want_allocator_traits_is_always_equal) */
+#endif /* !defined(__cpp_lib_allocator_traits_is_always_equal) */
#undef __glibcxx_want_allocator_traits_is_always_equal
#if !defined(__cpp_lib_is_null_pointer)
@@ -87,7 +87,7 @@
# define __cpp_lib_is_null_pointer 201309L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_null_pointer) && defined(__glibcxx_want_is_null_pointer) */
+#endif /* !defined(__cpp_lib_is_null_pointer) */
#undef __glibcxx_want_is_null_pointer
#if !defined(__cpp_lib_result_of_sfinae)
@@ -97,7 +97,7 @@
# define __cpp_lib_result_of_sfinae 201210L
# endif
# endif
-#endif /* !defined(__cpp_lib_result_of_sfinae) && defined(__glibcxx_want_result_of_sfinae) */
+#endif /* !defined(__cpp_lib_result_of_sfinae) */
#undef __glibcxx_want_result_of_sfinae
#if !defined(__cpp_lib_shared_ptr_arrays)
@@ -112,7 +112,7 @@
# define __cpp_lib_shared_ptr_arrays 201611L
# endif
# endif
-#endif /* !defined(__cpp_lib_shared_ptr_arrays) && defined(__glibcxx_want_shared_ptr_arrays) */
+#endif /* !defined(__cpp_lib_shared_ptr_arrays) */
#undef __glibcxx_want_shared_ptr_arrays
#if !defined(__cpp_lib_is_swappable)
@@ -122,7 +122,7 @@
# define __cpp_lib_is_swappable 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_swappable) && defined(__glibcxx_want_is_swappable) */
+#endif /* !defined(__cpp_lib_is_swappable) */
#undef __glibcxx_want_is_swappable
#if !defined(__cpp_lib_void_t)
@@ -132,7 +132,7 @@
# define __cpp_lib_void_t 201411L
# endif
# endif
-#endif /* !defined(__cpp_lib_void_t) && defined(__glibcxx_want_void_t) */
+#endif /* !defined(__cpp_lib_void_t) */
#undef __glibcxx_want_void_t
#if !defined(__cpp_lib_enable_shared_from_this)
@@ -142,7 +142,7 @@
# define __cpp_lib_enable_shared_from_this 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_enable_shared_from_this) && defined(__glibcxx_want_enable_shared_from_this) */
+#endif /* !defined(__cpp_lib_enable_shared_from_this) */
#undef __glibcxx_want_enable_shared_from_this
#if !defined(__cpp_lib_math_spec_funcs)
@@ -152,7 +152,7 @@
# define __STDCPP_MATH_SPEC_FUNCS__ 201003L
# endif
# endif
-#endif /* !defined(__cpp_lib_math_spec_funcs) && defined(__glibcxx_want_math_spec_funcs) */
+#endif /* !defined(__cpp_lib_math_spec_funcs) */
#undef __glibcxx_want_math_spec_funcs
#if !defined(__cpp_lib_coroutine)
@@ -162,7 +162,7 @@
# define __cpp_lib_coroutine 201902L
# endif
# endif
-#endif /* !defined(__cpp_lib_coroutine) && defined(__glibcxx_want_coroutine) */
+#endif /* !defined(__cpp_lib_coroutine) */
#undef __glibcxx_want_coroutine
#if !defined(__cpp_lib_exchange_function)
@@ -172,7 +172,7 @@
# define __cpp_lib_exchange_function 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_exchange_function) && defined(__glibcxx_want_exchange_function) */
+#endif /* !defined(__cpp_lib_exchange_function) */
#undef __glibcxx_want_exchange_function
#if !defined(__cpp_lib_integer_sequence)
@@ -182,7 +182,7 @@
# define __cpp_lib_integer_sequence 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_integer_sequence) && defined(__glibcxx_want_integer_sequence) */
+#endif /* !defined(__cpp_lib_integer_sequence) */
#undef __glibcxx_want_integer_sequence
#if !defined(__cpp_lib_integral_constant_callable)
@@ -192,7 +192,7 @@
# define __cpp_lib_integral_constant_callable 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_integral_constant_callable) && defined(__glibcxx_want_integral_constant_callable) */
+#endif /* !defined(__cpp_lib_integral_constant_callable) */
#undef __glibcxx_want_integral_constant_callable
#if !defined(__cpp_lib_is_final)
@@ -202,7 +202,7 @@
# define __cpp_lib_is_final 201402L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_final) && defined(__glibcxx_want_is_final) */
+#endif /* !defined(__cpp_lib_is_final) */
#undef __glibcxx_want_is_final
#if !defined(__cpp_lib_make_reverse_iterator)
@@ -212,7 +212,7 @@
# define __cpp_lib_make_reverse_iterator 201402L
# endif
# endif
-#endif /* !defined(__cpp_lib_make_reverse_iterator) && defined(__glibcxx_want_make_reverse_iterator) */
+#endif /* !defined(__cpp_lib_make_reverse_iterator) */
#undef __glibcxx_want_make_reverse_iterator
#if !defined(__cpp_lib_null_iterators)
@@ -222,7 +222,7 @@
# define __cpp_lib_null_iterators 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_null_iterators) && defined(__glibcxx_want_null_iterators) */
+#endif /* !defined(__cpp_lib_null_iterators) */
#undef __glibcxx_want_null_iterators
#if !defined(__cpp_lib_transformation_trait_aliases)
@@ -232,7 +232,7 @@
# define __cpp_lib_transformation_trait_aliases 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_transformation_trait_aliases) && defined(__glibcxx_want_transformation_trait_aliases) */
+#endif /* !defined(__cpp_lib_transformation_trait_aliases) */
#undef __glibcxx_want_transformation_trait_aliases
#if !defined(__cpp_lib_transparent_operators)
@@ -242,7 +242,7 @@
# define __cpp_lib_transparent_operators 201510L
# endif
# endif
-#endif /* !defined(__cpp_lib_transparent_operators) && defined(__glibcxx_want_transparent_operators) */
+#endif /* !defined(__cpp_lib_transparent_operators) */
#undef __glibcxx_want_transparent_operators
#if !defined(__cpp_lib_tuple_element_t)
@@ -252,7 +252,7 @@
# define __cpp_lib_tuple_element_t 201402L
# endif
# endif
-#endif /* !defined(__cpp_lib_tuple_element_t) && defined(__glibcxx_want_tuple_element_t) */
+#endif /* !defined(__cpp_lib_tuple_element_t) */
#undef __glibcxx_want_tuple_element_t
#if !defined(__cpp_lib_tuples_by_type)
@@ -262,7 +262,7 @@
# define __cpp_lib_tuples_by_type 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_tuples_by_type) && defined(__glibcxx_want_tuples_by_type) */
+#endif /* !defined(__cpp_lib_tuples_by_type) */
#undef __glibcxx_want_tuples_by_type
#if !defined(__cpp_lib_robust_nonmodifying_seq_ops)
@@ -272,7 +272,7 @@
# define __cpp_lib_robust_nonmodifying_seq_ops 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_robust_nonmodifying_seq_ops) && defined(__glibcxx_want_robust_nonmodifying_seq_ops) */
+#endif /* !defined(__cpp_lib_robust_nonmodifying_seq_ops) */
#undef __glibcxx_want_robust_nonmodifying_seq_ops
#if !defined(__cpp_lib_to_chars)
@@ -287,7 +287,7 @@
# define __cpp_lib_to_chars 201611L
# endif
# endif
-#endif /* !defined(__cpp_lib_to_chars) && defined(__glibcxx_want_to_chars) */
+#endif /* !defined(__cpp_lib_to_chars) */
#undef __glibcxx_want_to_chars
#if !defined(__cpp_lib_chrono_udls)
@@ -297,7 +297,7 @@
# define __cpp_lib_chrono_udls 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_chrono_udls) && defined(__glibcxx_want_chrono_udls) */
+#endif /* !defined(__cpp_lib_chrono_udls) */
#undef __glibcxx_want_chrono_udls
#if !defined(__cpp_lib_complex_udls)
@@ -307,7 +307,7 @@
# define __cpp_lib_complex_udls 201309L
# endif
# endif
-#endif /* !defined(__cpp_lib_complex_udls) && defined(__glibcxx_want_complex_udls) */
+#endif /* !defined(__cpp_lib_complex_udls) */
#undef __glibcxx_want_complex_udls
#if !defined(__cpp_lib_generic_associative_lookup)
@@ -317,7 +317,7 @@
# define __cpp_lib_generic_associative_lookup 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_generic_associative_lookup) && defined(__glibcxx_want_generic_associative_lookup) */
+#endif /* !defined(__cpp_lib_generic_associative_lookup) */
#undef __glibcxx_want_generic_associative_lookup
#if !defined(__cpp_lib_make_unique)
@@ -327,7 +327,7 @@
# define __cpp_lib_make_unique 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_make_unique) && defined(__glibcxx_want_make_unique) */
+#endif /* !defined(__cpp_lib_make_unique) */
#undef __glibcxx_want_make_unique
#if !defined(__cpp_lib_quoted_string_io)
@@ -337,7 +337,7 @@
# define __cpp_lib_quoted_string_io 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_quoted_string_io) && defined(__glibcxx_want_quoted_string_io) */
+#endif /* !defined(__cpp_lib_quoted_string_io) */
#undef __glibcxx_want_quoted_string_io
#if !defined(__cpp_lib_shared_timed_mutex)
@@ -347,7 +347,7 @@
# define __cpp_lib_shared_timed_mutex 201402L
# endif
# endif
-#endif /* !defined(__cpp_lib_shared_timed_mutex) && defined(__glibcxx_want_shared_timed_mutex) */
+#endif /* !defined(__cpp_lib_shared_timed_mutex) */
#undef __glibcxx_want_shared_timed_mutex
#if !defined(__cpp_lib_string_udls)
@@ -357,7 +357,7 @@
# define __cpp_lib_string_udls 201304L
# endif
# endif
-#endif /* !defined(__cpp_lib_string_udls) && defined(__glibcxx_want_string_udls) */
+#endif /* !defined(__cpp_lib_string_udls) */
#undef __glibcxx_want_string_udls
#if !defined(__cpp_lib_addressof_constexpr)
@@ -367,7 +367,7 @@
# define __cpp_lib_addressof_constexpr 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_addressof_constexpr) && defined(__glibcxx_want_addressof_constexpr) */
+#endif /* !defined(__cpp_lib_addressof_constexpr) */
#undef __glibcxx_want_addressof_constexpr
#if !defined(__cpp_lib_any)
@@ -377,7 +377,7 @@
# define __cpp_lib_any 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_any) && defined(__glibcxx_want_any) */
+#endif /* !defined(__cpp_lib_any) */
#undef __glibcxx_want_any
#if !defined(__cpp_lib_apply)
@@ -387,7 +387,7 @@
# define __cpp_lib_apply 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_apply) && defined(__glibcxx_want_apply) */
+#endif /* !defined(__cpp_lib_apply) */
#undef __glibcxx_want_apply
#if !defined(__cpp_lib_as_const)
@@ -397,7 +397,7 @@
# define __cpp_lib_as_const 201510L
# endif
# endif
-#endif /* !defined(__cpp_lib_as_const) && defined(__glibcxx_want_as_const) */
+#endif /* !defined(__cpp_lib_as_const) */
#undef __glibcxx_want_as_const
#if !defined(__cpp_lib_atomic_is_always_lock_free)
@@ -407,7 +407,7 @@
# define __cpp_lib_atomic_is_always_lock_free 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_atomic_is_always_lock_free) && defined(__glibcxx_want_atomic_is_always_lock_free) */
+#endif /* !defined(__cpp_lib_atomic_is_always_lock_free) */
#undef __glibcxx_want_atomic_is_always_lock_free
#if !defined(__cpp_lib_bool_constant)
@@ -417,7 +417,7 @@
# define __cpp_lib_bool_constant 201505L
# endif
# endif
-#endif /* !defined(__cpp_lib_bool_constant) && defined(__glibcxx_want_bool_constant) */
+#endif /* !defined(__cpp_lib_bool_constant) */
#undef __glibcxx_want_bool_constant
#if !defined(__cpp_lib_byte)
@@ -427,9 +427,19 @@
# define __cpp_lib_byte 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_byte) && defined(__glibcxx_want_byte) */
+#endif /* !defined(__cpp_lib_byte) */
#undef __glibcxx_want_byte
+#if !defined(__cpp_lib_constant_wrapper)
+# if (__cplusplus > 202302L)
+# define __glibcxx_constant_wrapper 202506L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constant_wrapper)
+# define __cpp_lib_constant_wrapper 202506L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_constant_wrapper) */
+#undef __glibcxx_want_constant_wrapper
+
#if !defined(__cpp_lib_has_unique_object_representations)
# if (__cplusplus >= 201703L) && (defined(_GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP))
# define __glibcxx_has_unique_object_representations 201606L
@@ -437,7 +447,7 @@
# define __cpp_lib_has_unique_object_representations 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_has_unique_object_representations) && defined(__glibcxx_want_has_unique_object_representations) */
+#endif /* !defined(__cpp_lib_has_unique_object_representations) */
#undef __glibcxx_want_has_unique_object_representations
#if !defined(__cpp_lib_hardware_interference_size)
@@ -447,7 +457,7 @@
# define __cpp_lib_hardware_interference_size 201703L
# endif
# endif
-#endif /* !defined(__cpp_lib_hardware_interference_size) && defined(__glibcxx_want_hardware_interference_size) */
+#endif /* !defined(__cpp_lib_hardware_interference_size) */
#undef __glibcxx_want_hardware_interference_size
#if !defined(__cpp_lib_invoke)
@@ -457,7 +467,7 @@
# define __cpp_lib_invoke 201411L
# endif
# endif
-#endif /* !defined(__cpp_lib_invoke) && defined(__glibcxx_want_invoke) */
+#endif /* !defined(__cpp_lib_invoke) */
#undef __glibcxx_want_invoke
#if !defined(__cpp_lib_is_aggregate)
@@ -467,7 +477,7 @@
# define __cpp_lib_is_aggregate 201703L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_aggregate) && defined(__glibcxx_want_is_aggregate) */
+#endif /* !defined(__cpp_lib_is_aggregate) */
#undef __glibcxx_want_is_aggregate
#if !defined(__cpp_lib_is_invocable)
@@ -477,7 +487,7 @@
# define __cpp_lib_is_invocable 201703L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_invocable) && defined(__glibcxx_want_is_invocable) */
+#endif /* !defined(__cpp_lib_is_invocable) */
#undef __glibcxx_want_is_invocable
#if !defined(__cpp_lib_launder)
@@ -487,7 +497,7 @@
# define __cpp_lib_launder 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_launder) && defined(__glibcxx_want_launder) */
+#endif /* !defined(__cpp_lib_launder) */
#undef __glibcxx_want_launder
#if !defined(__cpp_lib_logical_traits)
@@ -497,7 +507,7 @@
# define __cpp_lib_logical_traits 201510L
# endif
# endif
-#endif /* !defined(__cpp_lib_logical_traits) && defined(__glibcxx_want_logical_traits) */
+#endif /* !defined(__cpp_lib_logical_traits) */
#undef __glibcxx_want_logical_traits
#if !defined(__cpp_lib_make_from_tuple)
@@ -507,17 +517,22 @@
# define __cpp_lib_make_from_tuple 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_make_from_tuple) && defined(__glibcxx_want_make_from_tuple) */
+#endif /* !defined(__cpp_lib_make_from_tuple) */
#undef __glibcxx_want_make_from_tuple
#if !defined(__cpp_lib_not_fn)
-# if (__cplusplus >= 201703L)
+# if (__cplusplus > 202302L)
+# define __glibcxx_not_fn 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_not_fn)
+# define __cpp_lib_not_fn 202306L
+# endif
+# elif (__cplusplus >= 201703L)
# define __glibcxx_not_fn 201603L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_not_fn)
# define __cpp_lib_not_fn 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_not_fn) && defined(__glibcxx_want_not_fn) */
+#endif /* !defined(__cpp_lib_not_fn) */
#undef __glibcxx_want_not_fn
#if !defined(__cpp_lib_type_trait_variable_templates)
@@ -527,7 +542,7 @@
# define __cpp_lib_type_trait_variable_templates 201510L
# endif
# endif
-#endif /* !defined(__cpp_lib_type_trait_variable_templates) && defined(__glibcxx_want_type_trait_variable_templates) */
+#endif /* !defined(__cpp_lib_type_trait_variable_templates) */
#undef __glibcxx_want_type_trait_variable_templates
#if !defined(__cpp_lib_variant)
@@ -547,7 +562,7 @@
# define __cpp_lib_variant 202102L
# endif
# endif
-#endif /* !defined(__cpp_lib_variant) && defined(__glibcxx_want_variant) */
+#endif /* !defined(__cpp_lib_variant) */
#undef __glibcxx_want_variant
#if !defined(__cpp_lib_lcm)
@@ -557,7 +572,7 @@
# define __cpp_lib_lcm 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_lcm) && defined(__glibcxx_want_lcm) */
+#endif /* !defined(__cpp_lib_lcm) */
#undef __glibcxx_want_lcm
#if !defined(__cpp_lib_gcd)
@@ -567,7 +582,7 @@
# define __cpp_lib_gcd 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_gcd) && defined(__glibcxx_want_gcd) */
+#endif /* !defined(__cpp_lib_gcd) */
#undef __glibcxx_want_gcd
#if !defined(__cpp_lib_gcd_lcm)
@@ -577,7 +592,7 @@
# define __cpp_lib_gcd_lcm 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_gcd_lcm) && defined(__glibcxx_want_gcd_lcm) */
+#endif /* !defined(__cpp_lib_gcd_lcm) */
#undef __glibcxx_want_gcd_lcm
#if !defined(__cpp_lib_raw_memory_algorithms)
@@ -592,7 +607,7 @@
# define __cpp_lib_raw_memory_algorithms 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_raw_memory_algorithms) && defined(__glibcxx_want_raw_memory_algorithms) */
+#endif /* !defined(__cpp_lib_raw_memory_algorithms) */
#undef __glibcxx_want_raw_memory_algorithms
#if !defined(__cpp_lib_array_constexpr)
@@ -607,7 +622,7 @@
# define __cpp_lib_array_constexpr 201803L
# endif
# endif
-#endif /* !defined(__cpp_lib_array_constexpr) && defined(__glibcxx_want_array_constexpr) */
+#endif /* !defined(__cpp_lib_array_constexpr) */
#undef __glibcxx_want_array_constexpr
#if !defined(__cpp_lib_nonmember_container_access)
@@ -617,7 +632,7 @@
# define __cpp_lib_nonmember_container_access 201411L
# endif
# endif
-#endif /* !defined(__cpp_lib_nonmember_container_access) && defined(__glibcxx_want_nonmember_container_access) */
+#endif /* !defined(__cpp_lib_nonmember_container_access) */
#undef __glibcxx_want_nonmember_container_access
#if !defined(__cpp_lib_clamp)
@@ -627,7 +642,7 @@
# define __cpp_lib_clamp 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_clamp) && defined(__glibcxx_want_clamp) */
+#endif /* !defined(__cpp_lib_clamp) */
#undef __glibcxx_want_clamp
#if !defined(__cpp_lib_sample)
@@ -637,7 +652,7 @@
# define __cpp_lib_sample 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_sample) && defined(__glibcxx_want_sample) */
+#endif /* !defined(__cpp_lib_sample) */
#undef __glibcxx_want_sample
#if !defined(__cpp_lib_boyer_moore_searcher)
@@ -647,11 +662,16 @@
# define __cpp_lib_boyer_moore_searcher 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_boyer_moore_searcher) && defined(__glibcxx_want_boyer_moore_searcher) */
+#endif /* !defined(__cpp_lib_boyer_moore_searcher) */
#undef __glibcxx_want_boyer_moore_searcher
#if !defined(__cpp_lib_chrono)
-# if (__cplusplus >= 202002L) && _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED
+# if (__cplusplus > 202302L) && _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED
+# define __glibcxx_chrono 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono)
+# define __cpp_lib_chrono 202306L
+# endif
+# elif (__cplusplus >= 202002L) && _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED
# define __glibcxx_chrono 201907L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono)
# define __cpp_lib_chrono 201907L
@@ -662,9 +682,22 @@
# define __cpp_lib_chrono 201611L
# endif
# endif
-#endif /* !defined(__cpp_lib_chrono) && defined(__glibcxx_want_chrono) */
+#endif /* !defined(__cpp_lib_chrono) */
#undef __glibcxx_want_chrono
+#if !defined(__cpp_lib_chrono_cxx20)
+# if (__cplusplus > 202302L)
+# define __glibcxx_chrono_cxx20 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono_cxx20)
+# endif
+# elif (__cplusplus >= 202002L)
+# define __glibcxx_chrono_cxx20 201800L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono_cxx20)
+# endif
+# endif
+#endif /* !defined(__cpp_lib_chrono_cxx20) */
+#undef __glibcxx_want_chrono_cxx20
+
#if !defined(__cpp_lib_execution)
# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED
# define __glibcxx_execution 201902L
@@ -672,7 +705,7 @@
# define __cpp_lib_execution 201902L
# endif
# endif
-#endif /* !defined(__cpp_lib_execution) && defined(__glibcxx_want_execution) */
+#endif /* !defined(__cpp_lib_execution) */
#undef __glibcxx_want_execution
#if !defined(__cpp_lib_filesystem)
@@ -682,7 +715,7 @@
# define __cpp_lib_filesystem 201703L
# endif
# endif
-#endif /* !defined(__cpp_lib_filesystem) && defined(__glibcxx_want_filesystem) */
+#endif /* !defined(__cpp_lib_filesystem) */
#undef __glibcxx_want_filesystem
#if !defined(__cpp_lib_hypot)
@@ -692,7 +725,7 @@
# define __cpp_lib_hypot 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_hypot) && defined(__glibcxx_want_hypot) */
+#endif /* !defined(__cpp_lib_hypot) */
#undef __glibcxx_want_hypot
#if !defined(__cpp_lib_map_try_emplace)
@@ -702,7 +735,7 @@
# define __cpp_lib_map_try_emplace 201411L
# endif
# endif
-#endif /* !defined(__cpp_lib_map_try_emplace) && defined(__glibcxx_want_map_try_emplace) */
+#endif /* !defined(__cpp_lib_map_try_emplace) */
#undef __glibcxx_want_map_try_emplace
#if !defined(__cpp_lib_math_special_functions)
@@ -712,7 +745,7 @@
# define __cpp_lib_math_special_functions 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_math_special_functions) && defined(__glibcxx_want_math_special_functions) */
+#endif /* !defined(__cpp_lib_math_special_functions) */
#undef __glibcxx_want_math_special_functions
#if !defined(__cpp_lib_memory_resource)
@@ -727,7 +760,7 @@
# define __cpp_lib_memory_resource 1L
# endif
# endif
-#endif /* !defined(__cpp_lib_memory_resource) && defined(__glibcxx_want_memory_resource) */
+#endif /* !defined(__cpp_lib_memory_resource) */
#undef __glibcxx_want_memory_resource
#if !defined(__cpp_lib_node_extract)
@@ -737,7 +770,7 @@
# define __cpp_lib_node_extract 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_node_extract) && defined(__glibcxx_want_node_extract) */
+#endif /* !defined(__cpp_lib_node_extract) */
#undef __glibcxx_want_node_extract
#if !defined(__cpp_lib_parallel_algorithm)
@@ -747,17 +780,17 @@
# define __cpp_lib_parallel_algorithm 201603L
# endif
# endif
-#endif /* !defined(__cpp_lib_parallel_algorithm) && defined(__glibcxx_want_parallel_algorithm) */
+#endif /* !defined(__cpp_lib_parallel_algorithm) */
#undef __glibcxx_want_parallel_algorithm
#if !defined(__cpp_lib_scoped_lock)
-# if (__cplusplus >= 201703L) && defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED
+# if (__cplusplus >= 201703L)
# define __glibcxx_scoped_lock 201703L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_scoped_lock)
# define __cpp_lib_scoped_lock 201703L
# endif
# endif
-#endif /* !defined(__cpp_lib_scoped_lock) && defined(__glibcxx_want_scoped_lock) */
+#endif /* !defined(__cpp_lib_scoped_lock) */
#undef __glibcxx_want_scoped_lock
#if !defined(__cpp_lib_shared_mutex)
@@ -767,7 +800,7 @@
# define __cpp_lib_shared_mutex 201505L
# endif
# endif
-#endif /* !defined(__cpp_lib_shared_mutex) && defined(__glibcxx_want_shared_mutex) */
+#endif /* !defined(__cpp_lib_shared_mutex) */
#undef __glibcxx_want_shared_mutex
#if !defined(__cpp_lib_shared_ptr_weak_type)
@@ -777,7 +810,7 @@
# define __cpp_lib_shared_ptr_weak_type 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_shared_ptr_weak_type) && defined(__glibcxx_want_shared_ptr_weak_type) */
+#endif /* !defined(__cpp_lib_shared_ptr_weak_type) */
#undef __glibcxx_want_shared_ptr_weak_type
#if !defined(__cpp_lib_string_view)
@@ -792,7 +825,7 @@
# define __cpp_lib_string_view 201803L
# endif
# endif
-#endif /* !defined(__cpp_lib_string_view) && defined(__glibcxx_want_string_view) */
+#endif /* !defined(__cpp_lib_string_view) */
#undef __glibcxx_want_string_view
#if !defined(__cpp_lib_unordered_map_try_emplace)
@@ -802,7 +835,7 @@
# define __cpp_lib_unordered_map_try_emplace 201411L
# endif
# endif
-#endif /* !defined(__cpp_lib_unordered_map_try_emplace) && defined(__glibcxx_want_unordered_map_try_emplace) */
+#endif /* !defined(__cpp_lib_unordered_map_try_emplace) */
#undef __glibcxx_want_unordered_map_try_emplace
#if !defined(__cpp_lib_assume_aligned)
@@ -812,9 +845,19 @@
# define __cpp_lib_assume_aligned 201811L
# endif
# endif
-#endif /* !defined(__cpp_lib_assume_aligned) && defined(__glibcxx_want_assume_aligned) */
+#endif /* !defined(__cpp_lib_assume_aligned) */
#undef __glibcxx_want_assume_aligned
+#if !defined(__cpp_lib_is_sufficiently_aligned)
+# if (__cplusplus > 202302L)
+# define __glibcxx_is_sufficiently_aligned 202411L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_sufficiently_aligned)
+# define __cpp_lib_is_sufficiently_aligned 202411L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_is_sufficiently_aligned) */
+#undef __glibcxx_want_is_sufficiently_aligned
+
#if !defined(__cpp_lib_atomic_flag_test)
# if (__cplusplus >= 202002L)
# define __glibcxx_atomic_flag_test 201907L
@@ -822,7 +865,7 @@
# define __cpp_lib_atomic_flag_test 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_atomic_flag_test) && defined(__glibcxx_want_atomic_flag_test) */
+#endif /* !defined(__cpp_lib_atomic_flag_test) */
#undef __glibcxx_want_atomic_flag_test
#if !defined(__cpp_lib_atomic_float)
@@ -832,7 +875,7 @@
# define __cpp_lib_atomic_float 201711L
# endif
# endif
-#endif /* !defined(__cpp_lib_atomic_float) && defined(__glibcxx_want_atomic_float) */
+#endif /* !defined(__cpp_lib_atomic_float) */
#undef __glibcxx_want_atomic_float
#if !defined(__cpp_lib_atomic_lock_free_type_aliases)
@@ -842,17 +885,22 @@
# define __cpp_lib_atomic_lock_free_type_aliases 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_atomic_lock_free_type_aliases) && defined(__glibcxx_want_atomic_lock_free_type_aliases) */
+#endif /* !defined(__cpp_lib_atomic_lock_free_type_aliases) */
#undef __glibcxx_want_atomic_lock_free_type_aliases
#if !defined(__cpp_lib_atomic_ref)
-# if (__cplusplus >= 202002L)
+# if (__cplusplus > 202302L)
+# define __glibcxx_atomic_ref 202411L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_ref)
+# define __cpp_lib_atomic_ref 202411L
+# endif
+# elif (__cplusplus >= 202002L)
# define __glibcxx_atomic_ref 201806L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_ref)
# define __cpp_lib_atomic_ref 201806L
# endif
# endif
-#endif /* !defined(__cpp_lib_atomic_ref) && defined(__glibcxx_want_atomic_ref) */
+#endif /* !defined(__cpp_lib_atomic_ref) */
#undef __glibcxx_want_atomic_ref
#if !defined(__cpp_lib_atomic_value_initialization)
@@ -862,27 +910,37 @@
# define __cpp_lib_atomic_value_initialization 201911L
# endif
# endif
-#endif /* !defined(__cpp_lib_atomic_value_initialization) && defined(__glibcxx_want_atomic_value_initialization) */
+#endif /* !defined(__cpp_lib_atomic_value_initialization) */
#undef __glibcxx_want_atomic_value_initialization
#if !defined(__cpp_lib_bind_front)
-# if (__cplusplus >= 202002L)
+# if (__cplusplus > 202302L)
+# define __glibcxx_bind_front 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_front)
+# define __cpp_lib_bind_front 202306L
+# endif
+# elif (__cplusplus >= 202002L)
# define __glibcxx_bind_front 201907L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_front)
# define __cpp_lib_bind_front 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_bind_front) && defined(__glibcxx_want_bind_front) */
+#endif /* !defined(__cpp_lib_bind_front) */
#undef __glibcxx_want_bind_front
#if !defined(__cpp_lib_bind_back)
-# if (__cplusplus >= 202100L) && (__cpp_explicit_this_parameter)
+# if (__cplusplus > 202302L)
+# define __glibcxx_bind_back 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_back)
+# define __cpp_lib_bind_back 202306L
+# endif
+# elif (__cplusplus >= 202100L) && (__cpp_explicit_this_parameter)
# define __glibcxx_bind_back 202202L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_back)
# define __cpp_lib_bind_back 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_bind_back) && defined(__glibcxx_want_bind_back) */
+#endif /* !defined(__cpp_lib_bind_back) */
#undef __glibcxx_want_bind_back
#if !defined(__cpp_lib_starts_ends_with)
@@ -892,7 +950,7 @@
# define __cpp_lib_starts_ends_with 201711L
# endif
# endif
-#endif /* !defined(__cpp_lib_starts_ends_with) && defined(__glibcxx_want_starts_ends_with) */
+#endif /* !defined(__cpp_lib_starts_ends_with) */
#undef __glibcxx_want_starts_ends_with
#if !defined(__cpp_lib_bit_cast)
@@ -902,7 +960,7 @@
# define __cpp_lib_bit_cast 201806L
# endif
# endif
-#endif /* !defined(__cpp_lib_bit_cast) && defined(__glibcxx_want_bit_cast) */
+#endif /* !defined(__cpp_lib_bit_cast) */
#undef __glibcxx_want_bit_cast
#if !defined(__cpp_lib_bitops)
@@ -912,7 +970,7 @@
# define __cpp_lib_bitops 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_bitops) && defined(__glibcxx_want_bitops) */
+#endif /* !defined(__cpp_lib_bitops) */
#undef __glibcxx_want_bitops
#if !defined(__cpp_lib_bounded_array_traits)
@@ -922,21 +980,26 @@
# define __cpp_lib_bounded_array_traits 201902L
# endif
# endif
-#endif /* !defined(__cpp_lib_bounded_array_traits) && defined(__glibcxx_want_bounded_array_traits) */
+#endif /* !defined(__cpp_lib_bounded_array_traits) */
#undef __glibcxx_want_bounded_array_traits
#if !defined(__cpp_lib_concepts)
# if (__cplusplus >= 202002L) && (__cpp_concepts >= 201907L)
-# define __glibcxx_concepts 202002L
+# define __glibcxx_concepts 202207L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_concepts)
-# define __cpp_lib_concepts 202002L
+# define __cpp_lib_concepts 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_concepts) && defined(__glibcxx_want_concepts) */
+#endif /* !defined(__cpp_lib_concepts) */
#undef __glibcxx_want_concepts
#if !defined(__cpp_lib_optional)
-# if (__cplusplus >= 202100L) && (__glibcxx_concepts)
+# if (__cplusplus > 202302L) && (__glibcxx_concepts)
+# define __glibcxx_optional 202506L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_optional)
+# define __cpp_lib_optional 202506L
+# endif
+# elif (__cplusplus >= 202100L) && (__glibcxx_concepts)
# define __glibcxx_optional 202110L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_optional)
# define __cpp_lib_optional 202110L
@@ -952,9 +1015,19 @@
# define __cpp_lib_optional 201606L
# endif
# endif
-#endif /* !defined(__cpp_lib_optional) && defined(__glibcxx_want_optional) */
+#endif /* !defined(__cpp_lib_optional) */
#undef __glibcxx_want_optional
+#if !defined(__cpp_lib_optional_range_support)
+# if (__cplusplus > 202302L)
+# define __glibcxx_optional_range_support 202406L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_optional_range_support)
+# define __cpp_lib_optional_range_support 202406L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_optional_range_support) */
+#undef __glibcxx_want_optional_range_support
+
#if !defined(__cpp_lib_destroying_delete)
# if (__cplusplus >= 202002L) && (__cpp_impl_destroying_delete)
# define __glibcxx_destroying_delete 201806L
@@ -962,7 +1035,7 @@
# define __cpp_lib_destroying_delete 201806L
# endif
# endif
-#endif /* !defined(__cpp_lib_destroying_delete) && defined(__glibcxx_want_destroying_delete) */
+#endif /* !defined(__cpp_lib_destroying_delete) */
#undef __glibcxx_want_destroying_delete
#if !defined(__cpp_lib_constexpr_string_view)
@@ -972,7 +1045,7 @@
# define __cpp_lib_constexpr_string_view 201811L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_string_view) && defined(__glibcxx_want_constexpr_string_view) */
+#endif /* !defined(__cpp_lib_constexpr_string_view) */
#undef __glibcxx_want_constexpr_string_view
#if !defined(__cpp_lib_endian)
@@ -982,7 +1055,7 @@
# define __cpp_lib_endian 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_endian) && defined(__glibcxx_want_endian) */
+#endif /* !defined(__cpp_lib_endian) */
#undef __glibcxx_want_endian
#if !defined(__cpp_lib_int_pow2)
@@ -992,7 +1065,7 @@
# define __cpp_lib_int_pow2 202002L
# endif
# endif
-#endif /* !defined(__cpp_lib_int_pow2) && defined(__glibcxx_want_int_pow2) */
+#endif /* !defined(__cpp_lib_int_pow2) */
#undef __glibcxx_want_int_pow2
#if !defined(__cpp_lib_integer_comparison_functions)
@@ -1002,7 +1075,7 @@
# define __cpp_lib_integer_comparison_functions 202002L
# endif
# endif
-#endif /* !defined(__cpp_lib_integer_comparison_functions) && defined(__glibcxx_want_integer_comparison_functions) */
+#endif /* !defined(__cpp_lib_integer_comparison_functions) */
#undef __glibcxx_want_integer_comparison_functions
#if !defined(__cpp_lib_is_constant_evaluated)
@@ -1012,7 +1085,7 @@
# define __cpp_lib_is_constant_evaluated 201811L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_constant_evaluated) && defined(__glibcxx_want_is_constant_evaluated) */
+#endif /* !defined(__cpp_lib_is_constant_evaluated) */
#undef __glibcxx_want_is_constant_evaluated
#if !defined(__cpp_lib_constexpr_char_traits)
@@ -1027,7 +1100,7 @@
# define __cpp_lib_constexpr_char_traits 201611L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_char_traits) && defined(__glibcxx_want_constexpr_char_traits) */
+#endif /* !defined(__cpp_lib_constexpr_char_traits) */
#undef __glibcxx_want_constexpr_char_traits
#if !defined(__cpp_lib_is_layout_compatible)
@@ -1037,7 +1110,7 @@
# define __cpp_lib_is_layout_compatible 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_layout_compatible) && defined(__glibcxx_want_is_layout_compatible) */
+#endif /* !defined(__cpp_lib_is_layout_compatible) */
#undef __glibcxx_want_is_layout_compatible
#if !defined(__cpp_lib_is_nothrow_convertible)
@@ -1047,7 +1120,7 @@
# define __cpp_lib_is_nothrow_convertible 201806L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_nothrow_convertible) && defined(__glibcxx_want_is_nothrow_convertible) */
+#endif /* !defined(__cpp_lib_is_nothrow_convertible) */
#undef __glibcxx_want_is_nothrow_convertible
#if !defined(__cpp_lib_is_pointer_interconvertible)
@@ -1057,7 +1130,7 @@
# define __cpp_lib_is_pointer_interconvertible 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_pointer_interconvertible) && defined(__glibcxx_want_is_pointer_interconvertible) */
+#endif /* !defined(__cpp_lib_is_pointer_interconvertible) */
#undef __glibcxx_want_is_pointer_interconvertible
#if !defined(__cpp_lib_math_constants)
@@ -1067,17 +1140,16 @@
# define __cpp_lib_math_constants 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_math_constants) && defined(__glibcxx_want_math_constants) */
+#endif /* !defined(__cpp_lib_math_constants) */
#undef __glibcxx_want_math_constants
#if !defined(__cpp_lib_make_obj_using_allocator)
# if (__cplusplus >= 202002L) && (__cpp_concepts)
# define __glibcxx_make_obj_using_allocator 201811L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_make_obj_using_allocator)
-# define __cpp_lib_make_obj_using_allocator 201811L
# endif
# endif
-#endif /* !defined(__cpp_lib_make_obj_using_allocator) && defined(__glibcxx_want_make_obj_using_allocator) */
+#endif /* !defined(__cpp_lib_make_obj_using_allocator) */
#undef __glibcxx_want_make_obj_using_allocator
#if !defined(__cpp_lib_remove_cvref)
@@ -1087,7 +1159,7 @@
# define __cpp_lib_remove_cvref 201711L
# endif
# endif
-#endif /* !defined(__cpp_lib_remove_cvref) && defined(__glibcxx_want_remove_cvref) */
+#endif /* !defined(__cpp_lib_remove_cvref) */
#undef __glibcxx_want_remove_cvref
#if !defined(__cpp_lib_source_location)
@@ -1097,7 +1169,7 @@
# define __cpp_lib_source_location 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_source_location) && defined(__glibcxx_want_source_location) */
+#endif /* !defined(__cpp_lib_source_location) */
#undef __glibcxx_want_source_location
#if !defined(__cpp_lib_span)
@@ -1112,9 +1184,53 @@
# define __cpp_lib_span 202002L
# endif
# endif
-#endif /* !defined(__cpp_lib_span) && defined(__glibcxx_want_span) */
+#endif /* !defined(__cpp_lib_span) */
#undef __glibcxx_want_span
+#if !defined(__cpp_lib_mdspan)
+# if (__cplusplus > 202302L)
+# define __glibcxx_mdspan 202406L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_mdspan)
+# define __cpp_lib_mdspan 202406L
+# endif
+# elif (__cplusplus >= 202100L)
+# define __glibcxx_mdspan 202207L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_mdspan)
+# define __cpp_lib_mdspan 202207L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_mdspan) */
+#undef __glibcxx_want_mdspan
+
+#if !defined(__cpp_lib_aligned_accessor)
+# if (__cplusplus > 202302L) && (__glibcxx_assume_aligned && __glibcxx_is_sufficiently_aligned)
+# define __glibcxx_aligned_accessor 202411L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_aligned_accessor)
+# define __cpp_lib_aligned_accessor 202411L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_aligned_accessor) */
+#undef __glibcxx_want_aligned_accessor
+
+#if !defined(__cpp_lib_padded_layouts)
+# if (__cplusplus > 202302L)
+# define __glibcxx_padded_layouts 202403L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_padded_layouts)
+# endif
+# endif
+#endif /* !defined(__cpp_lib_padded_layouts) */
+#undef __glibcxx_want_padded_layouts
+
+#if !defined(__cpp_lib_submdspan)
+# if (__cplusplus > 202302L) && (__glibcxx_constant_wrapper >= 202506L)
+# define __glibcxx_submdspan 202411L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_submdspan)
+# define __cpp_lib_submdspan 202411L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_submdspan) */
+#undef __glibcxx_want_submdspan
+
#if !defined(__cpp_lib_ssize)
# if (__cplusplus >= 202002L)
# define __glibcxx_ssize 201902L
@@ -1122,7 +1238,7 @@
# define __cpp_lib_ssize 201902L
# endif
# endif
-#endif /* !defined(__cpp_lib_ssize) && defined(__glibcxx_want_ssize) */
+#endif /* !defined(__cpp_lib_ssize) */
#undef __glibcxx_want_ssize
#if !defined(__cpp_lib_three_way_comparison)
@@ -1132,7 +1248,7 @@
# define __cpp_lib_three_way_comparison 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_three_way_comparison) && defined(__glibcxx_want_three_way_comparison) */
+#endif /* !defined(__cpp_lib_three_way_comparison) */
#undef __glibcxx_want_three_way_comparison
#if !defined(__cpp_lib_to_address)
@@ -1142,7 +1258,7 @@
# define __cpp_lib_to_address 201711L
# endif
# endif
-#endif /* !defined(__cpp_lib_to_address) && defined(__glibcxx_want_to_address) */
+#endif /* !defined(__cpp_lib_to_address) */
#undef __glibcxx_want_to_address
#if !defined(__cpp_lib_to_array)
@@ -1152,7 +1268,7 @@
# define __cpp_lib_to_array 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_to_array) && defined(__glibcxx_want_to_array) */
+#endif /* !defined(__cpp_lib_to_array) */
#undef __glibcxx_want_to_array
#if !defined(__cpp_lib_type_identity)
@@ -1162,7 +1278,7 @@
# define __cpp_lib_type_identity 201806L
# endif
# endif
-#endif /* !defined(__cpp_lib_type_identity) && defined(__glibcxx_want_type_identity) */
+#endif /* !defined(__cpp_lib_type_identity) */
#undef __glibcxx_want_type_identity
#if !defined(__cpp_lib_unwrap_ref)
@@ -1172,7 +1288,7 @@
# define __cpp_lib_unwrap_ref 201811L
# endif
# endif
-#endif /* !defined(__cpp_lib_unwrap_ref) && defined(__glibcxx_want_unwrap_ref) */
+#endif /* !defined(__cpp_lib_unwrap_ref) */
#undef __glibcxx_want_unwrap_ref
#if !defined(__cpp_lib_constexpr_iterator)
@@ -1182,7 +1298,7 @@
# define __cpp_lib_constexpr_iterator 201811L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_iterator) && defined(__glibcxx_want_constexpr_iterator) */
+#endif /* !defined(__cpp_lib_constexpr_iterator) */
#undef __glibcxx_want_constexpr_iterator
#if !defined(__cpp_lib_interpolate)
@@ -1192,7 +1308,7 @@
# define __cpp_lib_interpolate 201902L
# endif
# endif
-#endif /* !defined(__cpp_lib_interpolate) && defined(__glibcxx_want_interpolate) */
+#endif /* !defined(__cpp_lib_interpolate) */
#undef __glibcxx_want_interpolate
#if !defined(__cpp_lib_constexpr_utility)
@@ -1202,17 +1318,22 @@
# define __cpp_lib_constexpr_utility 201811L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_utility) && defined(__glibcxx_want_constexpr_utility) */
+#endif /* !defined(__cpp_lib_constexpr_utility) */
#undef __glibcxx_want_constexpr_utility
#if !defined(__cpp_lib_shift)
-# if (__cplusplus >= 202002L)
+# if (__cplusplus >= 202100L)
+# define __glibcxx_shift 202202L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_shift)
+# define __cpp_lib_shift 202202L
+# endif
+# elif (__cplusplus >= 202002L)
# define __glibcxx_shift 201806L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_shift)
# define __cpp_lib_shift 201806L
# endif
# endif
-#endif /* !defined(__cpp_lib_shift) && defined(__glibcxx_want_shift) */
+#endif /* !defined(__cpp_lib_shift) */
#undef __glibcxx_want_shift
#if !defined(__cpp_lib_ranges)
@@ -1232,7 +1353,7 @@
# define __cpp_lib_ranges 202110L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges) && defined(__glibcxx_want_ranges) */
+#endif /* !defined(__cpp_lib_ranges) */
#undef __glibcxx_want_ranges
#if !defined(__cpp_lib_constexpr_numeric)
@@ -1242,7 +1363,7 @@
# define __cpp_lib_constexpr_numeric 201911L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_numeric) && defined(__glibcxx_want_constexpr_numeric) */
+#endif /* !defined(__cpp_lib_constexpr_numeric) */
#undef __glibcxx_want_constexpr_numeric
#if !defined(__cpp_lib_constexpr_functional)
@@ -1252,7 +1373,7 @@
# define __cpp_lib_constexpr_functional 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_functional) && defined(__glibcxx_want_constexpr_functional) */
+#endif /* !defined(__cpp_lib_constexpr_functional) */
#undef __glibcxx_want_constexpr_functional
#if !defined(__cpp_lib_constexpr_algorithms)
@@ -1267,7 +1388,7 @@
# define __cpp_lib_constexpr_algorithms 201806L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_algorithms) && defined(__glibcxx_want_constexpr_algorithms) */
+#endif /* !defined(__cpp_lib_constexpr_algorithms) */
#undef __glibcxx_want_constexpr_algorithms
#if !defined(__cpp_lib_constexpr_tuple)
@@ -1277,7 +1398,7 @@
# define __cpp_lib_constexpr_tuple 201811L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_tuple) && defined(__glibcxx_want_constexpr_tuple) */
+#endif /* !defined(__cpp_lib_constexpr_tuple) */
#undef __glibcxx_want_constexpr_tuple
#if !defined(__cpp_lib_constexpr_memory)
@@ -1292,7 +1413,7 @@
# define __cpp_lib_constexpr_memory 201811L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_memory) && defined(__glibcxx_want_constexpr_memory) */
+#endif /* !defined(__cpp_lib_constexpr_memory) */
#undef __glibcxx_want_constexpr_memory
#if !defined(__cpp_lib_atomic_shared_ptr)
@@ -1302,7 +1423,7 @@
# define __cpp_lib_atomic_shared_ptr 201711L
# endif
# endif
-#endif /* !defined(__cpp_lib_atomic_shared_ptr) && defined(__glibcxx_want_atomic_shared_ptr) */
+#endif /* !defined(__cpp_lib_atomic_shared_ptr) */
#undef __glibcxx_want_atomic_shared_ptr
#if !defined(__cpp_lib_atomic_wait)
@@ -1317,7 +1438,7 @@
# define __cpp_lib_atomic_wait 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_atomic_wait) && defined(__glibcxx_want_atomic_wait) */
+#endif /* !defined(__cpp_lib_atomic_wait) */
#undef __glibcxx_want_atomic_wait
#if !defined(__cpp_lib_barrier)
@@ -1327,7 +1448,7 @@
# define __cpp_lib_barrier 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_barrier) && defined(__glibcxx_want_barrier) */
+#endif /* !defined(__cpp_lib_barrier) */
#undef __glibcxx_want_barrier
#if !defined(__cpp_lib_format)
@@ -1342,7 +1463,7 @@
# define __cpp_lib_format 202304L
# endif
# endif
-#endif /* !defined(__cpp_lib_format) && defined(__glibcxx_want_format) */
+#endif /* !defined(__cpp_lib_format) */
#undef __glibcxx_want_format
#if !defined(__cpp_lib_format_uchar)
@@ -1352,7 +1473,7 @@
# define __cpp_lib_format_uchar 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_format_uchar) && defined(__glibcxx_want_format_uchar) */
+#endif /* !defined(__cpp_lib_format_uchar) */
#undef __glibcxx_want_format_uchar
#if !defined(__cpp_lib_constexpr_complex)
@@ -1362,7 +1483,7 @@
# define __cpp_lib_constexpr_complex 201711L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_complex) && defined(__glibcxx_want_constexpr_complex) */
+#endif /* !defined(__cpp_lib_constexpr_complex) */
#undef __glibcxx_want_constexpr_complex
#if !defined(__cpp_lib_constexpr_dynamic_alloc)
@@ -1372,7 +1493,7 @@
# define __cpp_lib_constexpr_dynamic_alloc 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_dynamic_alloc) && defined(__glibcxx_want_constexpr_dynamic_alloc) */
+#endif /* !defined(__cpp_lib_constexpr_dynamic_alloc) */
#undef __glibcxx_want_constexpr_dynamic_alloc
#if !defined(__cpp_lib_constexpr_string)
@@ -1392,7 +1513,7 @@
# define __cpp_lib_constexpr_string 201611L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_string) && defined(__glibcxx_want_constexpr_string) */
+#endif /* !defined(__cpp_lib_constexpr_string) */
#undef __glibcxx_want_constexpr_string
#if !defined(__cpp_lib_constexpr_vector)
@@ -1402,7 +1523,7 @@
# define __cpp_lib_constexpr_vector 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_vector) && defined(__glibcxx_want_constexpr_vector) */
+#endif /* !defined(__cpp_lib_constexpr_vector) */
#undef __glibcxx_want_constexpr_vector
#if !defined(__cpp_lib_constrained_equality)
@@ -1417,7 +1538,7 @@
# define __cpp_lib_constrained_equality 202403L
# endif
# endif
-#endif /* !defined(__cpp_lib_constrained_equality) && defined(__glibcxx_want_constrained_equality) */
+#endif /* !defined(__cpp_lib_constrained_equality) */
#undef __glibcxx_want_constrained_equality
#if !defined(__cpp_lib_erase_if)
@@ -1427,7 +1548,7 @@
# define __cpp_lib_erase_if 202002L
# endif
# endif
-#endif /* !defined(__cpp_lib_erase_if) && defined(__glibcxx_want_erase_if) */
+#endif /* !defined(__cpp_lib_erase_if) */
#undef __glibcxx_want_erase_if
#if !defined(__cpp_lib_generic_unordered_lookup)
@@ -1437,7 +1558,7 @@
# define __cpp_lib_generic_unordered_lookup 201811L
# endif
# endif
-#endif /* !defined(__cpp_lib_generic_unordered_lookup) && defined(__glibcxx_want_generic_unordered_lookup) */
+#endif /* !defined(__cpp_lib_generic_unordered_lookup) */
#undef __glibcxx_want_generic_unordered_lookup
#if !defined(__cpp_lib_jthread)
@@ -1447,7 +1568,7 @@
# define __cpp_lib_jthread 201911L
# endif
# endif
-#endif /* !defined(__cpp_lib_jthread) && defined(__glibcxx_want_jthread) */
+#endif /* !defined(__cpp_lib_jthread) */
#undef __glibcxx_want_jthread
#if !defined(__cpp_lib_latch)
@@ -1457,7 +1578,7 @@
# define __cpp_lib_latch 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_latch) && defined(__glibcxx_want_latch) */
+#endif /* !defined(__cpp_lib_latch) */
#undef __glibcxx_want_latch
#if !defined(__cpp_lib_list_remove_return_type)
@@ -1467,7 +1588,7 @@
# define __cpp_lib_list_remove_return_type 201806L
# endif
# endif
-#endif /* !defined(__cpp_lib_list_remove_return_type) && defined(__glibcxx_want_list_remove_return_type) */
+#endif /* !defined(__cpp_lib_list_remove_return_type) */
#undef __glibcxx_want_list_remove_return_type
#if !defined(__cpp_lib_polymorphic_allocator)
@@ -1477,7 +1598,7 @@
# define __cpp_lib_polymorphic_allocator 201902L
# endif
# endif
-#endif /* !defined(__cpp_lib_polymorphic_allocator) && defined(__glibcxx_want_polymorphic_allocator) */
+#endif /* !defined(__cpp_lib_polymorphic_allocator) */
#undef __glibcxx_want_polymorphic_allocator
#if !defined(__cpp_lib_move_iterator_concept)
@@ -1487,17 +1608,17 @@
# define __cpp_lib_move_iterator_concept 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_move_iterator_concept) && defined(__glibcxx_want_move_iterator_concept) */
+#endif /* !defined(__cpp_lib_move_iterator_concept) */
#undef __glibcxx_want_move_iterator_concept
#if !defined(__cpp_lib_semaphore)
-# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED && (__glibcxx_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE)
+# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED && (__glibcxx_atomic_wait)
# define __glibcxx_semaphore 201907L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_semaphore)
# define __cpp_lib_semaphore 201907L
# endif
# endif
-#endif /* !defined(__cpp_lib_semaphore) && defined(__glibcxx_want_semaphore) */
+#endif /* !defined(__cpp_lib_semaphore) */
#undef __glibcxx_want_semaphore
#if !defined(__cpp_lib_smart_ptr_for_overwrite)
@@ -1507,7 +1628,7 @@
# define __cpp_lib_smart_ptr_for_overwrite 202002L
# endif
# endif
-#endif /* !defined(__cpp_lib_smart_ptr_for_overwrite) && defined(__glibcxx_want_smart_ptr_for_overwrite) */
+#endif /* !defined(__cpp_lib_smart_ptr_for_overwrite) */
#undef __glibcxx_want_smart_ptr_for_overwrite
#if !defined(__cpp_lib_syncbuf)
@@ -1517,7 +1638,7 @@
# define __cpp_lib_syncbuf 201803L
# endif
# endif
-#endif /* !defined(__cpp_lib_syncbuf) && defined(__glibcxx_want_syncbuf) */
+#endif /* !defined(__cpp_lib_syncbuf) */
#undef __glibcxx_want_syncbuf
#if !defined(__cpp_lib_byteswap)
@@ -1527,7 +1648,7 @@
# define __cpp_lib_byteswap 202110L
# endif
# endif
-#endif /* !defined(__cpp_lib_byteswap) && defined(__glibcxx_want_byteswap) */
+#endif /* !defined(__cpp_lib_byteswap) */
#undef __glibcxx_want_byteswap
#if !defined(__cpp_lib_constexpr_charconv)
@@ -1537,7 +1658,7 @@
# define __cpp_lib_constexpr_charconv 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_charconv) && defined(__glibcxx_want_constexpr_charconv) */
+#endif /* !defined(__cpp_lib_constexpr_charconv) */
#undef __glibcxx_want_constexpr_charconv
#if !defined(__cpp_lib_constexpr_typeinfo)
@@ -1547,7 +1668,7 @@
# define __cpp_lib_constexpr_typeinfo 202106L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_typeinfo) && defined(__glibcxx_want_constexpr_typeinfo) */
+#endif /* !defined(__cpp_lib_constexpr_typeinfo) */
#undef __glibcxx_want_constexpr_typeinfo
#if !defined(__cpp_lib_expected)
@@ -1557,16 +1678,17 @@
# define __cpp_lib_expected 202211L
# endif
# endif
-#endif /* !defined(__cpp_lib_expected) && defined(__glibcxx_want_expected) */
+#endif /* !defined(__cpp_lib_expected) */
#undef __glibcxx_want_expected
#if !defined(__cpp_lib_format_ranges)
# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED
-# define __glibcxx_format_ranges 1L
+# define __glibcxx_format_ranges 202207L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_format_ranges)
+# define __cpp_lib_format_ranges 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_format_ranges) && defined(__glibcxx_want_format_ranges) */
+#endif /* !defined(__cpp_lib_format_ranges) */
#undef __glibcxx_want_format_ranges
#if !defined(__cpp_lib_freestanding_algorithm)
@@ -1576,7 +1698,7 @@
# define __cpp_lib_freestanding_algorithm 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_freestanding_algorithm) && defined(__glibcxx_want_freestanding_algorithm) */
+#endif /* !defined(__cpp_lib_freestanding_algorithm) */
#undef __glibcxx_want_freestanding_algorithm
#if !defined(__cpp_lib_freestanding_array)
@@ -1586,7 +1708,7 @@
# define __cpp_lib_freestanding_array 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_freestanding_array) && defined(__glibcxx_want_freestanding_array) */
+#endif /* !defined(__cpp_lib_freestanding_array) */
#undef __glibcxx_want_freestanding_array
#if !defined(__cpp_lib_freestanding_cstring)
@@ -1596,7 +1718,7 @@
# define __cpp_lib_freestanding_cstring 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_freestanding_cstring) && defined(__glibcxx_want_freestanding_cstring) */
+#endif /* !defined(__cpp_lib_freestanding_cstring) */
#undef __glibcxx_want_freestanding_cstring
#if !defined(__cpp_lib_freestanding_expected)
@@ -1606,7 +1728,7 @@
# define __cpp_lib_freestanding_expected 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_freestanding_expected) && defined(__glibcxx_want_freestanding_expected) */
+#endif /* !defined(__cpp_lib_freestanding_expected) */
#undef __glibcxx_want_freestanding_expected
#if !defined(__cpp_lib_freestanding_optional)
@@ -1616,7 +1738,7 @@
# define __cpp_lib_freestanding_optional 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_freestanding_optional) && defined(__glibcxx_want_freestanding_optional) */
+#endif /* !defined(__cpp_lib_freestanding_optional) */
#undef __glibcxx_want_freestanding_optional
#if !defined(__cpp_lib_freestanding_string_view)
@@ -1626,7 +1748,7 @@
# define __cpp_lib_freestanding_string_view 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_freestanding_string_view) && defined(__glibcxx_want_freestanding_string_view) */
+#endif /* !defined(__cpp_lib_freestanding_string_view) */
#undef __glibcxx_want_freestanding_string_view
#if !defined(__cpp_lib_freestanding_variant)
@@ -1636,7 +1758,7 @@
# define __cpp_lib_freestanding_variant 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_freestanding_variant) && defined(__glibcxx_want_freestanding_variant) */
+#endif /* !defined(__cpp_lib_freestanding_variant) */
#undef __glibcxx_want_freestanding_variant
#if !defined(__cpp_lib_invoke_r)
@@ -1646,7 +1768,7 @@
# define __cpp_lib_invoke_r 202106L
# endif
# endif
-#endif /* !defined(__cpp_lib_invoke_r) && defined(__glibcxx_want_invoke_r) */
+#endif /* !defined(__cpp_lib_invoke_r) */
#undef __glibcxx_want_invoke_r
#if !defined(__cpp_lib_is_scoped_enum)
@@ -1656,7 +1778,7 @@
# define __cpp_lib_is_scoped_enum 202011L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_scoped_enum) && defined(__glibcxx_want_is_scoped_enum) */
+#endif /* !defined(__cpp_lib_is_scoped_enum) */
#undef __glibcxx_want_is_scoped_enum
#if !defined(__cpp_lib_reference_from_temporary)
@@ -1666,7 +1788,7 @@
# define __cpp_lib_reference_from_temporary 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_reference_from_temporary) && defined(__glibcxx_want_reference_from_temporary) */
+#endif /* !defined(__cpp_lib_reference_from_temporary) */
#undef __glibcxx_want_reference_from_temporary
#if !defined(__cpp_lib_containers_ranges)
@@ -1676,7 +1798,7 @@
# define __cpp_lib_containers_ranges 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_containers_ranges) && defined(__glibcxx_want_containers_ranges) */
+#endif /* !defined(__cpp_lib_containers_ranges) */
#undef __glibcxx_want_containers_ranges
#if !defined(__cpp_lib_ranges_to_container)
@@ -1686,7 +1808,7 @@
# define __cpp_lib_ranges_to_container 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_to_container) && defined(__glibcxx_want_ranges_to_container) */
+#endif /* !defined(__cpp_lib_ranges_to_container) */
#undef __glibcxx_want_ranges_to_container
#if !defined(__cpp_lib_ranges_zip)
@@ -1696,7 +1818,7 @@
# define __cpp_lib_ranges_zip 202110L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_zip) && defined(__glibcxx_want_ranges_zip) */
+#endif /* !defined(__cpp_lib_ranges_zip) */
#undef __glibcxx_want_ranges_zip
#if !defined(__cpp_lib_ranges_chunk)
@@ -1706,7 +1828,7 @@
# define __cpp_lib_ranges_chunk 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_chunk) && defined(__glibcxx_want_ranges_chunk) */
+#endif /* !defined(__cpp_lib_ranges_chunk) */
#undef __glibcxx_want_ranges_chunk
#if !defined(__cpp_lib_ranges_slide)
@@ -1716,7 +1838,7 @@
# define __cpp_lib_ranges_slide 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_slide) && defined(__glibcxx_want_ranges_slide) */
+#endif /* !defined(__cpp_lib_ranges_slide) */
#undef __glibcxx_want_ranges_slide
#if !defined(__cpp_lib_ranges_chunk_by)
@@ -1726,7 +1848,7 @@
# define __cpp_lib_ranges_chunk_by 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_chunk_by) && defined(__glibcxx_want_ranges_chunk_by) */
+#endif /* !defined(__cpp_lib_ranges_chunk_by) */
#undef __glibcxx_want_ranges_chunk_by
#if !defined(__cpp_lib_ranges_join_with)
@@ -1736,7 +1858,7 @@
# define __cpp_lib_ranges_join_with 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_join_with) && defined(__glibcxx_want_ranges_join_with) */
+#endif /* !defined(__cpp_lib_ranges_join_with) */
#undef __glibcxx_want_ranges_join_with
#if !defined(__cpp_lib_ranges_repeat)
@@ -1746,7 +1868,7 @@
# define __cpp_lib_ranges_repeat 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_repeat) && defined(__glibcxx_want_ranges_repeat) */
+#endif /* !defined(__cpp_lib_ranges_repeat) */
#undef __glibcxx_want_ranges_repeat
#if !defined(__cpp_lib_ranges_stride)
@@ -1756,7 +1878,7 @@
# define __cpp_lib_ranges_stride 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_stride) && defined(__glibcxx_want_ranges_stride) */
+#endif /* !defined(__cpp_lib_ranges_stride) */
#undef __glibcxx_want_ranges_stride
#if !defined(__cpp_lib_ranges_cartesian_product)
@@ -1766,7 +1888,7 @@
# define __cpp_lib_ranges_cartesian_product 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_cartesian_product) && defined(__glibcxx_want_ranges_cartesian_product) */
+#endif /* !defined(__cpp_lib_ranges_cartesian_product) */
#undef __glibcxx_want_ranges_cartesian_product
#if !defined(__cpp_lib_ranges_as_rvalue)
@@ -1776,7 +1898,7 @@
# define __cpp_lib_ranges_as_rvalue 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_as_rvalue) && defined(__glibcxx_want_ranges_as_rvalue) */
+#endif /* !defined(__cpp_lib_ranges_as_rvalue) */
#undef __glibcxx_want_ranges_as_rvalue
#if !defined(__cpp_lib_ranges_as_const)
@@ -1786,7 +1908,7 @@
# define __cpp_lib_ranges_as_const 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_as_const) && defined(__glibcxx_want_ranges_as_const) */
+#endif /* !defined(__cpp_lib_ranges_as_const) */
#undef __glibcxx_want_ranges_as_const
#if !defined(__cpp_lib_ranges_enumerate)
@@ -1796,7 +1918,7 @@
# define __cpp_lib_ranges_enumerate 202302L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_enumerate) && defined(__glibcxx_want_ranges_enumerate) */
+#endif /* !defined(__cpp_lib_ranges_enumerate) */
#undef __glibcxx_want_ranges_enumerate
#if !defined(__cpp_lib_ranges_fold)
@@ -1806,7 +1928,7 @@
# define __cpp_lib_ranges_fold 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_fold) && defined(__glibcxx_want_ranges_fold) */
+#endif /* !defined(__cpp_lib_ranges_fold) */
#undef __glibcxx_want_ranges_fold
#if !defined(__cpp_lib_ranges_contains)
@@ -1816,7 +1938,7 @@
# define __cpp_lib_ranges_contains 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_contains) && defined(__glibcxx_want_ranges_contains) */
+#endif /* !defined(__cpp_lib_ranges_contains) */
#undef __glibcxx_want_ranges_contains
#if !defined(__cpp_lib_ranges_iota)
@@ -1826,7 +1948,7 @@
# define __cpp_lib_ranges_iota 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_iota) && defined(__glibcxx_want_ranges_iota) */
+#endif /* !defined(__cpp_lib_ranges_iota) */
#undef __glibcxx_want_ranges_iota
#if !defined(__cpp_lib_ranges_find_last)
@@ -1836,9 +1958,29 @@
# define __cpp_lib_ranges_find_last 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_find_last) && defined(__glibcxx_want_ranges_find_last) */
+#endif /* !defined(__cpp_lib_ranges_find_last) */
#undef __glibcxx_want_ranges_find_last
+#if !defined(__cpp_lib_ranges_starts_ends_with)
+# if (__cplusplus >= 202100L)
+# define __glibcxx_ranges_starts_ends_with 202106L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_starts_ends_with)
+# define __cpp_lib_ranges_starts_ends_with 202106L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_ranges_starts_ends_with) */
+#undef __glibcxx_want_ranges_starts_ends_with
+
+#if !defined(__cpp_lib_ranges_indices)
+# if (__cplusplus > 202302L)
+# define __glibcxx_ranges_indices 202506L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_indices)
+# define __cpp_lib_ranges_indices 202506L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_ranges_indices) */
+#undef __glibcxx_want_ranges_indices
+
#if !defined(__cpp_lib_constexpr_bitset)
# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED && (__cpp_constexpr_dynamic_alloc)
# define __glibcxx_constexpr_bitset 202202L
@@ -1846,7 +1988,7 @@
# define __cpp_lib_constexpr_bitset 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_bitset) && defined(__glibcxx_want_constexpr_bitset) */
+#endif /* !defined(__cpp_lib_constexpr_bitset) */
#undef __glibcxx_want_constexpr_bitset
#if !defined(__cpp_lib_stdatomic_h)
@@ -1856,7 +1998,7 @@
# define __cpp_lib_stdatomic_h 202011L
# endif
# endif
-#endif /* !defined(__cpp_lib_stdatomic_h) && defined(__glibcxx_want_stdatomic_h) */
+#endif /* !defined(__cpp_lib_stdatomic_h) */
#undef __glibcxx_want_stdatomic_h
#if !defined(__cpp_lib_adaptor_iterator_pair_constructor)
@@ -1866,7 +2008,7 @@
# define __cpp_lib_adaptor_iterator_pair_constructor 202106L
# endif
# endif
-#endif /* !defined(__cpp_lib_adaptor_iterator_pair_constructor) && defined(__glibcxx_want_adaptor_iterator_pair_constructor) */
+#endif /* !defined(__cpp_lib_adaptor_iterator_pair_constructor) */
#undef __glibcxx_want_adaptor_iterator_pair_constructor
#if !defined(__cpp_lib_flat_map)
@@ -1876,7 +2018,7 @@
# define __cpp_lib_flat_map 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_flat_map) && defined(__glibcxx_want_flat_map) */
+#endif /* !defined(__cpp_lib_flat_map) */
#undef __glibcxx_want_flat_map
#if !defined(__cpp_lib_flat_set)
@@ -1886,9 +2028,29 @@
# define __cpp_lib_flat_set 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_flat_set) && defined(__glibcxx_want_flat_set) */
+#endif /* !defined(__cpp_lib_flat_set) */
#undef __glibcxx_want_flat_set
+#if !defined(__cpp_lib_common_reference)
+# if (__cplusplus >= 202002L)
+# define __glibcxx_common_reference 202302L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_common_reference)
+# define __cpp_lib_common_reference 202302L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_common_reference) */
+#undef __glibcxx_want_common_reference
+
+#if !defined(__cpp_lib_common_reference_wrapper)
+# if (__cplusplus >= 202002L)
+# define __glibcxx_common_reference_wrapper 202302L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_common_reference_wrapper)
+# define __cpp_lib_common_reference_wrapper 202302L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_common_reference_wrapper) */
+#undef __glibcxx_want_common_reference_wrapper
+
#if !defined(__cpp_lib_formatters)
# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED
# define __glibcxx_formatters 202302L
@@ -1896,7 +2058,7 @@
# define __cpp_lib_formatters 202302L
# endif
# endif
-#endif /* !defined(__cpp_lib_formatters) && defined(__glibcxx_want_formatters) */
+#endif /* !defined(__cpp_lib_formatters) */
#undef __glibcxx_want_formatters
#if !defined(__cpp_lib_forward_like)
@@ -1906,7 +2068,7 @@
# define __cpp_lib_forward_like 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_forward_like) && defined(__glibcxx_want_forward_like) */
+#endif /* !defined(__cpp_lib_forward_like) */
#undef __glibcxx_want_forward_like
#if !defined(__cpp_lib_generator)
@@ -1916,7 +2078,7 @@
# define __cpp_lib_generator 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_generator) && defined(__glibcxx_want_generator) */
+#endif /* !defined(__cpp_lib_generator) */
#undef __glibcxx_want_generator
#if !defined(__cpp_lib_ios_noreplace)
@@ -1926,7 +2088,7 @@
# define __cpp_lib_ios_noreplace 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_ios_noreplace) && defined(__glibcxx_want_ios_noreplace) */
+#endif /* !defined(__cpp_lib_ios_noreplace) */
#undef __glibcxx_want_ios_noreplace
#if !defined(__cpp_lib_move_only_function)
@@ -1936,9 +2098,29 @@
# define __cpp_lib_move_only_function 202110L
# endif
# endif
-#endif /* !defined(__cpp_lib_move_only_function) && defined(__glibcxx_want_move_only_function) */
+#endif /* !defined(__cpp_lib_move_only_function) */
#undef __glibcxx_want_move_only_function
+#if !defined(__cpp_lib_copyable_function)
+# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
+# define __glibcxx_copyable_function 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_copyable_function)
+# define __cpp_lib_copyable_function 202306L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_copyable_function) */
+#undef __glibcxx_want_copyable_function
+
+#if !defined(__cpp_lib_function_ref)
+# if (__cplusplus > 202302L)
+# define __glibcxx_function_ref 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_function_ref)
+# define __cpp_lib_function_ref 202306L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_function_ref) */
+#undef __glibcxx_want_function_ref
+
#if !defined(__cpp_lib_out_ptr)
# if (__cplusplus >= 202100L)
# define __glibcxx_out_ptr 202311L
@@ -1946,17 +2128,17 @@
# define __cpp_lib_out_ptr 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_out_ptr) && defined(__glibcxx_want_out_ptr) */
+#endif /* !defined(__cpp_lib_out_ptr) */
#undef __glibcxx_want_out_ptr
#if !defined(__cpp_lib_print)
# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED
-# define __glibcxx_print 202211L
+# define __glibcxx_print 202406L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_print)
-# define __cpp_lib_print 202211L
+# define __cpp_lib_print 202406L
# endif
# endif
-#endif /* !defined(__cpp_lib_print) && defined(__glibcxx_want_print) */
+#endif /* !defined(__cpp_lib_print) */
#undef __glibcxx_want_print
#if !defined(__cpp_lib_spanstream)
@@ -1966,7 +2148,7 @@
# define __cpp_lib_spanstream 202106L
# endif
# endif
-#endif /* !defined(__cpp_lib_spanstream) && defined(__glibcxx_want_spanstream) */
+#endif /* !defined(__cpp_lib_spanstream) */
#undef __glibcxx_want_spanstream
#if !defined(__cpp_lib_stacktrace)
@@ -1976,9 +2158,19 @@
# define __cpp_lib_stacktrace 202011L
# endif
# endif
-#endif /* !defined(__cpp_lib_stacktrace) && defined(__glibcxx_want_stacktrace) */
+#endif /* !defined(__cpp_lib_stacktrace) */
#undef __glibcxx_want_stacktrace
+#if !defined(__cpp_lib_start_lifetime_as)
+# if (__cplusplus >= 202100L)
+# define __glibcxx_start_lifetime_as 202207L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_start_lifetime_as)
+# define __cpp_lib_start_lifetime_as 202207L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_start_lifetime_as) */
+#undef __glibcxx_want_start_lifetime_as
+
#if !defined(__cpp_lib_string_contains)
# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED
# define __glibcxx_string_contains 202011L
@@ -1986,7 +2178,7 @@
# define __cpp_lib_string_contains 202011L
# endif
# endif
-#endif /* !defined(__cpp_lib_string_contains) && defined(__glibcxx_want_string_contains) */
+#endif /* !defined(__cpp_lib_string_contains) */
#undef __glibcxx_want_string_contains
#if !defined(__cpp_lib_string_resize_and_overwrite)
@@ -1996,9 +2188,19 @@
# define __cpp_lib_string_resize_and_overwrite 202110L
# endif
# endif
-#endif /* !defined(__cpp_lib_string_resize_and_overwrite) && defined(__glibcxx_want_string_resize_and_overwrite) */
+#endif /* !defined(__cpp_lib_string_resize_and_overwrite) */
#undef __glibcxx_want_string_resize_and_overwrite
+#if !defined(__cpp_lib_string_subview)
+# if (__cplusplus > 202302L)
+# define __glibcxx_string_subview 202506L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_string_subview)
+# define __cpp_lib_string_subview 202506L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_string_subview) */
+#undef __glibcxx_want_string_subview
+
#if !defined(__cpp_lib_to_underlying)
# if (__cplusplus >= 202100L)
# define __glibcxx_to_underlying 202102L
@@ -2006,7 +2208,7 @@
# define __cpp_lib_to_underlying 202102L
# endif
# endif
-#endif /* !defined(__cpp_lib_to_underlying) && defined(__glibcxx_want_to_underlying) */
+#endif /* !defined(__cpp_lib_to_underlying) */
#undef __glibcxx_want_to_underlying
#if !defined(__cpp_lib_tuple_like)
@@ -2021,7 +2223,7 @@
# define __cpp_lib_tuple_like 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_tuple_like) && defined(__glibcxx_want_tuple_like) */
+#endif /* !defined(__cpp_lib_tuple_like) */
#undef __glibcxx_want_tuple_like
#if !defined(__cpp_lib_unreachable)
@@ -2031,9 +2233,19 @@
# define __cpp_lib_unreachable 202202L
# endif
# endif
-#endif /* !defined(__cpp_lib_unreachable) && defined(__glibcxx_want_unreachable) */
+#endif /* !defined(__cpp_lib_unreachable) */
#undef __glibcxx_want_unreachable
+#if !defined(__cpp_lib_observable_checkpoint)
+# if (__cplusplus > 202302L) && (__has_builtin(__builtin_observable_checkpoint))
+# define __glibcxx_observable_checkpoint 202506L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_observable_checkpoint)
+# define __cpp_lib_observable_checkpoint 202506L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_observable_checkpoint) */
+#undef __glibcxx_want_observable_checkpoint
+
#if !defined(__cpp_lib_algorithm_default_value_type)
# if (__cplusplus > 202302L)
# define __glibcxx_algorithm_default_value_type 202403L
@@ -2041,7 +2253,7 @@
# define __cpp_lib_algorithm_default_value_type 202403L
# endif
# endif
-#endif /* !defined(__cpp_lib_algorithm_default_value_type) && defined(__glibcxx_want_algorithm_default_value_type) */
+#endif /* !defined(__cpp_lib_algorithm_default_value_type) */
#undef __glibcxx_want_algorithm_default_value_type
#if !defined(__cpp_lib_constexpr_new)
@@ -2051,9 +2263,19 @@
# define __cpp_lib_constexpr_new 202406L
# endif
# endif
-#endif /* !defined(__cpp_lib_constexpr_new) && defined(__glibcxx_want_constexpr_new) */
+#endif /* !defined(__cpp_lib_constexpr_new) */
#undef __glibcxx_want_constexpr_new
+#if !defined(__cpp_lib_debugging)
+# if (__cplusplus > 202302L)
+# define __glibcxx_debugging 202403L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_debugging)
+# define __cpp_lib_debugging 202403L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_debugging) */
+#undef __glibcxx_want_debugging
+
#if !defined(__cpp_lib_fstream_native_handle)
# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
# define __glibcxx_fstream_native_handle 202306L
@@ -2061,7 +2283,7 @@
# define __cpp_lib_fstream_native_handle 202306L
# endif
# endif
-#endif /* !defined(__cpp_lib_fstream_native_handle) && defined(__glibcxx_want_fstream_native_handle) */
+#endif /* !defined(__cpp_lib_fstream_native_handle) */
#undef __glibcxx_want_fstream_native_handle
#if !defined(__cpp_lib_is_virtual_base_of)
@@ -2071,7 +2293,7 @@
# define __cpp_lib_is_virtual_base_of 202406L
# endif
# endif
-#endif /* !defined(__cpp_lib_is_virtual_base_of) && defined(__glibcxx_want_is_virtual_base_of) */
+#endif /* !defined(__cpp_lib_is_virtual_base_of) */
#undef __glibcxx_want_is_virtual_base_of
#if !defined(__cpp_lib_ranges_cache_latest)
@@ -2081,7 +2303,7 @@
# define __cpp_lib_ranges_cache_latest 202411L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_cache_latest) && defined(__glibcxx_want_ranges_cache_latest) */
+#endif /* !defined(__cpp_lib_ranges_cache_latest) */
#undef __glibcxx_want_ranges_cache_latest
#if !defined(__cpp_lib_ranges_concat)
@@ -2091,7 +2313,7 @@
# define __cpp_lib_ranges_concat 202403L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_concat) && defined(__glibcxx_want_ranges_concat) */
+#endif /* !defined(__cpp_lib_ranges_concat) */
#undef __glibcxx_want_ranges_concat
#if !defined(__cpp_lib_ratio)
@@ -2101,7 +2323,7 @@
# define __cpp_lib_ratio 202306L
# endif
# endif
-#endif /* !defined(__cpp_lib_ratio) && defined(__glibcxx_want_ratio) */
+#endif /* !defined(__cpp_lib_ratio) */
#undef __glibcxx_want_ratio
#if !defined(__cpp_lib_reference_wrapper)
@@ -2111,7 +2333,7 @@
# define __cpp_lib_reference_wrapper 202403L
# endif
# endif
-#endif /* !defined(__cpp_lib_reference_wrapper) && defined(__glibcxx_want_reference_wrapper) */
+#endif /* !defined(__cpp_lib_reference_wrapper) */
#undef __glibcxx_want_reference_wrapper
#if !defined(__cpp_lib_saturation_arithmetic)
@@ -2121,7 +2343,7 @@
# define __cpp_lib_saturation_arithmetic 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_saturation_arithmetic) && defined(__glibcxx_want_saturation_arithmetic) */
+#endif /* !defined(__cpp_lib_saturation_arithmetic) */
#undef __glibcxx_want_saturation_arithmetic
#if !defined(__cpp_lib_span_initializer_list)
@@ -2131,7 +2353,7 @@
# define __cpp_lib_span_initializer_list 202311L
# endif
# endif
-#endif /* !defined(__cpp_lib_span_initializer_list) && defined(__glibcxx_want_span_initializer_list) */
+#endif /* !defined(__cpp_lib_span_initializer_list) */
#undef __glibcxx_want_span_initializer_list
#if !defined(__cpp_lib_text_encoding)
@@ -2141,7 +2363,7 @@
# define __cpp_lib_text_encoding 202306L
# endif
# endif
-#endif /* !defined(__cpp_lib_text_encoding) && defined(__glibcxx_want_text_encoding) */
+#endif /* !defined(__cpp_lib_text_encoding) */
#undef __glibcxx_want_text_encoding
#if !defined(__cpp_lib_ranges_to_input)
@@ -2151,7 +2373,7 @@
# define __cpp_lib_ranges_to_input 202502L
# endif
# endif
-#endif /* !defined(__cpp_lib_ranges_to_input) && defined(__glibcxx_want_ranges_to_input) */
+#endif /* !defined(__cpp_lib_ranges_to_input) */
#undef __glibcxx_want_ranges_to_input
#if !defined(__cpp_lib_to_string)
@@ -2161,7 +2383,7 @@
# define __cpp_lib_to_string 202306L
# endif
# endif
-#endif /* !defined(__cpp_lib_to_string) && defined(__glibcxx_want_to_string) */
+#endif /* !defined(__cpp_lib_to_string) */
#undef __glibcxx_want_to_string
#if !defined(__cpp_lib_modules)
@@ -2171,7 +2393,116 @@
# define __cpp_lib_modules 202207L
# endif
# endif
-#endif /* !defined(__cpp_lib_modules) && defined(__glibcxx_want_modules) */
+#endif /* !defined(__cpp_lib_modules) */
#undef __glibcxx_want_modules
+#if !defined(__cpp_lib_inplace_vector)
+# if (__cplusplus > 202302L)
+# define __glibcxx_inplace_vector 202406L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_inplace_vector)
+# define __cpp_lib_inplace_vector 202406L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_inplace_vector) */
+#undef __glibcxx_want_inplace_vector
+
+#if !defined(__cpp_lib_indirect)
+# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
+# define __glibcxx_indirect 202502L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_indirect)
+# define __cpp_lib_indirect 202502L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_indirect) */
+#undef __glibcxx_want_indirect
+
+#if !defined(__cpp_lib_polymorphic)
+# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
+# define __glibcxx_polymorphic 202502L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_polymorphic)
+# define __cpp_lib_polymorphic 202502L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_polymorphic) */
+#undef __glibcxx_want_polymorphic
+
+#if !defined(__cpp_lib_smart_ptr_owner_equality)
+# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
+# define __glibcxx_smart_ptr_owner_equality 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_smart_ptr_owner_equality)
+# define __cpp_lib_smart_ptr_owner_equality 202306L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_smart_ptr_owner_equality) */
+#undef __glibcxx_want_smart_ptr_owner_equality
+
+#if !defined(__cpp_lib_sstream_from_string_view)
+# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
+# define __glibcxx_sstream_from_string_view 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_sstream_from_string_view)
+# define __cpp_lib_sstream_from_string_view 202306L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_sstream_from_string_view) */
+#undef __glibcxx_want_sstream_from_string_view
+
+#if !defined(__cpp_lib_type_order)
+# if (__cplusplus > 202302L) && (__has_builtin(__builtin_type_order) && __cpp_lib_three_way_comparison >= 201907L)
+# define __glibcxx_type_order 202506L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_type_order)
+# define __cpp_lib_type_order 202506L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_type_order) */
+#undef __glibcxx_want_type_order
+
+#if !defined(__cpp_lib_exception_ptr_cast)
+# if (__cplusplus > 202302L)
+# define __glibcxx_exception_ptr_cast 202506L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_exception_ptr_cast)
+# define __cpp_lib_exception_ptr_cast 202506L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_exception_ptr_cast) */
+#undef __glibcxx_want_exception_ptr_cast
+
+#if !defined(__cpp_lib_bitset)
+# if (__cplusplus > 202302L)
+# define __glibcxx_bitset 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bitset)
+# define __cpp_lib_bitset 202306L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_bitset) */
+#undef __glibcxx_want_bitset
+
+#if !defined(__cpp_lib_constexpr_exceptions)
+# if (__cplusplus > 202302L) && (__cpp_constexpr_exceptions >= 202411L)
+# define __glibcxx_constexpr_exceptions 1L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_exceptions)
+# endif
+# endif
+#endif /* !defined(__cpp_lib_constexpr_exceptions) */
+#undef __glibcxx_want_constexpr_exceptions
+
+#if !defined(__cpp_lib_philox_engine)
+# if (__cplusplus > 202302L) && (__SIZEOF_INT128__)
+# define __glibcxx_philox_engine 202406L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_philox_engine)
+# define __cpp_lib_philox_engine 202406L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_philox_engine) */
+#undef __glibcxx_want_philox_engine
+
+#if !defined(__cpp_lib_is_implicit_lifetime)
+# if (__cplusplus >= 202100L) && (__has_builtin(__builtin_is_implicit_lifetime))
+# define __glibcxx_is_implicit_lifetime 202302L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_implicit_lifetime)
+# define __cpp_lib_is_implicit_lifetime 202302L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_is_implicit_lifetime) */
+#undef __glibcxx_want_is_implicit_lifetime
+
#undef __glibcxx_want_all
diff --git a/libstdc++-v3/include/bits/version.tpl b/libstdc++-v3/include/bits/version.tpl
index ccda71d..5d62b2a 100644
--- a/libstdc++-v3/include/bits/version.tpl
+++ b/libstdc++-v3/include/bits/version.tpl
@@ -132,10 +132,11 @@ h
This macro block defines two versions of each FTM:
- 1. __glibcxx_NAME, which is defined unconditionally, and
- 2. __cpp_lib_NAME, which is defined only if marked as wanted.
+ 1. __glibcxx_NAME, which is defined as long its conditions are met, and
+ 2. __cpp_lib_NAME, which is defined only if __glibcxx_want_NAME is defined
+ and no_stdname is not set.
- This allows FTMs to depend on eachother in their definitions without messing
+ This allows FTMs to depend on each other in their definitions without messing
with the exported values.
This can also be used by bits that do not want to expose FTMs that they can't
@@ -155,7 +156,7 @@ h
# endif
/*{ ENDFOR values
}*/# endif
-#endif /* !defined(__cpp_lib_/*{name}*/) && defined(__glibcxx_want_/*{name}*/) */
+#endif /* !defined(__cpp_lib_/*{name}*/) */
#undef __glibcxx_want_/*{name
}*//*{ (unless (last-for?) "\n\n" "\n")}*/
/*{ ENDFOR ftms }*//*{
diff --git a/libstdc++-v3/include/c_compatibility/stdckdint.h b/libstdc++-v3/include/c_compatibility/stdckdint.h
index 1de2d18..5bdf4dc 100644
--- a/libstdc++-v3/include/c_compatibility/stdckdint.h
+++ b/libstdc++-v3/include/c_compatibility/stdckdint.h
@@ -40,15 +40,6 @@
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
#endif
-/// @cond undocumented
-namespace __detail
-{
- template<typename _Tp>
- concept __cv_unqual_signed_or_unsigned_integer_type
- = std::same_as<_Tp, std::remove_cv_t<_Tp>>
- && std::__is_standard_integer<_Tp>::value;
-}
-/// @endcond
/** Checked integer arithmetic
*
@@ -71,10 +62,9 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
inline bool
ckd_add(_Tp1* __result, _Tp2 __a, _Tp3 __b)
{
- using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
return __builtin_add_overflow(__a, __b, __result);
}
@@ -82,10 +72,9 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
inline bool
ckd_sub(_Tp1* __result, _Tp2 __a, _Tp3 __b)
{
- using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
return __builtin_sub_overflow(__a, __b, __result);
}
@@ -93,15 +82,14 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
inline bool
ckd_mul(_Tp1* __result, _Tp2 __a, _Tp3 __b)
{
- using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
return __builtin_mul_overflow(__a, __b, __result);
}
/// @}
#ifndef _GLIBCXX_DOXYGEN
-}
+} // namespace __gnu_cxx
using __gnu_cxx::ckd_add;
using __gnu_cxx::ckd_sub;
diff --git a/libstdc++-v3/include/c_global/ccomplex b/libstdc++-v3/include/c_global/ccomplex
index 7044cf7..a39273f 100644
--- a/libstdc++-v3/include/c_global/ccomplex
+++ b/libstdc++-v3/include/c_global/ccomplex
@@ -24,6 +24,8 @@
/** @file include/ccomplex
* This is a Standard C++ Library header.
+ *
+ * @since C++11 (removed in C++20)
*/
#ifndef _GLIBCXX_CCOMPLEX
diff --git a/libstdc++-v3/include/c_global/ciso646 b/libstdc++-v3/include/c_global/ciso646
index a663e04..6dec7df 100644
--- a/libstdc++-v3/include/c_global/ciso646
+++ b/libstdc++-v3/include/c_global/ciso646
@@ -28,6 +28,8 @@
*
* This is the C++ version of the Standard C Library header @c iso646.h,
* which is empty in C++.
+ *
+ * @since C++11 (removed in C++20)
*/
#ifndef _GLIBCXX_CISO646
#define _GLIBCXX_CISO646
@@ -38,13 +40,15 @@
#include <bits/c++config.h>
-#if __cplusplus >= 202002L && ! _GLIBCXX_USE_DEPRECATED
-# error "<ciso646> is not a standard header in C++20, use <version> to detect implementation-specific macros"
-#elif __cplusplus >= 201703L && defined __DEPRECATED
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wc++23-extensions"
-# warning "<ciso646> is deprecated in C++17, use <version> to detect implementation-specific macros"
-# pragma GCC diagnostic pop
+#if __cplusplus >= 202002L
+# if ! _GLIBCXX_USE_DEPRECATED
+# error "<ciso646> is not a standard header since C++20, use <version> to detect implementation-specific macros"
+# elif defined __DEPRECATED
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wc++23-extensions"
+# warning "<ciso646> is not a standard header since C++20, use <version> to detect implementation-specific macros"
+# pragma GCC diagnostic pop
+# endif
#endif
#endif
diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath
index 27c21ca..65a3b81 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -3792,10 +3792,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return std::__hypot3<long double>(__x, __y, __z); }
template<typename _Tp, typename _Up, typename _Vp>
- __gnu_cxx::__promoted_t<_Tp, _Up, _Vp>
+ typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type
hypot(_Tp __x, _Up __y, _Vp __z)
{
- using __type = __gnu_cxx::__promoted_t<_Tp, _Up, _Vp>;
+ using __type = typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type;
return std::__hypot3<__type>(__x, __y, __z);
}
diff --git a/libstdc++-v3/include/c_global/cstdalign b/libstdc++-v3/include/c_global/cstdalign
index 92e0ad6..41ce506 100644
--- a/libstdc++-v3/include/c_global/cstdalign
+++ b/libstdc++-v3/include/c_global/cstdalign
@@ -24,6 +24,8 @@
/** @file include/cstdalign
* This is a Standard C++ Library header.
+ *
+ * @since C++11 (removed in C++20)
*/
#ifndef _GLIBCXX_CSTDALIGN
diff --git a/libstdc++-v3/include/c_global/cstdbool b/libstdc++-v3/include/c_global/cstdbool
index e75f56c..5933d7d 100644
--- a/libstdc++-v3/include/c_global/cstdbool
+++ b/libstdc++-v3/include/c_global/cstdbool
@@ -24,6 +24,8 @@
/** @file include/cstdbool
* This is a Standard C++ Library header.
+ *
+ * @since C++11 (removed in C++20)
*/
#ifndef _GLIBCXX_CSTDBOOL
diff --git a/libstdc++-v3/include/c_global/ctgmath b/libstdc++-v3/include/c_global/ctgmath
index 0a5a0e7..b708878 100644
--- a/libstdc++-v3/include/c_global/ctgmath
+++ b/libstdc++-v3/include/c_global/ctgmath
@@ -24,6 +24,8 @@
/** @file include/ctgmath
* This is a Standard C++ Library header.
+ *
+ * @since C++11 (removed in C++20)
*/
#ifndef _GLIBCXX_CTGMATH
diff --git a/libstdc++-v3/include/debug/bitset b/libstdc++-v3/include/debug/bitset
index ad9b7b5..2f4bab8 100644
--- a/libstdc++-v3/include/debug/bitset
+++ b/libstdc++-v3/include/debug/bitset
@@ -164,11 +164,28 @@ namespace __debug
_CharT __zero, _CharT __one = _CharT('1'))
: _Base(__str, __pos, __n, __zero, __one) { }
+#ifdef __cpp_lib_bitset // ... from string_view
+ template<class _CharT, class _Traits>
+ constexpr explicit
+ bitset(std::basic_string_view<_CharT, _Traits> __s,
+ std::basic_string_view<_CharT, _Traits>::size_type __position = 0,
+ std::basic_string_view<_CharT, _Traits>::size_type __n =
+ std::basic_string_view<_CharT, _Traits>::npos,
+ _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'))
+ : _Base(__s, __position, __n, __zero, __one) { }
+#endif
+
_GLIBCXX23_CONSTEXPR
bitset(const _Base& __x) : _Base(__x) { }
#if __cplusplus >= 201103L
- template<typename _CharT>
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4294. bitset(const CharT*) constructor needs to be constrained
+ template<typename _CharT,
+ typename = _Require<is_trivially_copyable<_CharT>,
+ is_standard_layout<_CharT>,
+ is_trivially_default_constructible<_CharT>,
+ __not_<is_array<_CharT>>>>
_GLIBCXX23_CONSTEXPR
explicit
bitset(const _CharT* __str,
diff --git a/libstdc++-v3/include/debug/debug.h b/libstdc++-v3/include/debug/debug.h
index 0e02d58..0131c0a 100644
--- a/libstdc++-v3/include/debug/debug.h
+++ b/libstdc++-v3/include/debug/debug.h
@@ -58,7 +58,7 @@ namespace __gnu_debug
using namespace std::__debug;
template<typename _Ite, typename _Seq, typename _Cat>
- struct _Safe_iterator;
+ class _Safe_iterator;
}
#if ! defined _GLIBCXX_DEBUG || ! _GLIBCXX_HOSTED
diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque
index 59d60b2..b2e5dd3 100644
--- a/libstdc++-v3/include/debug/deque
+++ b/libstdc++-v3/include/debug/deque
@@ -650,7 +650,8 @@ namespace __debug
else if (__first.base() == _Base::begin()
|| __last.base() == _Base::end())
{
- this->_M_detach_singular();
+ const deque* __this = this;
+ __this->_M_detach_singular();
for (_Base_const_iterator __position = __first.base();
__position != __last.base(); ++__position)
{
@@ -663,7 +664,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
@@ -770,6 +771,34 @@ namespace __debug
{ __lhs.swap(__rhs); }
} // namespace __debug
+
+#ifdef __glibcxx_erase_if // C++ >= 20 && HOSTED
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ template<typename _Tp, typename _Alloc, typename _Predicate>
+ inline typename __debug::deque<_Tp, _Alloc>::size_type
+ erase_if(__debug::deque<_Tp, _Alloc>& __cont, _Predicate __pred)
+ {
+ _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __unsafe_cont = __cont;
+ const auto __osz = __cont.size();
+ const auto __end = __unsafe_cont.end();
+ auto __removed = std::__remove_if(__unsafe_cont.begin(), __end,
+ std::move(__pred));
+ if (__removed != __end)
+ {
+ __cont.erase(__niter_wrap(__cont.begin(), __removed),
+ __cont.end());
+ return __osz - __cont.size();
+ }
+
+ return 0;
+ }
+
+ template<typename _Tp, typename _Alloc, typename _Up = _Tp>
+ inline typename __debug::deque<_Tp, _Alloc>::size_type
+ erase(__debug::deque<_Tp, _Alloc>& __cont, const _Up& __value)
+ { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }
+_GLIBCXX_END_NAMESPACE_VERSION
+#endif // __cpp_lib_erase_if
} // namespace std
#endif
diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h
index d80e8a7..8aa84ad 100644
--- a/libstdc++-v3/include/debug/formatter.h
+++ b/libstdc++-v3/include/debug/formatter.h
@@ -96,7 +96,7 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence, typename _Category>
class _Safe_iterator;
- template<typename _Iterator, typename _Sequence>
+ template<typename _Iterator, typename _UContainer>
class _Safe_local_iterator;
template<typename _Sequence>
@@ -316,8 +316,8 @@ namespace __gnu_debug
}
}
- template<typename _Iterator, typename _Sequence>
- _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it,
+ template<typename _Iterator, typename _UContainer>
+ _Parameter(_Safe_local_iterator<_Iterator, _UContainer> const& __it,
const char* __name, _Is_iterator)
: _M_kind(__iterator), _M_variant()
{
@@ -326,8 +326,8 @@ namespace __gnu_debug
_M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator);
_M_variant._M_iterator._M_constness =
__it._S_constant() ? __const_iterator : __mutable_iterator;
- _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
- _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
+ _M_variant._M_iterator._M_sequence = __it._M_get_ucontainer();
+ _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_UContainer);
if (__it._M_singular())
{
diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list
index 60a2542..9da7dda 100644
--- a/libstdc++-v3/include/debug/forward_list
+++ b/libstdc++-v3/include/debug/forward_list
@@ -58,44 +58,44 @@ namespace __gnu_debug
class _Safe_forward_list
: public _Safe_sequence<_SafeSequence>
{
- _SafeSequence&
- _M_this() noexcept
- { return *static_cast<_SafeSequence*>(this); }
+ const _SafeSequence*
+ _M_this() const noexcept
+ { return static_cast<const _SafeSequence*>(this); }
static void
- _M_swap_aux(_Safe_sequence_base& __lhs,
+ _S_swap_aux(const _Safe_forward_list& __lhs,
_Safe_iterator_base*& __lhs_iterators,
- _Safe_sequence_base& __rhs,
+ const _Safe_forward_list& __rhs,
_Safe_iterator_base*& __rhs_iterators);
- void _M_swap_single(_Safe_sequence_base&) noexcept;
+ void _M_swap_single(const _Safe_forward_list&) const noexcept;
protected:
void
- _M_invalidate_all()
+ _M_invalidate_all() const
{
- using _Base_const_iterator = __decltype(_M_this()._M_base().cend());
+ using _Base_const_iterator = __decltype(_M_this()->_M_base().cend());
this->_M_invalidate_if([this](_Base_const_iterator __it)
{
- return __it != _M_this()._M_base().cbefore_begin()
- && __it != _M_this()._M_base().cend(); });
+ return __it != _M_this()->_M_base().cbefore_begin()
+ && __it != _M_this()->_M_base().cend(); });
}
- void _M_swap(_Safe_sequence_base&) noexcept;
+ void
+ _M_swap(const _Safe_forward_list&) const noexcept;
};
template<typename _SafeSequence>
void
_Safe_forward_list<_SafeSequence>::
- _M_swap_aux(_Safe_sequence_base& __lhs,
+ _S_swap_aux(const _Safe_forward_list& __lhs,
_Safe_iterator_base*& __lhs_iterators,
- _Safe_sequence_base& __rhs,
+ const _Safe_forward_list& __rhs,
_Safe_iterator_base*& __rhs_iterators)
{
using const_iterator = typename _SafeSequence::const_iterator;
_Safe_iterator_base* __bbegin_its = 0;
_Safe_iterator_base* __last_bbegin = 0;
- _SafeSequence& __rseq = static_cast<_SafeSequence&>(__rhs);
for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
{
@@ -104,7 +104,7 @@ namespace __gnu_debug
const_iterator* __victim =
static_cast<const_iterator*>(__victim_base);
__iter = __iter->_M_next;
- if (__victim->base() == __rseq._M_base().cbefore_begin())
+ if (__victim->base() == __rhs._M_this()->_M_base().cbefore_begin())
{
__victim->_M_unlink();
if (__lhs_iterators == __victim_base)
@@ -136,21 +136,21 @@ namespace __gnu_debug
template<typename _SafeSequence>
void
_Safe_forward_list<_SafeSequence>::
- _M_swap_single(_Safe_sequence_base& __other) noexcept
+ _M_swap_single(const _Safe_forward_list& __other) const noexcept
{
- std::swap(_M_this()._M_iterators, __other._M_iterators);
- std::swap(_M_this()._M_const_iterators, __other._M_const_iterators);
+ std::swap(_M_this()->_M_iterators, __other._M_iterators);
+ std::swap(_M_this()->_M_const_iterators, __other._M_const_iterators);
// Useless, always 1 on forward_list
- //std::swap(_M_this()_M_version, __other._M_version);
- _Safe_iterator_base* __this_its = _M_this()._M_iterators;
- _M_swap_aux(__other, __other._M_iterators,
- _M_this(), _M_this()._M_iterators);
- _Safe_iterator_base* __this_const_its = _M_this()._M_const_iterators;
- _M_swap_aux(__other, __other._M_const_iterators,
- _M_this(), _M_this()._M_const_iterators);
- _M_swap_aux(_M_this(), __this_its,
+ //std::swap(_M_this()->_M_version, __other._M_version);
+ _Safe_iterator_base* __this_its = _M_this()->_M_iterators;
+ _S_swap_aux(__other, __other._M_iterators,
+ *_M_this(), _M_this()->_M_iterators);
+ _Safe_iterator_base* __this_const_its = _M_this()->_M_const_iterators;
+ _S_swap_aux(__other, __other._M_const_iterators,
+ *_M_this(), _M_this()->_M_const_iterators);
+ _S_swap_aux(*_M_this(), __this_its,
__other, __other._M_iterators);
- _M_swap_aux(_M_this(), __this_const_its,
+ _S_swap_aux(*_M_this(), __this_const_its,
__other, __other._M_const_iterators);
}
@@ -159,13 +159,12 @@ namespace __gnu_debug
template<typename _SafeSequence>
void
_Safe_forward_list<_SafeSequence>::
- _M_swap(_Safe_sequence_base& __other) noexcept
+ _M_swap(const _Safe_forward_list& __other) const noexcept
{
// We need to lock both sequences to swap
using namespace __gnu_cxx;
- __mutex *__this_mutex = &_M_this()._M_get_mutex();
- __mutex *__other_mutex =
- &static_cast<_SafeSequence&>(__other)._M_get_mutex();
+ __mutex *__this_mutex = &_M_this()->_M_get_mutex();
+ __mutex *__other_mutex = &__other._M_get_mutex();
if (__this_mutex == __other_mutex)
{
__scoped_lock __lock(*__this_mutex);
@@ -565,7 +564,8 @@ namespace __debug
void
resize(size_type __sz)
{
- this->_M_detach_singular();
+ const forward_list* __this = this;
+ __this->_M_detach_singular();
// if __sz < size(), invalidate all iterators in [begin+__sz, end()
_Base_iterator __victim = _Base::begin();
@@ -585,7 +585,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
@@ -593,7 +593,8 @@ namespace __debug
void
resize(size_type __sz, const value_type& __val)
{
- this->_M_detach_singular();
+ const forward_list* __this = this;
+ __this->_M_detach_singular();
// if __sz < size(), invalidate all iterators in [begin+__sz, end())
_Base_iterator __victim = _Base::begin();
@@ -613,7 +614,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h
index c5f5582..4e6fdae 100644
--- a/libstdc++-v3/include/debug/functions.h
+++ b/libstdc++-v3/include/debug/functions.h
@@ -53,15 +53,19 @@ namespace __gnu_debug
* assertion statement because, e.g., we are in a constructor.
*/
template<typename _InputIterator>
- inline _InputIterator
+ _GLIBCXX20_CONSTEXPR inline _InputIterator
__check_valid_range(const _InputIterator& __first,
const _InputIterator& __last,
const char* __file,
unsigned int __line,
const char* __function)
{
- __glibcxx_check_valid_range_at(__first, __last,
- __file, __line, __function);
+ if (!std::__is_constant_evaluated())
+ {
+ __glibcxx_check_valid_range_at(__first, __last,
+ __file, __line, __function);
+ }
+
return __first;
}
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index 9395892..b977103 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -249,7 +249,7 @@ namespace __gnu_debug
}
template<typename _Iterator, typename _Sequence, typename _Category>
- bool
+ _GLIBCXX20_CONSTEXPR bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
const _Safe_iterator<_Iterator, _Sequence, _Category>&,
typename _Distance_traits<_Iterator>::__type&);
@@ -272,7 +272,7 @@ namespace __gnu_debug
}
template<typename _Iterator, typename _Sequence, typename _Category>
- bool
+ _GLIBCXX20_CONSTEXPR bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
const _Safe_iterator<_Iterator, _Sequence, _Category>&);
diff --git a/libstdc++-v3/include/debug/inplace_vector b/libstdc++-v3/include/debug/inplace_vector
new file mode 100644
index 0000000..c7e301e
--- /dev/null
+++ b/libstdc++-v3/include/debug/inplace_vector
@@ -0,0 +1,691 @@
+// Debugging inplace_vector implementation -*- 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 debug/inplace_vector
+ * This file is a GNU debug extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_DEBUG_INPLACE_VECTOR
+#define _GLIBCXX_DEBUG_INPLACE_VECTOR 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <debug/debug.h>
+
+namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug {
+ template<typename _Tp, size_t _Nm> class inplace_vector;
+} } // namespace std::__debug
+
+#include <inplace_vector>
+
+#ifdef __glibcxx_inplace_vector // C++ >= 26
+
+#include <debug/safe_sequence.h>
+#include <debug/safe_iterator.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace __debug
+{
+ /// Class std::inplace_vector with safety/checking/debug instrumentation.
+ template<typename _Tp, size_t _Nm>
+ class inplace_vector
+ : public __gnu_debug::_Safe_sequence<inplace_vector<_Tp, _Nm>>
+ , public _GLIBCXX_STD_C::inplace_vector<_Tp, _Nm>
+ {
+ using _Base = _GLIBCXX_STD_C::inplace_vector<_Tp, _Nm>;
+ using _Base_iterator = typename _Base::iterator;
+ using _Base_const_iterator = typename _Base::const_iterator;
+ using _Equal = __gnu_debug::_Equal_to<_Base_const_iterator>;
+
+ template<typename _ItT, typename _SeqT, typename _CatT>
+ friend class ::__gnu_debug::_Safe_iterator;
+
+ public:
+ // types:
+ using value_type = _Base::value_type;
+ using pointer = _Base::pointer;
+ using const_pointer = _Base::const_pointer;
+ using reference = _Base::reference;
+ using const_reference = _Base::const_reference;
+ using size_type = _Base::size_type;
+ using difference_type = _Base::difference_type;
+ using iterator
+ = __gnu_debug::_Safe_iterator<_Base_iterator, inplace_vector>;
+ using const_iterator
+ = __gnu_debug::_Safe_iterator<_Base_const_iterator, inplace_vector>;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ constexpr
+ inplace_vector() noexcept = default;
+
+ constexpr explicit
+ inplace_vector(size_type __n)
+ : _Base(__n) { }
+
+ constexpr
+ inplace_vector(size_type __n, const _Tp& __value)
+ : _Base(__n, __value) { }
+
+ template<__any_input_iterator _InputIterator>
+ constexpr
+ inplace_vector(_InputIterator __first, _InputIterator __last)
+ : _Base(__gnu_debug::__base(
+ __glibcxx_check_valid_constructor_range(__first, __last)),
+ __gnu_debug::__base(__last)) { }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr
+ inplace_vector(from_range_t, _Rg&& __rg)
+ : _Base(from_range_t{}, std::forward<_Rg>(__rg)) { }
+
+ constexpr
+ inplace_vector(initializer_list<_Tp> __il)
+ : _Base(__il) { }
+
+ inplace_vector(const inplace_vector&) = default;
+ inplace_vector(inplace_vector&&) = default;
+ ~inplace_vector() = default;
+
+ inplace_vector&
+ operator=(const inplace_vector&) = default;
+
+ inplace_vector&
+ operator=(inplace_vector&&) = default;
+
+ constexpr inplace_vector&
+ operator=(initializer_list<_Tp> __il)
+ {
+ _Base::operator=(__il);
+ this->_M_invalidate_all();
+ return *this;
+ }
+
+ template<__any_input_iterator _InputIterator>
+ constexpr void
+ assign(_InputIterator __first, _InputIterator __last)
+ {
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ const auto __size = size();
+ const auto __end = _Base::end();
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
+ if (size() < __size)
+ _M_invalidate_after_nth(size());
+ else if (size() > __size)
+ this->_M_invalidate_if(_Equal(__end));
+ }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr void
+ assign_range(_Rg&& __rg)
+ {
+ _Base::assign_range(std::forward<_Rg>(__rg));
+ this->_M_invalidate_all();
+ }
+
+ constexpr void
+ assign(size_type __n, const _Tp& __u)
+ {
+ _Base::assign(__n, __u);
+ this->_M_invalidate_all();
+ }
+
+ constexpr void
+ assign(initializer_list<_Tp> __il)
+ {
+ _Base::assign(__il);
+ this->_M_invalidate_all();
+ }
+
+ // iterators
+ [[nodiscard]]
+ constexpr iterator
+ begin() noexcept
+ { return { _Base::begin(), this }; }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ begin() const noexcept
+ { return { _Base::begin(), this }; }
+
+ [[nodiscard]]
+ constexpr iterator
+ end() noexcept
+ { return { _Base::end(), this }; }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ end() const noexcept
+ { return { _Base::end(), this }; }
+
+ [[nodiscard]]
+ constexpr reverse_iterator
+ rbegin() noexcept
+ { return reverse_iterator(end()); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ rbegin() const noexcept
+ { return const_reverse_iterator(end()); }
+
+ [[nodiscard]]
+ constexpr reverse_iterator
+ rend() noexcept { return reverse_iterator(begin()); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ rend() const noexcept { return const_reverse_iterator(begin()); }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ cbegin() const noexcept
+ { return { _Base::cbegin(), this }; }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ cend() const noexcept
+ { return { _Base::cend(), this }; }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ crbegin() const noexcept { return rbegin(); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ crend() const noexcept { return rend(); }
+
+ using _Base::empty;
+ using _Base::size;
+ using _Base::max_size;
+ using _Base::capacity;
+
+ constexpr void
+ resize(size_type __n)
+ {
+ _Base::resize(__n);
+ _M_invalidate_after_nth(__n);
+ }
+
+ constexpr void
+ resize(size_type __n, const _Tp& __c)
+ {
+ _Base::resize(__n, __c);
+ _M_invalidate_after_nth(__n);
+ }
+
+ using _Base::reserve;
+ using _Base::shrink_to_fit;
+
+ // element access
+ [[nodiscard]]
+ constexpr reference
+ operator[](size_type __n)
+ {
+ __glibcxx_check_subscript(__n);
+ return _Base::operator[](__n);
+ }
+
+ [[nodiscard]]
+ constexpr const_reference
+ operator[](size_type __n) const
+ {
+ __glibcxx_check_subscript(__n);
+ return _Base::operator[](__n);
+ }
+
+ using _Base::at;
+
+ [[nodiscard]]
+ constexpr reference
+ front()
+ {
+ __glibcxx_check_nonempty();
+ return data()[0];
+ }
+
+ [[nodiscard]]
+ constexpr const_reference
+ front() const
+ {
+ __glibcxx_check_nonempty();
+ return data()[0];
+ }
+
+ [[nodiscard]]
+ constexpr reference
+ back()
+ {
+ __glibcxx_check_nonempty();
+ return data()[size() - 1];
+ }
+
+ [[nodiscard]]
+ constexpr const_reference
+ back() const
+ {
+ __glibcxx_check_nonempty();
+ return data()[size() - 1];
+ }
+
+ using _Base::data;
+
+ template<typename... _Args>
+ constexpr _Tp&
+ emplace_back(_Args&&... __args)
+ {
+ const auto __end = _Base::cend();
+ _Tp& __res = _Base::emplace_back(std::forward<_Args>(__args)...);
+ this->_M_invalidate_if(_Equal(__end));
+ return __res;
+ }
+
+ constexpr _Tp&
+ push_back(const _Tp& __x)
+ { return emplace_back(__x); }
+
+ constexpr _Tp&
+ push_back(_Tp&& __x)
+ { return emplace_back(std::move(__x)); }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr void
+ append_range(_Rg&& __rg)
+ {
+ const auto __size = size();
+ const auto __end = _Base::cend();
+ _Base::append_range(__rg);
+ if (size() != __size)
+ this->_M_invalidate_if(_Equal(__end));
+ }
+
+ constexpr void
+ pop_back()
+ {
+ __glibcxx_check_nonempty();
+ _M_invalidate_after_nth(_Base::size() - 1);
+ _Base::pop_back();
+ }
+
+ template<typename... _Args>
+ constexpr _Tp*
+ try_emplace_back(_Args&&... __args)
+ {
+ auto __end = _Base::cend();
+ _Tp* __res = _Base::try_emplace_back(std::forward<_Args>(__args)...);
+
+ if (__res)
+ this->_M_invalidate_if(_Equal(__end));
+
+ return __res;
+ }
+
+ constexpr _Tp*
+ try_push_back(const _Tp& __x)
+ {
+ const auto __end = _Base::cend();
+ _Tp* __res = _Base::try_push_back(__x);
+
+ if (__res)
+ this->_M_invalidate_if(_Equal(__end));
+
+ return __res;
+ }
+
+ constexpr _Tp*
+ try_push_back(_Tp&& __x)
+ {
+ const auto __end = _Base::cend();
+ _Tp* __res = _Base::try_push_back(std::move(__x));
+
+ if (__res)
+ this->_M_invalidate_if(_Equal(__end));
+
+ return __res;
+ }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr ranges::borrowed_iterator_t<_Rg>
+ try_append_range(_Rg&& __rg)
+ {
+ const auto __size = size();
+ const auto __end = _Base::cend();
+ auto __res = _Base::try_append_range(__rg);
+ if (size() != __size)
+ this->_M_invalidate_if(_Equal(__end));
+
+ return __res;
+ }
+
+ template<typename... _Args>
+ constexpr _Tp&
+ unchecked_emplace_back(_Args&&... __args)
+ {
+ const auto __end = _Base::cend();
+ _Tp& __res =
+ _Base::unchecked_emplace_back(std::forward<_Args>(__args)...);
+
+ this->_M_invalidate_if(_Equal(__end));
+
+ return __res;
+ }
+
+ constexpr _Tp&
+ unchecked_push_back(const _Tp& __x)
+ { return unchecked_emplace_back(__x); }
+
+ constexpr _Tp&
+ unchecked_push_back(_Tp&& __x)
+ { return unchecked_emplace_back(std::move(__x)); }
+
+ template<typename... _Args>
+ constexpr iterator
+ emplace(const_iterator __position, _Args&&... __args)
+ {
+ if (std::is_constant_evaluated())
+ return iterator(_Base::emplace(__position.base(),
+ std::forward<_Args>(__args)...),
+ this);
+
+ __glibcxx_check_insert(__position);
+ const difference_type __offset = __position.base() - _Base::cbegin();
+ _Base_iterator __res = _Base::emplace(__position.base(),
+ std::forward<_Args>(__args)...);
+ _M_invalidate_after_nth(__offset);
+ return { __res, this };
+ }
+
+ constexpr iterator
+ insert(const_iterator __position, const _Tp& __x)
+ { return emplace(__position, __x); }
+
+ constexpr iterator
+ insert(const_iterator __position, _Tp&& __x)
+ { return emplace(__position, std::move(__x)); }
+
+ constexpr iterator
+ insert(const_iterator __position, size_type __n, const _Tp& __x)
+ {
+ if (std::is_constant_evaluated())
+ return iterator(_Base::insert(__position.base(), __n, __x), this);
+
+ __glibcxx_check_insert(__position);
+ const difference_type __offset = __position.base() - _Base::cbegin();
+ _Base_iterator __res = _Base::insert(__position.base(), __n, __x);
+ _M_invalidate_after_nth(__offset);
+ return { __res, this };
+ }
+
+ template<__any_input_iterator _InputIterator>
+ constexpr iterator
+ insert(const_iterator __position, _InputIterator __first,
+ _InputIterator __last)
+ {
+ if (std::is_constant_evaluated())
+ return iterator(_Base::insert(__position.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last)), this);
+
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
+
+ const difference_type __offset = __position.base() - _Base::cbegin();
+ _Base_iterator __res;
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ __res = _Base::insert(__position.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ __res = _Base::insert(__position.base(), __first, __last);
+
+ _M_invalidate_after_nth(__offset);
+ return { __res, this };
+ }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr iterator
+ insert_range(const_iterator __position, _Rg&& __rg)
+ {
+ const auto __size = size();
+ const difference_type __offset = __position.base() - _Base::cbegin();
+ auto __res = _Base::insert_range(__position.base(), __rg);
+ if (size() > __size)
+ this->_M_invalidate_after_nth(__offset);
+
+ return iterator(__res, this);
+ }
+
+ constexpr iterator
+ insert(const_iterator __position, initializer_list<_Tp> __il)
+ {
+ if (std::is_constant_evaluated())
+ return iterator(_Base::insert(__position.base(), __il), this);
+
+ __glibcxx_check_insert(__position);
+ const auto __size = size();
+ difference_type __offset = __position.base() - _Base::begin();
+ _Base_iterator __res = _Base::insert(__position.base(), __il);
+ if (size() > __size)
+ this->_M_invalidate_after_nth(__offset);
+ return iterator(__res, this);
+ }
+
+ constexpr iterator
+ erase(const_iterator __position)
+ {
+ if (std::is_constant_evaluated())
+ return iterator(_Base::erase(__position.base()), this);
+
+ __glibcxx_check_erase(__position);
+ difference_type __offset = __position.base() - _Base::cbegin();
+ _Base_iterator __res = _Base::erase(__position.base());
+ this->_M_invalidate_after_nth(__offset);
+ return iterator(__res, this);
+ }
+
+ constexpr iterator
+ erase(const_iterator __first, const_iterator __last)
+ {
+ if (std::is_constant_evaluated())
+ return iterator(_Base::erase(__first.base(), __last.base()),
+ this);
+
+ __glibcxx_check_erase_range(__first, __last);
+
+ if (__first.base() != __last.base())
+ {
+ difference_type __offset = __first.base() - _Base::cbegin();
+ _Base_iterator __res = _Base::erase(__first.base(),
+ __last.base());
+ this->_M_invalidate_after_nth(__offset);
+ return { __res, this };
+ }
+ else
+ return { _Base::begin() + (__first.base() - _Base::cbegin()), this };
+ }
+
+ constexpr void
+ swap(inplace_vector& __x)
+ noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)
+ {
+ this->_M_invalidate_all();
+ __x._M_invalidate_all();
+ _Base::swap(__x);
+ }
+
+ constexpr void
+ clear() noexcept
+ {
+ _Base::clear();
+ this->_M_invalidate_all();
+ }
+
+ constexpr friend bool
+ operator==(const inplace_vector& __x, const inplace_vector& __y)
+ { return __x._M_base() == __y._M_base(); }
+
+ constexpr friend auto
+ operator<=>(const inplace_vector& __x, const inplace_vector& __y)
+ requires requires (const _Tp __t) {
+ { __t < __t } -> __detail::__boolean_testable;
+ }
+ { return __x._M_base() <=> __y._M_base(); }
+
+ constexpr friend void
+ swap(inplace_vector& __x, inplace_vector& __y)
+ noexcept( noexcept(__x.swap(__y)) )
+ { __x.swap(__y); }
+
+ private:
+ constexpr _Base&
+ _M_base() noexcept { return *this; }
+
+ constexpr const _Base&
+ _M_base() const noexcept { return *this; }
+
+ constexpr void
+ _M_invalidate_after_nth(difference_type __n) noexcept
+ {
+ using _After_nth
+ = __gnu_debug::_After_nth_from<_Base_const_iterator>;
+ this->_M_invalidate_if(_After_nth(__n, _Base::cbegin()));
+ }
+ };
+
+ // specialization for zero capacity, that is required to be trivally copyable
+ // and empty regardless of _Tp.
+ template<typename _Tp>
+ class inplace_vector<_Tp, 0>
+ : public _GLIBCXX_STD_C::inplace_vector<_Tp, 0>
+ {
+ using _Base = _GLIBCXX_STD_C::inplace_vector<_Tp, 0>;
+
+ public:
+ // types:
+ using value_type = _Base::value_type;
+ using pointer = _Base::pointer;
+ using const_pointer = _Base::const_pointer;
+ using reference = _Base::reference;
+ using const_reference = _Base::const_reference;
+ using size_type = _Base::size_type;
+ using difference_type = _Base::difference_type;
+ using iterator = _Base::iterator;
+ using const_iterator = _Base::const_iterator;
+ using reverse_iterator = _Base::reverse_iterator;
+ using const_reverse_iterator = _Base::const_reverse_iterator;
+
+ inplace_vector() = default;
+
+ constexpr explicit
+ inplace_vector(size_type __n) : _Base(__n) { }
+
+ constexpr
+ inplace_vector(size_type __n, const _Tp& __value)
+ : _Base(__n, __value) { }
+
+ template<__any_input_iterator _InputIterator>
+ constexpr
+ inplace_vector(_InputIterator __first, _InputIterator __last)
+ : _Base(__gnu_debug::__base(
+ __glibcxx_check_valid_constructor_range(__first, __last)),
+ __gnu_debug::__base(__last)) { }
+
+ template <__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr
+ inplace_vector(from_range_t, _Rg&& __rg)
+ : _Base(from_range_t{}, std::forward<_Rg>(__rg)) { }
+
+ constexpr
+ inplace_vector(initializer_list<_Tp> __il)
+ : _Base(__il) { }
+
+ inplace_vector(const inplace_vector&) = default;
+ inplace_vector(inplace_vector&&) = default;
+
+ constexpr
+ ~inplace_vector() = default;
+
+ inplace_vector&
+ operator=(const inplace_vector&) = default;
+
+ inplace_vector&
+ operator=(inplace_vector&&) = default;
+
+ constexpr inplace_vector&
+ operator=(initializer_list<_Tp> __il)
+ {
+ _Base::operator=(__il);
+ return *this;
+ }
+
+ constexpr void
+ swap(inplace_vector& __x)
+ noexcept
+ { }
+ };
+} // namespace __debug
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<typename _Tp, size_t _Nm, typename _Predicate>
+ constexpr size_t
+ erase_if(__debug::inplace_vector<_Tp, _Nm>& __cont, _Predicate __pred)
+ {
+ if constexpr (_Nm != 0)
+ {
+ _GLIBCXX_STD_C::inplace_vector<_Tp, _Nm>& __ucont = __cont;
+ const auto __osz = __cont.size();
+ const auto __end = __ucont.end();
+ auto __removed = std::__remove_if(__ucont.begin(), __end,
+ std::move(__pred));
+ if (__removed != __end)
+ {
+ __cont.erase(__niter_wrap(__cont.cbegin(), __removed),
+ __cont.cend());
+ return __osz - __cont.size();
+ }
+ }
+
+ return 0;
+ }
+
+ template<typename _Tp, size_t _Nm, typename _Up = _Tp>
+ constexpr size_t
+ erase(__debug::inplace_vector<_Tp, _Nm>& __cont, const _Up& __value)
+ { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // __glibcxx_inplace_vector
+#endif // _GLIBCXX_DEBUG_INPLACE_VECTOR
diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list
index a9d974c..c502c7c 100644
--- a/libstdc++-v3/include/debug/list
+++ b/libstdc++-v3/include/debug/list
@@ -321,7 +321,8 @@ namespace __debug
void
resize(size_type __sz)
{
- this->_M_detach_singular();
+ const list* __this = this;
+ __this->_M_detach_singular();
// if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
@@ -338,7 +339,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
@@ -346,7 +347,8 @@ namespace __debug
void
resize(size_type __sz, const _Tp& __c)
{
- this->_M_detach_singular();
+ const list* __this = this;
+ __this->_M_detach_singular();
// if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
@@ -363,7 +365,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
@@ -371,7 +373,8 @@ namespace __debug
void
resize(size_type __sz, _Tp __c = _Tp())
{
- this->_M_detach_singular();
+ const list* __this = this;
+ __this->_M_detach_singular();
// if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
@@ -388,7 +391,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h
index 985a7ac..30469b0 100644
--- a/libstdc++-v3/include/debug/map.h
+++ b/libstdc++-v3/include/debug/map.h
@@ -455,7 +455,7 @@ namespace __debug
}
#endif // C++17
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
using node_type = typename _Base::node_type;
using insert_return_type = _Node_insert_return<iterator, node_type>;
@@ -601,7 +601,7 @@ namespace __debug
find(const key_type& __x)
{ return iterator(_Base::find(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -614,7 +614,7 @@ namespace __debug
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -629,7 +629,7 @@ namespace __debug
lower_bound(const key_type& __x)
{ return iterator(_Base::lower_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -642,7 +642,7 @@ namespace __debug
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -655,7 +655,7 @@ namespace __debug
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -668,7 +668,7 @@ namespace __debug
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -686,7 +686,7 @@ namespace __debug
iterator(__res.second, this));
}
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -707,7 +707,7 @@ namespace __debug
const_iterator(__res.second, this));
}
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h
index c187e51..db9e246 100644
--- a/libstdc++-v3/include/debug/multimap.h
+++ b/libstdc++-v3/include/debug/multimap.h
@@ -340,7 +340,7 @@ namespace __debug
_Base::insert(__first, __last);
}
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
using node_type = typename _Base::node_type;
node_type
@@ -483,7 +483,7 @@ namespace __debug
find(const key_type& __x)
{ return iterator(_Base::find(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -496,7 +496,7 @@ namespace __debug
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -511,7 +511,7 @@ namespace __debug
lower_bound(const key_type& __x)
{ return iterator(_Base::lower_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -524,7 +524,7 @@ namespace __debug
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -537,7 +537,7 @@ namespace __debug
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -550,7 +550,7 @@ namespace __debug
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -568,7 +568,7 @@ namespace __debug
iterator(__res.second, this));
}
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -589,7 +589,7 @@ namespace __debug
const_iterator(__res.second, this));
}
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h
index 41bf78d..156378a 100644
--- a/libstdc++-v3/include/debug/multiset.h
+++ b/libstdc++-v3/include/debug/multiset.h
@@ -311,7 +311,7 @@ namespace __debug
{ _Base::insert(__l); }
#endif
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
using node_type = typename _Base::node_type;
node_type
@@ -457,7 +457,7 @@ namespace __debug
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -485,7 +485,7 @@ namespace __debug
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -511,7 +511,7 @@ namespace __debug
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -547,7 +547,7 @@ namespace __debug
const_iterator(__res.second, this));
}
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h
index cf3f170..7491cc0 100644
--- a/libstdc++-v3/include/debug/safe_base.h
+++ b/libstdc++-v3/include/debug/safe_base.h
@@ -53,8 +53,10 @@ namespace __gnu_debug
public:
/** The sequence this iterator references; may be NULL to indicate
- a singular iterator. */
- _Safe_sequence_base* _M_sequence;
+ * a singular iterator. Stored as pointer-to-const because sequence
+ * could be declared as const.
+ */
+ const _Safe_sequence_base* _M_sequence;
/** The version number of this iterator. The sentinel value 0 is
* used to indicate an invalidated iterator (i.e., one that is
@@ -92,7 +94,7 @@ namespace __gnu_debug
: _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
{
if (!std::__is_constant_evaluated())
- this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant);
+ this->_M_attach(__seq, __constant);
}
/** Initializes the iterator to reference the same sequence that
@@ -115,7 +117,7 @@ namespace __gnu_debug
/** For use in _Safe_iterator. */
__gnu_cxx::__mutex&
- _M_get_mutex() throw ();
+ _M_get_mutex() _GLIBCXX_USE_NOEXCEPT;
/** Attaches this iterator to the given sequence, detaching it
* from whatever sequence it was attached to originally. If the
@@ -123,11 +125,12 @@ namespace __gnu_debug
* unattached.
*/
void
- _M_attach(_Safe_sequence_base* __seq, bool __constant);
+ _M_attach(const _Safe_sequence_base* __seq, bool __constant);
/** Likewise, but not thread-safe. */
void
- _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ();
+ _M_attach_single(const _Safe_sequence_base* __seq,
+ bool __constant) _GLIBCXX_USE_NOEXCEPT;
/** Detach the iterator for whatever sequence it is attached to,
* if any.
@@ -135,10 +138,23 @@ namespace __gnu_debug
void
_M_detach();
+#if !_GLIBCXX_INLINE_VERSION
+ private:
+ /***************************************************************/
+ /** Not-const method preserved for abi backward compatibility. */
+ void
+ _M_attach(_Safe_sequence_base* __seq, bool __constant);
+
+ void
+ _M_attach_single(_Safe_sequence_base* __seq,
+ bool __constant) _GLIBCXX_USE_NOEXCEPT;
+ /***************************************************************/
+#endif
+
public:
/** Likewise, but not thread-safe. */
void
- _M_detach_single() throw ();
+ _M_detach_single() _GLIBCXX_USE_NOEXCEPT;
/** Determines if we are attached to the given sequence. */
bool
@@ -147,13 +163,13 @@ namespace __gnu_debug
/** Is this iterator singular? */
_GLIBCXX_PURE bool
- _M_singular() const throw ();
+ _M_singular() const _GLIBCXX_USE_NOEXCEPT;
/** Can we compare this iterator to the given iterator @p __x?
Returns true if both iterators are nonsingular and reference
the same sequence. */
_GLIBCXX_PURE bool
- _M_can_compare(const _Safe_iterator_base& __x) const throw ();
+ _M_can_compare(const _Safe_iterator_base& __x) const _GLIBCXX_USE_NOEXCEPT;
/** Invalidate the iterator, making it singular. */
void
@@ -162,11 +178,11 @@ namespace __gnu_debug
/** Reset all member variables */
void
- _M_reset() throw ();
+ _M_reset() _GLIBCXX_USE_NOEXCEPT;
/** Unlink itself */
void
- _M_unlink() throw ()
+ _M_unlink() _GLIBCXX_USE_NOEXCEPT
{
if (_M_prior)
_M_prior->_M_next = _M_next;
@@ -238,22 +254,40 @@ namespace __gnu_debug
/** Notify all iterators that reference this sequence that the
sequence is being destroyed. */
_GLIBCXX20_CONSTEXPR
- ~_Safe_sequence_base()
+ ~_Safe_sequence_base() _GLIBCXX_NOEXCEPT
{
if (!std::__is_constant_evaluated())
this->_M_detach_all();
}
+ // Copy assignment invalidate all iterators.
+ _GLIBCXX20_CONSTEXPR _Safe_sequence_base&
+ operator=(const _Safe_sequence_base&) _GLIBCXX_NOEXCEPT
+ {
+ _M_invalidate_all();
+ return *this;
+ }
+
+#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR _Safe_sequence_base&
+ operator=(_Safe_sequence_base&& __x) noexcept
+ {
+ _M_invalidate_all();
+ __x._M_invalidate_all();
+ return *this;
+ }
+#endif
+
/** Detach all iterators, leaving them singular. */
void
- _M_detach_all();
+ _M_detach_all() const;
/** Detach all singular iterators.
* @post for all iterators i attached to this sequence,
* i->_M_version == _M_version.
*/
void
- _M_detach_singular();
+ _M_detach_singular() const;
/** Revalidates all attached singular iterators. This method may
* be used to validate iterators that were invalidated before
@@ -261,7 +295,7 @@ namespace __gnu_debug
* valid again).
*/
void
- _M_revalidate_singular();
+ _M_revalidate_singular() const;
/** Swap this sequence with the given sequence. This operation
* also swaps ownership of the iterators, so that when the
@@ -269,33 +303,54 @@ namespace __gnu_debug
* one container now reference the other container.
*/
void
- _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT;
+ _M_swap(const _Safe_sequence_base& __x) const _GLIBCXX_USE_NOEXCEPT;
/** For use in _Safe_sequence. */
__gnu_cxx::__mutex&
- _M_get_mutex() throw ();
+ _M_get_mutex() const _GLIBCXX_USE_NOEXCEPT;
/** Invalidates all iterators. */
- void
+ _GLIBCXX20_CONSTEXPR void
_M_invalidate_all() const
{ if (++_M_version == 0) _M_version = 1; }
private:
+#if !_GLIBCXX_INLINE_VERSION
+ /***************************************************************/
+ /** Not-const method preserved for abi backward compatibility. */
+ void
+ _M_detach_all();
+
+ void
+ _M_detach_singular();
+
+ void
+ _M_revalidate_singular();
+
+ void
+ _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT;
+
+ __gnu_cxx::__mutex&
+ _M_get_mutex() _GLIBCXX_USE_NOEXCEPT;
+ /***************************************************************/
+#endif
+
/** Attach an iterator to this sequence. */
void
- _M_attach(_Safe_iterator_base* __it, bool __constant);
+ _M_attach(_Safe_iterator_base* __it, bool __constant) const;
/** Likewise but not thread safe. */
void
- _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ();
+ _M_attach_single(_Safe_iterator_base* __it,
+ bool __constant) const _GLIBCXX_USE_NOEXCEPT;
/** Detach an iterator from this sequence */
void
- _M_detach(_Safe_iterator_base* __it);
+ _M_detach(_Safe_iterator_base* __it) const;
/** Likewise but not thread safe. */
void
- _M_detach_single(_Safe_iterator_base* __it) throw ();
+ _M_detach_single(_Safe_iterator_base* __it) const _GLIBCXX_USE_NOEXCEPT;
};
} // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_container.h b/libstdc++-v3/include/debug/safe_container.h
index cb1e69a..2d0fbb8 100644
--- a/libstdc++-v3/include/debug/safe_container.h
+++ b/libstdc++-v3/include/debug/safe_container.h
@@ -44,9 +44,9 @@ namespace __gnu_debug
typedef _SafeBase<_SafeContainer> _Base;
_GLIBCXX20_CONSTEXPR
- _SafeContainer&
- _M_cont() _GLIBCXX_NOEXCEPT
- { return *static_cast<_SafeContainer*>(this); }
+ const _SafeContainer&
+ _M_cont() const _GLIBCXX_NOEXCEPT
+ { return *static_cast<const _SafeContainer*>(this); }
protected:
#if __cplusplus >= 201103L
@@ -56,6 +56,11 @@ namespace __gnu_debug
private:
_GLIBCXX20_CONSTEXPR
+ void
+ _M_swap_base(const _Safe_container& __x) const noexcept
+ { _Base::_M_swap(__x); }
+
+ _GLIBCXX20_CONSTEXPR
_Safe_container(_Safe_container&& __x, const _Alloc&, std::true_type)
: _Safe_container(std::move(__x))
{ }
@@ -67,7 +72,7 @@ namespace __gnu_debug
if (!std::__is_constant_evaluated())
{
if (__x._M_cont().get_allocator() == __a)
- _Base::_M_swap(__x);
+ _M_swap_base(__x);
else
__x._M_invalidate_all();
}
@@ -81,17 +86,22 @@ namespace __gnu_debug
{ }
#endif
- // Copy assignment invalidate all iterators.
- _GLIBCXX20_CONSTEXPR
+#if __cplusplus < 201103L
_Safe_container&
- operator=(const _Safe_container&) _GLIBCXX_NOEXCEPT
+ operator=(const _Safe_container& __x)
{
- if (!std::__is_constant_evaluated())
- this->_M_invalidate_all();
+ _Base::operator=(__x);
return *this;
}
-#if __cplusplus >= 201103L
+ void
+ _M_swap(const _Safe_container& __x) const throw()
+ { _Base::_M_swap(__x); }
+#else
+ _GLIBCXX20_CONSTEXPR
+ _Safe_container&
+ operator=(const _Safe_container&) noexcept = default;
+
_GLIBCXX20_CONSTEXPR
_Safe_container&
operator=(_Safe_container&& __x) noexcept
@@ -115,12 +125,12 @@ namespace __gnu_debug
bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
|| _M_cont().get_allocator() == __x._M_cont().get_allocator();
if (__xfer_memory)
- _Base::_M_swap(__x);
+ _M_swap_base(__x);
else
this->_M_invalidate_all();
}
else
- _Base::_M_swap(__x);
+ _M_swap_base(__x);
__x._M_invalidate_all();
return *this;
@@ -128,7 +138,7 @@ namespace __gnu_debug
_GLIBCXX20_CONSTEXPR
void
- _M_swap(_Safe_container& __x) noexcept
+ _M_swap(const _Safe_container& __x) const noexcept
{
if (_IsCxx11AllocatorAware)
{
@@ -139,7 +149,7 @@ namespace __gnu_debug
__x._M_cont()._M_base());
}
- _Base::_M_swap(__x);
+ _M_swap_base(__x);
}
#endif
};
diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h
index 7c56338..80ed957 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -224,7 +224,7 @@ namespace __gnu_debug
_M_message(__msg_init_copy_singular)
._M_iterator(*this, "this")
._M_iterator(__x, "other"));
- _Safe_sequence_base* __seq = __x._M_sequence;
+ const _Safe_sequence_base* __seq = __x._M_sequence;
__x._M_detach();
std::swap(base(), __x.base());
_M_attach(__seq);
@@ -445,12 +445,12 @@ namespace __gnu_debug
/** Attach iterator to the given sequence. */
void
- _M_attach(_Safe_sequence_base* __seq)
+ _M_attach(const _Safe_sequence_base* __seq)
{ _Safe_base::_M_attach(__seq, _S_constant()); }
/** Likewise, but not thread-safe. */
void
- _M_attach_single(_Safe_sequence_base* __seq)
+ _M_attach_single(const _Safe_sequence_base* __seq)
{ _Safe_base::_M_attach_single(__seq, _S_constant()); }
/// Is the iterator dereferenceable?
@@ -500,7 +500,13 @@ namespace __gnu_debug
typename __gnu_cxx::__conditional_type<
_IsConstant::__value, const _Sequence*, _Sequence*>::__type
_M_get_sequence() const
- { return static_cast<_Sequence*>(_M_sequence); }
+ {
+ // Looks like not const-correct, but if _IsConstant the constness
+ // is restored when returning the sequence pointer and if not
+ // _IsConstant we are allowed to remove constness.
+ return static_cast<_Sequence*>
+ (const_cast<_Safe_sequence_base*>(_M_sequence));
+ }
// Get distance to __rhs.
typename _Distance_traits<_Iterator>::__type
@@ -1108,21 +1114,31 @@ namespace __gnu_debug
/** Safe iterators know how to check if they form a valid range. */
template<typename _Iterator, typename _Sequence, typename _Category>
+ _GLIBCXX20_CONSTEXPR
inline bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence,
_Category>& __first,
const _Safe_iterator<_Iterator, _Sequence,
_Category>& __last,
typename _Distance_traits<_Iterator>::__type& __dist)
- { return __first._M_valid_range(__last, __dist); }
+ {
+ if (std::__is_constant_evaluated())
+ return true;
+
+ return __first._M_valid_range(__last, __dist);
+ }
template<typename _Iterator, typename _Sequence, typename _Category>
+ _GLIBCXX20_CONSTEXPR
inline bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence,
_Category>& __first,
const _Safe_iterator<_Iterator, _Sequence,
_Category>& __last)
{
+ if (std::__is_constant_evaluated())
+ return true;
+
typename _Distance_traits<_Iterator>::__type __dist;
return __first._M_valid_range(__last, __dist);
}
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h
index c84f4f1..47b3a80 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.h
+++ b/libstdc++-v3/include/debug/safe_local_iterator.h
@@ -52,15 +52,15 @@ namespace __gnu_debug
/** \brief Safe iterator wrapper.
*
* The class template %_Safe_local_iterator is a wrapper around an
- * iterator that tracks the iterator's movement among sequences and
- * checks that operations performed on the "safe" iterator are
+ * iterator that tracks the iterator's movement among unordered containers
+ * and checks that operations performed on the "safe" iterator are
* legal. In additional to the basic iterator operations (which are
* validated, and then passed to the underlying iterator),
* %_Safe_local_iterator has member functions for iterator invalidation,
- * attaching/detaching the iterator from sequences, and querying
+ * attaching/detaching the iterator from unordered containers, and querying
* the iterator's state.
*/
- template<typename _Iterator, typename _Sequence>
+ template<typename _Iterator, typename _UContainer>
class _Safe_local_iterator
: private _Iterator
, public _Safe_local_iterator_base
@@ -68,28 +68,27 @@ namespace __gnu_debug
typedef _Iterator _Iter_base;
typedef _Safe_local_iterator_base _Safe_base;
- typedef typename _Sequence::size_type size_type;
+ typedef typename _UContainer::size_type size_type;
typedef std::iterator_traits<_Iterator> _Traits;
- typedef std::__are_same<
- typename _Sequence::_Base::const_local_iterator,
- _Iterator> _IsConstant;
+ using _IsConstant = std::__are_same<
+ typename _UContainer::_Base::const_local_iterator, _Iterator>;
- typedef typename __gnu_cxx::__conditional_type<_IsConstant::__value,
- typename _Sequence::_Base::local_iterator,
- typename _Sequence::_Base::const_local_iterator>::__type
- _OtherIterator;
+ using _OtherIterator = std::__conditional_t<
+ _IsConstant::__value,
+ typename _UContainer::_Base::local_iterator,
+ typename _UContainer::_Base::const_local_iterator>;
typedef _Safe_local_iterator _Self;
- typedef _Safe_local_iterator<_OtherIterator, _Sequence> _OtherSelf;
+ typedef _Safe_local_iterator<_OtherIterator, _UContainer> _OtherSelf;
struct _Unchecked { };
_Safe_local_iterator(const _Safe_local_iterator& __x,
_Unchecked) noexcept
: _Iter_base(__x.base())
- { _M_attach(__x._M_sequence); }
+ { _M_attach(__x._M_safe_container()); }
public:
typedef _Iterator iterator_type;
@@ -104,12 +103,13 @@ namespace __gnu_debug
/**
* @brief Safe iterator construction from an unsafe iterator and
- * its sequence.
+ * its unordered container.
*
- * @pre @p seq is not NULL
+ * @pre @p cont is not NULL
* @post this is not singular
*/
- _Safe_local_iterator(_Iterator __i, const _Safe_sequence_base* __cont)
+ _Safe_local_iterator(_Iterator __i,
+ const _Safe_unordered_container_base* __cont)
: _Iter_base(__i), _Safe_base(__cont, _S_constant())
{ }
@@ -126,7 +126,7 @@ namespace __gnu_debug
_M_message(__msg_init_copy_singular)
._M_iterator(*this, "this")
._M_iterator(__x, "other"));
- _M_attach(__x._M_sequence);
+ _M_attach(__x._M_safe_container());
}
/**
@@ -141,7 +141,7 @@ namespace __gnu_debug
_M_message(__msg_init_copy_singular)
._M_iterator(*this, "this")
._M_iterator(__x, "other"));
- auto __cont = __x._M_sequence;
+ auto __cont = __x._M_safe_container();
__x._M_detach();
std::swap(base(), __x.base());
_M_attach(__cont);
@@ -156,7 +156,7 @@ namespace __gnu_debug
const _Safe_local_iterator<_MutableIterator,
typename __gnu_cxx::__enable_if<_IsConstant::__value &&
std::__are_same<_MutableIterator, _OtherIterator>::__value,
- _Sequence>::__type>& __x) noexcept
+ _UContainer>::__type>& __x) noexcept
: _Iter_base(__x.base())
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -166,7 +166,7 @@ namespace __gnu_debug
_M_message(__msg_init_const_singular)
._M_iterator(*this, "this")
._M_iterator(__x, "other"));
- _M_attach(__x._M_sequence);
+ _M_attach(__x._M_safe_container());
}
/**
@@ -193,7 +193,7 @@ namespace __gnu_debug
{
_M_detach();
base() = __x.base();
- _M_attach(__x._M_sequence);
+ _M_attach(__x._M_safe_container());
}
return *this;
@@ -225,7 +225,7 @@ namespace __gnu_debug
{
_M_detach();
base() = __x.base();
- _M_attach(__x._M_sequence);
+ _M_attach(__x._M_safe_container());
}
__x._M_detach();
@@ -318,15 +318,15 @@ namespace __gnu_debug
*/
operator _Iterator() const { return *this; }
- /** Attach iterator to the given sequence. */
+ /** Attach iterator to the given unordered container. */
void
- _M_attach(_Safe_sequence_base* __seq)
- { _Safe_base::_M_attach(__seq, _S_constant()); }
+ _M_attach(const _Safe_unordered_container_base* __cont)
+ { _Safe_base::_M_attach(__cont, _S_constant()); }
/** Likewise, but not thread-safe. */
void
- _M_attach_single(_Safe_sequence_base* __seq)
- { _Safe_base::_M_attach_single(__seq, _S_constant()); }
+ _M_attach_single(const _Safe_unordered_container_base* __cont)
+ { _Safe_base::_M_attach_single(__cont, _S_constant()); }
/// Is the iterator dereferenceable?
bool
@@ -353,25 +353,31 @@ namespace __gnu_debug
typename _Distance_traits<_Iterator>::__type
_M_get_distance_to(const _Safe_local_iterator& __rhs) const;
- // The sequence this iterator references.
- typename __gnu_cxx::__conditional_type<
- _IsConstant::__value, const _Sequence*, _Sequence*>::__type
- _M_get_sequence() const
- { return static_cast<_Sequence*>(_M_sequence); }
+ // The unordered container this iterator references.
+ std::__conditional_t<
+ _IsConstant::__value, const _UContainer*, _UContainer*>
+ _M_get_ucontainer() const
+ {
+ // Looks like not const-correct, but if _IsConstant the constness
+ // is restored when returning the container pointer and if not
+ // _IsConstant we are allowed to remove constness.
+ return static_cast<_UContainer*>
+ (const_cast<_Safe_unordered_container_base*>(_M_safe_container()));
+ }
- /// Is this iterator equal to the sequence's begin(bucket) iterator?
+ /// Is this iterator equal to the container's begin(bucket) iterator?
bool _M_is_begin() const
- { return base() == _M_get_sequence()->_M_base().begin(bucket()); }
+ { return base() == _M_get_ucontainer()->_M_base().begin(bucket()); }
- /// Is this iterator equal to the sequence's end(bucket) iterator?
+ /// Is this iterator equal to the container's end(bucket) iterator?
bool _M_is_end() const
- { return base() == _M_get_sequence()->_M_base().end(bucket()); }
+ { return base() == _M_get_ucontainer()->_M_base().end(bucket()); }
/// Is this iterator part of the same bucket as the other one?
template<typename _Other>
bool
_M_in_same_bucket(const _Safe_local_iterator<_Other,
- _Sequence>& __other) const
+ _UContainer>& __other) const
{ return bucket() == __other.bucket(); }
friend inline bool
@@ -404,31 +410,31 @@ namespace __gnu_debug
};
/** Safe local iterators know how to check if they form a valid range. */
- template<typename _Iterator, typename _Sequence>
+ template<typename _Iterator, typename _UContainer>
inline bool
- __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
- const _Safe_local_iterator<_Iterator, _Sequence>& __last,
+ __valid_range(const _Safe_local_iterator<_Iterator, _UContainer>& __first,
+ const _Safe_local_iterator<_Iterator, _UContainer>& __last,
typename _Distance_traits<_Iterator>::__type& __dist_info)
{ return __first._M_valid_range(__last, __dist_info); }
- template<typename _Iterator, typename _Sequence>
+ template<typename _Iterator, typename _UContainer>
inline bool
- __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
- const _Safe_local_iterator<_Iterator, _Sequence>& __last)
+ __valid_range(const _Safe_local_iterator<_Iterator, _UContainer>& __first,
+ const _Safe_local_iterator<_Iterator, _UContainer>& __last)
{
typename _Distance_traits<_Iterator>::__type __dist_info;
return __first._M_valid_range(__last, __dist_info);
}
#if __cplusplus < 201103L
- template<typename _Iterator, typename _Sequence>
- struct _Unsafe_type<_Safe_local_iterator<_Iterator, _Sequence> >
+ template<typename _Iterator, typename _UContainer>
+ struct _Unsafe_type<_Safe_local_iterator<_Iterator, _UContainer> >
{ typedef _Iterator _Type; };
#endif
- template<typename _Iterator, typename _Sequence>
+ template<typename _Iterator, typename _UContainer>
inline _Iterator
- __unsafe(const _Safe_local_iterator<_Iterator, _Sequence>& __it)
+ __unsafe(const _Safe_local_iterator<_Iterator, _UContainer>& __it)
{ return __it.base(); }
} // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.tcc b/libstdc++-v3/include/debug/safe_local_iterator.tcc
index 71e5320..10fec3f 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_local_iterator.tcc
@@ -44,7 +44,7 @@ namespace __gnu_debug
if (__rhs._M_is_end())
return
{
- _M_get_sequence()->bucket_size(bucket()),
+ _M_get_ucontainer()->bucket_size(bucket()),
__dp_exact
};
@@ -56,7 +56,7 @@ namespace __gnu_debug
if (__rhs._M_is_begin())
return
{
- -_M_get_sequence()->bucket_size(bucket()),
+ -_M_get_ucontainer()->bucket_size(bucket()),
__dp_exact
};
diff --git a/libstdc++-v3/include/debug/safe_sequence.h b/libstdc++-v3/include/debug/safe_sequence.h
index 6b35afa..9120044 100644
--- a/libstdc++-v3/include/debug/safe_sequence.h
+++ b/libstdc++-v3/include/debug/safe_sequence.h
@@ -46,6 +46,7 @@ namespace __gnu_debug
_Type __value;
public:
+ _GLIBCXX20_CONSTEXPR
explicit _Not_equal_to(const _Type& __v) : __value(__v) { }
bool
@@ -61,6 +62,7 @@ namespace __gnu_debug
_Type __value;
public:
+ _GLIBCXX20_CONSTEXPR
explicit _Equal_to(const _Type& __v) : __value(__v) { }
bool
@@ -80,6 +82,7 @@ namespace __gnu_debug
difference_type _M_n;
public:
+ _GLIBCXX20_CONSTEXPR
_After_nth_from(const difference_type& __n, const _Iterator& __base)
: _M_base(__base), _M_n(__n) { }
@@ -113,8 +116,8 @@ namespace __gnu_debug
true. @c __pred will be invoked with the normal iterators nested
in the safe ones. */
template<typename _Predicate>
- void
- _M_invalidate_if(_Predicate __pred);
+ _GLIBCXX20_CONSTEXPR void
+ _M_invalidate_if(_Predicate __pred) const;
/** Transfers all iterators @c x that reference @c from sequence,
are not singular, and for which @c __pred(x) returns @c
@@ -122,7 +125,8 @@ namespace __gnu_debug
in the safe ones. */
template<typename _Predicate>
void
- _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred);
+ _M_transfer_from_if(const _Safe_sequence& __from,
+ _Predicate __pred) const;
};
/// Like _Safe_sequence but with a special _M_invalidate_all implementation
@@ -131,14 +135,39 @@ namespace __gnu_debug
class _Safe_node_sequence
: public _Safe_sequence<_Sequence>
{
+ public:
+#if __cplusplus >= 201103L
+ _Safe_node_sequence() = default;
+ _Safe_node_sequence(_Safe_node_sequence&&) = default;
+ _Safe_node_sequence(_Safe_node_sequence const&) = default;
+
+ _GLIBCXX20_CONSTEXPR _Safe_node_sequence&
+ operator=(_Safe_node_sequence&& __x) noexcept
+ {
+ _M_invalidate_all();
+ __x._M_invalidate_all();
+ return *this;
+ }
+#endif
+
+ _GLIBCXX20_CONSTEXPR _Safe_node_sequence&
+ operator=(const _Safe_node_sequence&) _GLIBCXX_NOEXCEPT
+ {
+ _M_invalidate_all();
+ return *this;
+ }
+
protected:
- void
- _M_invalidate_all()
+ _GLIBCXX20_CONSTEXPR void
+ _M_invalidate_all() const
{
+ if (std::__is_constant_evaluated())
+ return;
+
typedef typename _Sequence::const_iterator _Const_iterator;
typedef typename _Const_iterator::iterator_type _Base_const_iterator;
typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
- const _Sequence& __seq = *static_cast<_Sequence*>(this);
+ const _Sequence& __seq = *static_cast<const _Sequence*>(this);
this->_M_invalidate_if(_Not_equal(__seq._M_base().end()));
}
};
diff --git a/libstdc++-v3/include/debug/safe_sequence.tcc b/libstdc++-v3/include/debug/safe_sequence.tcc
index 336bf2a..720a184 100644
--- a/libstdc++-v3/include/debug/safe_sequence.tcc
+++ b/libstdc++-v3/include/debug/safe_sequence.tcc
@@ -33,10 +33,13 @@ namespace __gnu_debug
{
template<typename _Sequence>
template<typename _Predicate>
- void
+ _GLIBCXX20_CONSTEXPR void
_Safe_sequence<_Sequence>::
- _M_invalidate_if(_Predicate __pred)
+ _M_invalidate_if(_Predicate __pred) const
{
+ if (std::__is_constant_evaluated())
+ return;
+
typedef typename _Sequence::iterator iterator;
typedef typename _Sequence::const_iterator const_iterator;
@@ -66,7 +69,7 @@ namespace __gnu_debug
template<typename _Predicate>
void
_Safe_sequence<_Sequence>::
- _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred)
+ _M_transfer_from_if(const _Safe_sequence& __from, _Predicate __pred) const
{
if (this == std::__addressof(__from))
return;
@@ -104,7 +107,7 @@ namespace __gnu_debug
}
for (_Safe_iterator_base* __iter2 = __from._M_const_iterators;
- __iter2;)
+ __iter2;)
{
_Safe_iterator_base* __victim_base = __iter2;
const_iterator* __victim =
diff --git a/libstdc++-v3/include/debug/safe_unordered_base.h b/libstdc++-v3/include/debug/safe_unordered_base.h
index 1547f5b..c7b98a5 100644
--- a/libstdc++-v3/include/debug/safe_unordered_base.h
+++ b/libstdc++-v3/include/debug/safe_unordered_base.h
@@ -49,6 +49,10 @@ namespace __gnu_debug
*/
class _Safe_local_iterator_base : public _Safe_iterator_base
{
+ public:
+ const _Safe_unordered_container_base*
+ _M_safe_container() const noexcept;
+
protected:
/** Initializes the iterator and makes it singular. */
_Safe_local_iterator_base()
@@ -61,32 +65,32 @@ namespace __gnu_debug
* singular. Otherwise, the iterator will reference @p __seq and
* be nonsingular.
*/
- _Safe_local_iterator_base(const _Safe_sequence_base* __seq, bool __constant)
- { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); }
+ _Safe_local_iterator_base(const _Safe_unordered_container_base* __seq,
+ bool __constant)
+ { _M_attach(__seq, __constant); }
/** Initializes the iterator to reference the same container that
@p __x does. @p __constant is true if this is a constant
iterator, and false if it is mutable. */
_Safe_local_iterator_base(const _Safe_local_iterator_base& __x,
bool __constant)
- { this->_M_attach(__x._M_sequence, __constant); }
+ { this->_M_attach(__x._M_safe_container(), __constant); }
~_Safe_local_iterator_base() { this->_M_detach(); }
- _Safe_unordered_container_base*
- _M_get_container() const noexcept;
-
/** Attaches this iterator to the given container, detaching it
* from whatever container it was attached to originally. If the
* new container is the NULL pointer, the iterator is left
* unattached.
*/
void
- _M_attach(_Safe_sequence_base* __seq, bool __constant);
+ _M_attach(const _Safe_unordered_container_base* __cont,
+ bool __constant);
/** Likewise, but not thread-safe. */
void
- _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ();
+ _M_attach_single(const _Safe_unordered_container_base* __cont,
+ bool __constant) noexcept;
/** Detach the iterator for whatever container it is attached to,
* if any.
@@ -96,7 +100,19 @@ namespace __gnu_debug
/** Likewise, but not thread-safe. */
void
- _M_detach_single() throw ();
+ _M_detach_single() noexcept;
+
+#if !_GLIBCXX_INLINE_VERSION
+ private:
+ /***************************************************************/
+ /** Not-const method preserved for abi backward compatibility. */
+ void
+ _M_attach(_Safe_sequence_base* __seq, bool __constant);
+
+ void
+ _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept;
+ /***************************************************************/
+#endif
};
/**
@@ -124,10 +140,10 @@ namespace __gnu_debug
public:
/// The list of mutable local iterators that reference this container
- _Safe_iterator_base* _M_local_iterators;
+ mutable _Safe_iterator_base* _M_local_iterators;
/// The list of constant local iterators that reference this container
- _Safe_iterator_base* _M_const_local_iterators;
+ mutable _Safe_iterator_base* _M_const_local_iterators;
protected:
// Initialize with a version number of 1 and no iterators
@@ -146,6 +162,12 @@ namespace __gnu_debug
: _Safe_unordered_container_base()
{ this->_M_swap(__x); }
+ _Safe_unordered_container_base&
+ operator=(_Safe_unordered_container_base const&) = default;
+
+ _Safe_unordered_container_base&
+ operator=(_Safe_unordered_container_base&&) = default;
+
/** Notify all iterators that reference this container that the
container is being destroyed. */
~_Safe_unordered_container_base() noexcept
@@ -153,7 +175,7 @@ namespace __gnu_debug
/** Detach all iterators, leaving them singular. */
void
- _M_detach_all();
+ _M_detach_all() const;
/** Swap this container with the given container. This operation
* also swaps ownership of the iterators, so that when the
@@ -161,25 +183,42 @@ namespace __gnu_debug
* one container now reference the other container.
*/
void
- _M_swap(_Safe_unordered_container_base& __x) noexcept;
+ _M_swap(const _Safe_unordered_container_base& __x) const noexcept;
private:
+#if !_GLIBCXX_INLINE_VERSION
+ /***************************************************************/
+ /** Not-const method preserved for abi backward compatibility. */
+ void
+ _M_detach_all();
+
+ void
+ _M_swap(_Safe_unordered_container_base& __x) noexcept;
+ /***************************************************************/
+#endif
+
/** Attach an iterator to this container. */
void
- _M_attach_local(_Safe_iterator_base* __it, bool __constant);
+ _M_attach_local(_Safe_iterator_base* __it, bool __constant) const;
/** Likewise but not thread safe. */
void
- _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ();
+ _M_attach_local_single(_Safe_iterator_base* __it,
+ bool __constant) const noexcept;
/** Detach an iterator from this container */
void
- _M_detach_local(_Safe_iterator_base* __it);
+ _M_detach_local(_Safe_iterator_base* __it) const;
/** Likewise but not thread safe. */
void
- _M_detach_local_single(_Safe_iterator_base* __it) throw ();
+ _M_detach_local_single(_Safe_iterator_base* __it) const noexcept;
};
+
+ inline const _Safe_unordered_container_base*
+ _Safe_local_iterator_base::
+ _M_safe_container() const noexcept
+ { return static_cast<const _Safe_unordered_container_base*>(_M_sequence); }
} // namespace __gnu_debug
#endif
diff --git a/libstdc++-v3/include/debug/safe_unordered_container.h b/libstdc++-v3/include/debug/safe_unordered_container.h
index 2ba27db..b67b7e0 100644
--- a/libstdc++-v3/include/debug/safe_unordered_container.h
+++ b/libstdc++-v3/include/debug/safe_unordered_container.h
@@ -62,6 +62,10 @@ namespace __gnu_debug
_M_cont() noexcept
{ return *static_cast<_Container*>(this); }
+ const _Safe_unordered_container*
+ _M_self() const
+ { return this; }
+
protected:
void
_M_invalidate_locals()
diff --git a/libstdc++-v3/include/debug/safe_unordered_container.tcc b/libstdc++-v3/include/debug/safe_unordered_container.tcc
index 6819389..0732e63 100644
--- a/libstdc++-v3/include/debug/safe_unordered_container.tcc
+++ b/libstdc++-v3/include/debug/safe_unordered_container.tcc
@@ -40,7 +40,7 @@ namespace __gnu_debug
typedef typename _Container::iterator iterator;
typedef typename _Container::const_iterator const_iterator;
- __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
+ __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
{
iterator* __victim = static_cast<iterator*>(__iter);
@@ -72,7 +72,7 @@ namespace __gnu_debug
typedef typename _Container::local_iterator local_iterator;
typedef typename _Container::const_local_iterator const_local_iterator;
- __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
+ __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_local_iterators; __iter;)
{
local_iterator* __victim = static_cast<local_iterator*>(__iter);
diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h
index 6ec8338..9b42862 100644
--- a/libstdc++-v3/include/debug/set.h
+++ b/libstdc++-v3/include/debug/set.h
@@ -319,7 +319,7 @@ namespace __debug
{ _Base::insert(__l); }
#endif
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
using node_type = typename _Base::node_type;
using insert_return_type = _Node_insert_return<iterator, node_type>;
@@ -468,7 +468,7 @@ namespace __debug
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -496,7 +496,7 @@ namespace __debug
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -522,7 +522,7 @@ namespace __debug
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
@@ -558,7 +558,7 @@ namespace __debug
const_iterator(__res.second, this));
}
-#if __cplusplus > 201103L
+#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
template<typename _Kt,
typename _Req =
typename __has_is_transparent<_Compare, _Kt>::type>
diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map
index 448f681..c90e44a 100644
--- a/libstdc++-v3/include/debug/unordered_map
+++ b/libstdc++-v3/include/debug/unordered_map
@@ -175,6 +175,12 @@ namespace __debug
template<typename _InputIterator>
unordered_map(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a)
+ : unordered_map(__first, __last, 0, hasher(), key_equal(), __a)
+ { }
+
+ template<typename _InputIterator>
+ unordered_map(_InputIterator __first, _InputIterator __last,
size_type __n,
const allocator_type& __a)
: unordered_map(__first, __last, __n, hasher(), key_equal(), __a)
@@ -189,6 +195,11 @@ namespace __debug
{ }
unordered_map(initializer_list<value_type> __l,
+ const allocator_type& __a)
+ : unordered_map(__l, 0, hasher(), key_equal(), __a)
+ { }
+
+ unordered_map(initializer_list<value_type> __l,
size_type __n,
const allocator_type& __a)
: unordered_map(__l, __n, hasher(), key_equal(), __a)
@@ -550,7 +561,7 @@ namespace __debug
}
#endif // C++17
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
using node_type = typename _Base::node_type;
using insert_return_type = _Node_insert_return<iterator, node_type>;
@@ -621,7 +632,7 @@ namespace __debug
find(const key_type& __key)
{ return { _Base::find(__key), this }; }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -634,7 +645,7 @@ namespace __debug
find(const key_type& __key) const
{ return { _Base::find(__key), this }; }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -655,7 +666,7 @@ namespace __debug
return { { __res.first, this }, { __res.second, this } };
}
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -674,7 +685,7 @@ namespace __debug
return { { __res.first, this }, { __res.second, this } };
}
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -779,7 +790,7 @@ namespace __debug
return __next;
}
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
node_type
_M_extract(_Base_const_iterator __victim)
{
@@ -1053,6 +1064,12 @@ namespace __debug
template<typename _InputIterator>
unordered_multimap(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a)
+ : unordered_multimap(__first, __last, 0, hasher(), key_equal(), __a)
+ { }
+
+ template<typename _InputIterator>
+ unordered_multimap(_InputIterator __first, _InputIterator __last,
size_type __n,
const allocator_type& __a)
: unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a)
@@ -1066,6 +1083,11 @@ namespace __debug
{ }
unordered_multimap(initializer_list<value_type> __l,
+ const allocator_type& __a)
+ : unordered_multimap(__l, 0, hasher(), key_equal(), __a)
+ { }
+
+ unordered_multimap(initializer_list<value_type> __l,
size_type __n,
const allocator_type& __a)
: unordered_multimap(__l, __n, hasher(), key_equal(), __a)
@@ -1340,7 +1362,7 @@ namespace __debug
_M_check_rehashed(__bucket_count);
}
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
using node_type = typename _Base::node_type;
node_type
@@ -1406,7 +1428,7 @@ namespace __debug
find(const key_type& __key)
{ return { _Base::find(__key), this }; }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -1419,7 +1441,7 @@ namespace __debug
find(const key_type& __key) const
{ return { _Base::find(__key), this }; }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -1440,7 +1462,7 @@ namespace __debug
return { { __res.first, this }, { __res.second, this } };
}
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -1459,7 +1481,7 @@ namespace __debug
return { { __res.first, this }, { __res.second, this } };
}
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -1565,7 +1587,7 @@ namespace __debug
return __next;
}
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
node_type
_M_extract(_Base_const_iterator __victim)
{
diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set
index 4255f6e..7fc4146 100644
--- a/libstdc++-v3/include/debug/unordered_set
+++ b/libstdc++-v3/include/debug/unordered_set
@@ -170,6 +170,12 @@ namespace __debug
template<typename _InputIterator>
unordered_set(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a)
+ : unordered_set(__first, __last, 0, hasher(), key_equal(), __a)
+ { }
+
+ template<typename _InputIterator>
+ unordered_set(_InputIterator __first, _InputIterator __last,
size_type __n,
const allocator_type& __a)
: unordered_set(__first, __last, __n, hasher(), key_equal(), __a)
@@ -183,6 +189,11 @@ namespace __debug
{ }
unordered_set(initializer_list<value_type> __l,
+ const allocator_type& __a)
+ : unordered_set(__l, 0, hasher(), key_equal(), __a)
+ { }
+
+ unordered_set(initializer_list<value_type> __l,
size_type __n,
const allocator_type& __a)
: unordered_set(__l, __n, hasher(), key_equal(), __a)
@@ -437,7 +448,7 @@ namespace __debug
_M_check_rehashed(__bucket_count);
}
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
using node_type = typename _Base::node_type;
using insert_return_type = _Node_insert_return<iterator, node_type>;
@@ -508,7 +519,7 @@ namespace __debug
find(const key_type& __key)
{ return { _Base::find(__key), this }; }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -521,7 +532,7 @@ namespace __debug
find(const key_type& __key) const
{ return { _Base::find(__key), this }; }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -543,7 +554,7 @@ namespace __debug
return { { __res.first, this }, { __res.second, this } };
}
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -562,7 +573,7 @@ namespace __debug
return { { __res.first, this }, { __res.second, this } };
}
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -661,7 +672,7 @@ namespace __debug
return __next;
}
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
node_type
_M_extract(_Base_const_iterator __victim)
{
@@ -713,6 +724,17 @@ namespace __debug
typename iterator_traits<_InputIterator>::value_type>,
_Allocator>;
+ template<typename _InputIterator, typename _Allocator,
+ typename = _RequireInputIter<_InputIterator>,
+ typename = _RequireAllocator<_Allocator>>
+ unordered_set(_InputIterator, _InputIterator, _Allocator)
+ -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
+ hash<
+ typename iterator_traits<_InputIterator>::value_type>,
+ equal_to<
+ typename iterator_traits<_InputIterator>::value_type>,
+ _Allocator>;
+
template<typename _InputIterator, typename _Hash, typename _Allocator,
typename = _RequireInputIter<_InputIterator>,
typename = _RequireNotAllocatorOrIntegral<_Hash>,
@@ -732,6 +754,11 @@ namespace __debug
unordered_set<int>::size_type, _Allocator)
-> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
+ template<typename _Tp, typename _Allocator,
+ typename = _RequireAllocator<_Allocator>>
+ unordered_set(initializer_list<_Tp>, _Allocator)
+ -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
+
template<typename _Tp, typename _Hash, typename _Allocator,
typename = _RequireNotAllocatorOrIntegral<_Hash>,
typename = _RequireAllocator<_Allocator>>
@@ -878,6 +905,12 @@ namespace __debug
template<typename _InputIterator>
unordered_multiset(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a)
+ : unordered_multiset(__first, __last, 0, hasher(), key_equal(), __a)
+ { }
+
+ template<typename _InputIterator>
+ unordered_multiset(_InputIterator __first, _InputIterator __last,
size_type __n,
const allocator_type& __a)
: unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a)
@@ -891,6 +924,11 @@ namespace __debug
{ }
unordered_multiset(initializer_list<value_type> __l,
+ const allocator_type& __a)
+ : unordered_multiset(__l, 0, hasher(), key_equal(), __a)
+ { }
+
+ unordered_multiset(initializer_list<value_type> __l,
size_type __n,
const allocator_type& __a)
: unordered_multiset(__l, __n, hasher(), key_equal(), __a)
@@ -1145,7 +1183,7 @@ namespace __debug
_M_check_rehashed(__bucket_count);
}
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
using node_type = typename _Base::node_type;
node_type
@@ -1211,7 +1249,7 @@ namespace __debug
find(const key_type& __key)
{ return { _Base::find(__key), this }; }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -1224,7 +1262,7 @@ namespace __debug
find(const key_type& __key) const
{ return { _Base::find(__key), this }; }
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -1246,7 +1284,7 @@ namespace __debug
return { { __res.first, this }, { __res.second, this } };
}
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -1265,7 +1303,7 @@ namespace __debug
return { { __res.first, this }, { __res.second, this } };
}
-#if __cplusplus > 201703L
+#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
template<typename _Kt,
typename = std::__has_is_transparent_t<_Hash, _Kt>,
typename = std::__has_is_transparent_t<_Pred, _Kt>>
@@ -1362,7 +1400,7 @@ namespace __debug
return __next;
}
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
node_type
_M_extract(_Base_const_iterator __victim)
{
@@ -1416,6 +1454,17 @@ namespace __debug
iterator_traits<_InputIterator>::value_type>,
_Allocator>;
+ template<typename _InputIterator, typename _Allocator,
+ typename = _RequireInputIter<_InputIterator>,
+ typename = _RequireAllocator<_Allocator>>
+ unordered_multiset(_InputIterator, _InputIterator, _Allocator)
+ -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
+ hash<typename
+ iterator_traits<_InputIterator>::value_type>,
+ equal_to<typename
+ iterator_traits<_InputIterator>::value_type>,
+ _Allocator>;
+
template<typename _InputIterator, typename _Hash, typename _Allocator,
typename = _RequireInputIter<_InputIterator>,
typename = _RequireNotAllocatorOrIntegral<_Hash>,
@@ -1437,6 +1486,11 @@ namespace __debug
unordered_multiset<int>::size_type, _Allocator)
-> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
+ template<typename _Tp, typename _Allocator,
+ typename = _RequireAllocator<_Allocator>>
+ unordered_multiset(initializer_list<_Tp>, _Allocator)
+ -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
+
template<typename _Tp, typename _Hash, typename _Allocator,
typename = _RequireNotAllocatorOrIntegral<_Hash>,
typename = _RequireAllocator<_Allocator>>
diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector
index 1b3486b..f952fe9 100644
--- a/libstdc++-v3/include/debug/vector
+++ b/libstdc++-v3/include/debug/vector
@@ -1038,6 +1038,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} // namespace __detail::__variant
#endif // C++17
+#ifdef __glibcxx_erase_if // C++ >= 20 && HOSTED
+ template<typename _Tp, typename _Alloc, typename _Predicate>
+ constexpr typename __debug::vector<_Tp, _Alloc>::size_type
+ erase_if(__debug::vector<_Tp, _Alloc>& __cont, _Predicate __pred)
+ {
+ _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __unsafe_cont = __cont;
+ const auto __osz = __cont.size();
+ const auto __end = __unsafe_cont.end();
+ auto __removed = std::__remove_if(__unsafe_cont.begin(), __end,
+ std::move(__pred));
+ if (__removed != __end)
+ {
+ __cont.erase(__niter_wrap(__cont.begin(), __removed),
+ __cont.end());
+ return __osz - __cont.size();
+ }
+
+ return 0;
+ }
+
+ template<typename _Tp, typename _Alloc, typename _Up = _Tp>
+ constexpr typename __debug::vector<_Tp, _Alloc>::size_type
+ erase(__debug::vector<_Tp, _Alloc>& __cont, const _Up& __value)
+ { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }
+#endif // __glibcxx_erase_if
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/experimental/memory b/libstdc++-v3/include/experimental/memory
index 131e5ac..1b01462 100644
--- a/libstdc++-v3/include/experimental/memory
+++ b/libstdc++-v3/include/experimental/memory
@@ -148,42 +148,42 @@ inline namespace fundamentals_v2
}; // observer_ptr<>
template<typename _Tp>
- void
+ constexpr void
swap(observer_ptr<_Tp>& __p1, observer_ptr<_Tp>& __p2) noexcept
{
__p1.swap(__p2);
}
template<typename _Tp>
- observer_ptr<_Tp>
+ constexpr observer_ptr<_Tp>
make_observer(_Tp* __p) noexcept
{
return observer_ptr<_Tp>(__p);
}
template<typename _Tp, typename _Up>
- bool
+ constexpr bool
operator==(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
{
return __p1.get() == __p2.get();
}
template<typename _Tp, typename _Up>
- bool
+ constexpr bool
operator!=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
{
return !(__p1 == __p2);
}
template<typename _Tp>
- bool
+ constexpr bool
operator==(observer_ptr<_Tp> __p, nullptr_t) noexcept
{
return !__p;
}
template<typename _Tp>
- bool
+ constexpr bool
operator==(nullptr_t, observer_ptr<_Tp> __p) noexcept
{
return !__p;
@@ -197,14 +197,14 @@ inline namespace fundamentals_v2
}
template<typename _Tp>
- bool
+ constexpr bool
operator!=(nullptr_t, observer_ptr<_Tp> __p) noexcept
{
return bool(__p);
}
template<typename _Tp, typename _Up>
- bool
+ constexpr bool
operator<(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
{
return std::less<typename common_type<typename add_pointer<_Tp>::type,
@@ -214,21 +214,21 @@ inline namespace fundamentals_v2
}
template<typename _Tp, typename _Up>
- bool
+ constexpr bool
operator>(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
{
return __p2 < __p1;
}
template<typename _Tp, typename _Up>
- bool
+ constexpr bool
operator<=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
{
return !(__p2 < __p1);
}
template<typename _Tp, typename _Up>
- bool
+ constexpr bool
operator>=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
{
return !(__p1 < __p2);
diff --git a/libstdc++-v3/include/experimental/numeric b/libstdc++-v3/include/experimental/numeric
index 381ecf3..33e9731 100644
--- a/libstdc++-v3/include/experimental/numeric
+++ b/libstdc++-v3/include/experimental/numeric
@@ -88,9 +88,12 @@ inline namespace fundamentals_v2
return 0;
_Ct __r = __m2 / __detail::__gcd<make_unsigned_t<_Ct>>(__m2, __n2);
- if _GLIBCXX17_CONSTEXPR (is_signed_v<_Ct>)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ if constexpr (is_signed_v<_Ct>)
if (__is_constant_evaluated())
return __r * __n2; // constant evaluation can detect overflow here.
+#pragma GCC diagnostic pop
bool __overflow = __builtin_mul_overflow(__r, __n2, &__r);
__glibcxx_assert(!__overflow);
diff --git a/libstdc++-v3/include/ext/atomicity.h b/libstdc++-v3/include/ext/atomicity.h
index 98f745c..14670b5 100644
--- a/libstdc++-v3/include/ext/atomicity.h
+++ b/libstdc++-v3/include/ext/atomicity.h
@@ -39,6 +39,9 @@
#if __has_include(<sys/single_threaded.h>)
# include <sys/single_threaded.h>
#endif
+#if __cplusplus >= 201103L
+# include <type_traits> // make_unsigned_t
+#endif
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
@@ -61,7 +64,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// To abstract locking primitives across all thread policies, use:
// __exchange_and_add_dispatch
// __atomic_add_dispatch
-#ifdef _GLIBCXX_ATOMIC_BUILTINS
+#ifdef _GLIBCXX_ATOMIC_WORD_BUILTINS
inline _Atomic_word
__attribute__((__always_inline__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
@@ -71,7 +74,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__attribute__((__always_inline__))
__atomic_add(volatile _Atomic_word* __mem, int __val)
{ __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
-#else
+#else // Defined in config/cpu/.../atomicity.h
_Atomic_word
__exchange_and_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW;
@@ -79,19 +82,57 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__atomic_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW;
#endif
+#if __cplusplus < 201103L
+ // The array bound will be ill-formed in the very unlikely case that
+ // _Atomic_word is wider than long and we need to use unsigned long long
+ // below in __exchange_and_add_single and __atomic_add_single.
+ typedef int
+ _Atomic_word_fits_in_long[sizeof(_Atomic_word) <= sizeof(long) ? 1 : -1];
+#endif
+
+ // Targets where _Atomic_word uses __attribute__((__aligned__(n))) will get
+ // a warning for make_unsigned<_Atomic_word>. That warning can be ignored,
+ // because we only need an unsigned type, we don't care about its alignment.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wignored-attributes"
+
+ // We need an unsigned type that can be used for the arithmetic below.
+ // This type must not be use for atomic ops because it might not be
+ // sufficiently aligned. Define it as a macro that we #undef below,
+ // to prevent misuse elsewhere in the library.
+#if __cplusplus >= 201103L
+# define _GLIBCXX_UNSIGNED_ATOMIC_WORD std::make_unsigned<_Atomic_word>::type
+#else
+ // For most targets make_unsigned_t<_Atomic_word> is unsigned int,
+ // but 64-bit sparc uses long for _Atomic_word, so needs unsigned long.
+ // Sign-extending to unsigned long works for both cases, so use that.
+# define _GLIBCXX_UNSIGNED_ATOMIC_WORD unsigned long
+#endif
+
inline _Atomic_word
__attribute__((__always_inline__))
__exchange_and_add_single(_Atomic_word* __mem, int __val)
{
_Atomic_word __result = *__mem;
- *__mem += __val;
+ // Do the addition with an unsigned type so that overflow is well defined.
+ _GLIBCXX_UNSIGNED_ATOMIC_WORD __u;
+ __u = __result;
+ __u += __val;
+ *__mem = __u;
return __result;
}
inline void
__attribute__((__always_inline__))
__atomic_add_single(_Atomic_word* __mem, int __val)
- { *__mem += __val; }
+ {
+ _GLIBCXX_UNSIGNED_ATOMIC_WORD __u;
+ __u = *__mem;
+ __u += __val;
+ *__mem = __u;
+ }
+#undef _GLIBCXX_UNSIGNED_ATOMIC_WORD
+#pragma GCC diagnostic pop
inline _Atomic_word
__attribute__ ((__always_inline__))
diff --git a/libstdc++-v3/include/ext/numeric_traits.h b/libstdc++-v3/include/ext/numeric_traits.h
index 2cd8943..78cb8e3 100644
--- a/libstdc++-v3/include/ext/numeric_traits.h
+++ b/libstdc++-v3/include/ext/numeric_traits.h
@@ -48,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// or is_signed, digits10, max_digits10, or max_exponent10 for floats.
// Unlike __is_integer (and std::is_integral) this trait is true for
- // non-standard built-in integer types such as __int128 and __int20.
+ // non-standard built-in integer types such as __int20.
template<typename _Tp>
struct __is_integer_nonstrict
: public std::__is_integer<_Tp>
@@ -126,12 +126,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3)
#endif
-#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
- // In strict modes __is_integer<__int128> is false,
- // but we still want to define __numeric_traits_integer<__int128>.
- _GLIBCXX_INT_N_TRAITS(__int128, 128)
-#endif
-
#undef _GLIBCXX_INT_N_TRAITS
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp b/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp
index 6088709..a8c73b5 100644
--- a/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp
+++ b/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/bin_search_tree_.hpp
@@ -305,6 +305,9 @@ namespace __gnu_pbds
rotate_parent(node_pointer);
inline void
+ update_subtree_size(node_pointer);
+
+ inline void
apply_update(node_pointer, null_node_update_pointer);
template<typename Node_Update_>
diff --git a/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp b/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp
index e6e954d..b8f5014 100644
--- a/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp
+++ b/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/insert_fn_imps.hpp
@@ -122,7 +122,6 @@ insert_leaf_new(const_reference r_value, node_pointer p_nd, bool left_nd)
}
p_new_nd->m_p_parent = p_nd;
- p_new_nd->m_p_left = p_new_nd->m_p_right = 0;
PB_DS_ASSERT_NODE_CONSISTENT(p_nd)
update_to_top(p_new_nd, (node_update* )this);
@@ -142,7 +141,6 @@ insert_imp_empty(const_reference r_value)
m_p_head->m_p_parent = p_new_node;
p_new_node->m_p_parent = m_p_head;
- p_new_node->m_p_left = p_new_node->m_p_right = 0;
_GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(r_value));)
update_to_top(m_p_head->m_p_parent, (node_update*)this);
diff --git a/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp b/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp
index 069b17f..8cadce2 100644
--- a/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp
+++ b/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/rotate_fn_imps.hpp
@@ -122,8 +122,23 @@ rotate_parent(node_pointer p_nd)
PB_DS_CLASS_T_DEC
inline void
PB_DS_CLASS_C_DEC::
-apply_update(node_pointer /*p_nd*/, null_node_update_pointer /*p_update*/)
-{ }
+update_subtree_size(node_pointer p_nd)
+{
+ size_type size = 1;
+ if (p_nd->m_p_left)
+ size += p_nd->m_p_left->m_subtree_size;
+ if (p_nd->m_p_right)
+ size += p_nd->m_p_right->m_subtree_size;
+ p_nd->m_subtree_size = size;
+}
+
+PB_DS_CLASS_T_DEC
+inline void
+PB_DS_CLASS_C_DEC::
+apply_update(node_pointer p_nd, null_node_update_pointer /*p_update*/)
+{
+ update_subtree_size(p_nd);
+}
PB_DS_CLASS_T_DEC
template<typename Node_Update_>
@@ -131,6 +146,7 @@ inline void
PB_DS_CLASS_C_DEC::
apply_update(node_pointer p_nd, Node_Update_* /*p_update*/)
{
+ update_subtree_size(p_nd);
node_update::operator()(node_iterator(p_nd),
node_const_iterator(static_cast<node_pointer>(0)));
}
@@ -152,7 +168,14 @@ update_to_top(node_pointer p_nd, Node_Update_* p_update)
PB_DS_CLASS_T_DEC
inline void
PB_DS_CLASS_C_DEC::
-update_to_top(node_pointer /*p_nd*/, null_node_update_pointer /*p_update*/)
-{ }
+update_to_top(node_pointer p_nd, null_node_update_pointer /*p_update */)
+{
+ while (p_nd != m_p_head)
+ {
+ update_subtree_size(p_nd);
+
+ p_nd = p_nd->m_p_parent;
+ }
+}
#endif
diff --git a/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp b/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp
index 0c1b26f..a2a5775 100644
--- a/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp
+++ b/libstdc++-v3/include/ext/pb_ds/detail/bin_search_tree_/split_join_fn_imps.hpp
@@ -133,7 +133,9 @@ PB_DS_CLASS_C_DEC::
split_finish(PB_DS_CLASS_C_DEC& other)
{
other.initialize_min_max();
- other.m_size = std::distance(other.begin(), other.end());
+ other.m_size = 0;
+ if (other.m_p_head->m_p_parent != 0)
+ other.m_size = other.m_p_head->m_p_parent->m_subtree_size;
m_size -= other.m_size;
initialize_min_max();
PB_DS_ASSERT_VALID((*this))
diff --git a/libstdc++-v3/include/ext/pb_ds/detail/rb_tree_map_/node.hpp b/libstdc++-v3/include/ext/pb_ds/detail/rb_tree_map_/node.hpp
index f229be7..3803ddb 100644
--- a/libstdc++-v3/include/ext/pb_ds/detail/rb_tree_map_/node.hpp
+++ b/libstdc++-v3/include/ext/pb_ds/detail/rb_tree_map_/node.hpp
@@ -58,6 +58,9 @@ namespace __gnu_pbds
typedef typename rebind_traits<_Alloc, rb_tree_node_>::pointer
node_pointer;
+ typedef typename rebind_traits<_Alloc, rb_tree_node_>::size_type
+ size_type;
+
typedef typename rebind_traits<_Alloc, metadata_type>::reference
metadata_reference;
@@ -88,6 +91,7 @@ namespace __gnu_pbds
node_pointer m_p_left;
node_pointer m_p_right;
node_pointer m_p_parent;
+ size_type m_subtree_size;
value_type m_value;
bool m_red;
metadata_type m_metadata;
@@ -100,6 +104,9 @@ namespace __gnu_pbds
typedef Value_Type value_type;
typedef null_type metadata_type;
+ typedef typename rebind_traits<_Alloc, rb_tree_node_>::size_type
+ size_type;
+
typedef typename rebind_traits<_Alloc, rb_tree_node_>::pointer
node_pointer;
@@ -116,6 +123,7 @@ namespace __gnu_pbds
node_pointer m_p_left;
node_pointer m_p_right;
node_pointer m_p_parent;
+ size_type m_subtree_size;
value_type m_value;
bool m_red;
};
diff --git a/libstdc++-v3/include/ext/pb_ds/detail/splay_tree_/node.hpp b/libstdc++-v3/include/ext/pb_ds/detail/splay_tree_/node.hpp
index 961afbe..b5fbb50 100644
--- a/libstdc++-v3/include/ext/pb_ds/detail/splay_tree_/node.hpp
+++ b/libstdc++-v3/include/ext/pb_ds/detail/splay_tree_/node.hpp
@@ -56,6 +56,9 @@ namespace __gnu_pbds
typedef typename rebind_traits<_Alloc, splay_tree_node_>::pointer
node_pointer;
+ typedef typename rebind_traits<_Alloc, splay_tree_node_>::size_type
+ size_type;
+
typedef typename rebind_traits<_Alloc, metadata_type>::reference
metadata_reference;
@@ -85,6 +88,7 @@ namespace __gnu_pbds
node_pointer m_p_left;
node_pointer m_p_right;
node_pointer m_p_parent;
+ size_type m_subtree_size;
metadata_type m_metadata;
};
@@ -98,6 +102,9 @@ namespace __gnu_pbds
typedef typename rebind_traits<_Alloc, splay_tree_node_>::pointer
node_pointer;
+ typedef typename rebind_traits<_Alloc, splay_tree_node_>::size_type
+ size_type;
+
inline bool
special() const
{ return m_special; }
@@ -111,6 +118,7 @@ namespace __gnu_pbds
node_pointer m_p_left;
node_pointer m_p_right;
node_pointer m_p_parent;
+ size_type m_subtree_size;
value_type m_value;
bool m_special;
};
diff --git a/libstdc++-v3/include/ext/pointer.h b/libstdc++-v3/include/ext/pointer.h
index 700c9a1..5feb9f0 100644
--- a/libstdc++-v3/include/ext/pointer.h
+++ b/libstdc++-v3/include/ext/pointer.h
@@ -40,6 +40,7 @@
#pragma GCC system_header
#endif
+#include <bits/c++config.h>
#if _GLIBCXX_HOSTED
# include <iosfwd>
#endif
diff --git a/libstdc++-v3/include/ext/ropeimpl.h b/libstdc++-v3/include/ext/ropeimpl.h
index 3201927..00b334c 100644
--- a/libstdc++-v3/include/ext/ropeimpl.h
+++ b/libstdc++-v3/include/ext/ropeimpl.h
@@ -1355,7 +1355,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
case __detail::_S_substringfn:
{
_RopeFunction* __f = (_RopeFunction*)__r;
- _CharT __result;
+ _CharT __result = _CharT();
(*(__f->_M_fn))(__i, 1, &__result);
return __result;
diff --git a/libstdc++-v3/include/precompiled/extc++.h b/libstdc++-v3/include/precompiled/extc++.h
index cc6e5e5..9d41656 100644
--- a/libstdc++-v3/include/precompiled/extc++.h
+++ b/libstdc++-v3/include/precompiled/extc++.h
@@ -37,7 +37,6 @@
#endif
#include <ext/alloc_traits.h>
#include <ext/atomicity.h>
-#include <ext/cast.h>
#include <ext/iterator>
#include <ext/numeric_traits.h>
#include <ext/pointer.h>
diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h
index f4b312d..54baed4 100644
--- a/libstdc++-v3/include/precompiled/stdc++.h
+++ b/libstdc++-v3/include/precompiled/stdc++.h
@@ -29,9 +29,7 @@
// 17.4.1.2 Headers
// C
-#ifndef _GLIBCXX_NO_ASSERT
-#include <cassert>
-#endif
+// Don't include cassert, it's not suitable for PCH or header unit.
#include <cctype>
#include <cfloat>
#include <climits>
@@ -104,9 +102,6 @@
#if _GLIBCXX_HOSTED
// C
-#ifndef _GLIBCXX_NO_ASSERT
-#include <cassert>
-#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
@@ -228,6 +223,7 @@
#include <flat_map>
#include <flat_set>
#include <generator>
+#include <mdspan>
#include <print>
#include <spanstream>
#include <stacktrace>
@@ -236,6 +232,8 @@
#endif
#if __cplusplus > 202302L
+#include <debugging>
+#include <inplace_vector>
#include <text_encoding>
#include <stdbit.h>
#include <stdckdint.h>
diff --git a/libstdc++-v3/include/pstl/algorithm_impl.h b/libstdc++-v3/include/pstl/algorithm_impl.h
index 5b1cd20..2080e82 100644
--- a/libstdc++-v3/include/pstl/algorithm_impl.h
+++ b/libstdc++-v3/include/pstl/algorithm_impl.h
@@ -79,7 +79,7 @@ template <class _ForwardIterator, class _Size, class _Function>
_ForwardIterator
__for_each_n_it_serial(_ForwardIterator __first, _Size __n, _Function __f)
{
- for (; __n > 0; ++__first, --__n)
+ for (; __n > 0; ++__first, (void) --__n)
__f(__first);
return __first;
}
@@ -221,7 +221,7 @@ _ForwardIterator2
__brick_walk2(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Function __f,
/*vector=*/std::false_type) noexcept
{
- for (; __first1 != __last1; ++__first1, ++__first2)
+ for (; __first1 != __last1; ++__first1, (void) ++__first2)
__f(*__first1, *__first2);
return __first2;
}
@@ -240,7 +240,7 @@ _ForwardIterator2
__brick_walk2_n(_ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, _Function __f,
/*vector=*/std::false_type) noexcept
{
- for (; __n > 0; --__n, ++__first1, ++__first2)
+ for (; __n > 0; --__n, (void) ++__first1, ++__first2)
__f(*__first1, *__first2);
return __first2;
}
@@ -364,7 +364,7 @@ _ForwardIterator3
__brick_walk3(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
_ForwardIterator3 __first3, _Function __f, /*vector=*/std::false_type) noexcept
{
- for (; __first1 != __last1; ++__first1, ++__first2, ++__first3)
+ for (; __first1 != __last1; ++__first1, (void) ++__first2, ++__first3)
__f(*__first1, *__first2, *__first3);
return __first3;
}
@@ -961,7 +961,7 @@ struct __brick_move_destroy
{
using _IteratorValueType = typename std::iterator_traits<_RandomAccessIterator1>::value_type;
- for (; __first != __last; ++__first, ++__result)
+ for (; __first != __last; ++__first, (void) ++__result)
{
*__result = std::move(*__first);
(*__first).~_IteratorValueType();
@@ -1027,7 +1027,7 @@ __brick_calc_mask_1(_ForwardIterator __first, _ForwardIterator __last, bool* __r
static_assert(__are_random_access_iterators<_ForwardIterator>::value,
"Pattern-brick error. Should be a random access iterator.");
- for (; __first != __last; ++__first, ++__mask)
+ for (; __first != __last; ++__first, (void) ++__mask)
{
*__mask = __pred(*__first);
if (*__mask)
@@ -1052,7 +1052,7 @@ void
__brick_copy_by_mask(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, bool* __mask,
_Assigner __assigner, /*vector=*/std::false_type) noexcept
{
- for (; __first != __last; ++__first, ++__mask)
+ for (; __first != __last; ++__first, (void) ++__mask)
{
if (*__mask)
{
@@ -1079,7 +1079,7 @@ void
__brick_partition_by_mask(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator1 __out_true,
_OutputIterator2 __out_false, bool* __mask, /*vector=*/std::false_type) noexcept
{
- for (; __first != __last; ++__first, ++__mask)
+ for (; __first != __last; ++__first, (void) ++__mask)
{
if (*__mask)
{
@@ -1383,7 +1383,7 @@ __brick_calc_mask_2(_RandomAccessIterator __first, _RandomAccessIterator __last,
_BinaryPredicate __pred, /*vector=*/std::false_type) noexcept
{
_DifferenceType __count = 0;
- for (; __first != __last; ++__first, ++__mask)
+ for (; __first != __last; ++__first, (void) ++__mask)
{
*__mask = !__pred(*__first, *(__first - 1));
__count += *__mask;
@@ -1483,7 +1483,7 @@ void
__brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, _BidirectionalIterator __d_last,
/*is_vector=*/std::false_type) noexcept
{
- for (--__d_last; __first != __last; ++__first, --__d_last)
+ for (--__d_last; __first != __last; ++__first, (void) --__d_last)
{
using std::iter_swap;
iter_swap(__first, __d_last);
@@ -2333,7 +2333,7 @@ __pattern_partial_sort_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&&
_RandomAccessIterator1 __it = __first + (__i - __r);
// 1. Copy elements from input to raw memory
- for (_T1* __k = __i; __k != __j; ++__k, ++__it)
+ for (_T1* __k = __i; __k != __j; ++__k, (void) ++__it)
{
::new (__k) _T2(*__it);
}
@@ -3648,7 +3648,7 @@ __mismatch_serial(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _Forwar
#if defined(_PSTL_CPP14_2RANGE_MISMATCH_EQUAL_PRESENT)
return std::mismatch(__first1, __last1, __first2, __last2, __pred);
#else
- for (; __first1 != __last1 && __first2 != __last2 && __pred(*__first1, *__first2); ++__first1, ++__first2)
+ for (; __first1 != __last1 && __first2 != __last2 && __pred(*__first1, *__first2); ++__first1, (void) ++__first2)
{
}
return std::make_pair(__first1, __first2);
diff --git a/libstdc++-v3/include/pstl/glue_numeric_impl.h b/libstdc++-v3/include/pstl/glue_numeric_impl.h
index 10d4912..fe2d0fd 100644
--- a/libstdc++-v3/include/pstl/glue_numeric_impl.h
+++ b/libstdc++-v3/include/pstl/glue_numeric_impl.h
@@ -25,7 +25,7 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
_BinaryOperation __binary_op)
{
- return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, __binary_op,
+ return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::move(__init), __binary_op,
__pstl::__internal::__no_op());
}
@@ -33,7 +33,7 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Tp>
__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init)
{
- return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, std::plus<_Tp>(),
+ return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::move(__init), std::plus<_Tp>(),
__pstl::__internal::__no_op());
}
@@ -58,7 +58,7 @@ transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _Forward
typedef typename iterator_traits<_ForwardIterator1>::value_type _InputType;
return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
- __first1, __last1, __first2, __init, std::plus<_InputType>(),
+ __first1, __last1, __first2, std::move(__init), std::plus<_InputType>(),
std::multiplies<_InputType>());
}
@@ -70,7 +70,7 @@ transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _Forward
{
auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
- __first1, __last1, __first2, __init, __binary_op1,
+ __first1, __last1, __first2, std::move(__init), __binary_op1,
__binary_op2);
}
@@ -81,7 +81,7 @@ transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIt
{
auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
- __first, __last, __init, __binary_op, __unary_op);
+ __first, __last, std::move(__init), __binary_op, __unary_op);
}
// [exclusive.scan]
@@ -139,7 +139,7 @@ inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIte
_ForwardIterator2 __result, _BinaryOperation __binary_op, _Tp __init)
{
return transform_inclusive_scan(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __binary_op,
- __pstl::__internal::__no_op(), __init);
+ __pstl::__internal::__no_op(), std::move(__init));
}
// [transform.exclusive.scan]
@@ -154,7 +154,7 @@ transform_exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _
auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
return __pstl::__internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
- __last, __result, __unary_op, __init, __binary_op,
+ __last, __result, __unary_op, std::move(__init), __binary_op,
/*inclusive=*/std::false_type());
}
@@ -170,7 +170,7 @@ transform_inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _
auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
return __pstl::__internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
- __last, __result, __unary_op, __init, __binary_op,
+ __last, __result, __unary_op, std::move(__init), __binary_op,
/*inclusive=*/std::true_type());
}
diff --git a/libstdc++-v3/include/pstl/memory_impl.h b/libstdc++-v3/include/pstl/memory_impl.h
index 8cb32d0..080b6ca 100644
--- a/libstdc++-v3/include/pstl/memory_impl.h
+++ b/libstdc++-v3/include/pstl/memory_impl.h
@@ -29,7 +29,7 @@ __brick_uninitialized_move(_ForwardIterator __first, _ForwardIterator __last, _O
/*vector=*/std::false_type) noexcept
{
using _ValueType = typename std::iterator_traits<_OutputIterator>::value_type;
- for (; __first != __last; ++__first, ++__result)
+ for (; __first != __last; ++__first, (void) ++__result)
{
::new (std::addressof(*__result)) _ValueType(std::move(*__first));
}
@@ -80,7 +80,7 @@ __brick_uninitialized_copy(_ForwardIterator __first, _ForwardIterator __last, _O
/*vector=*/std::false_type) noexcept
{
using _ValueType = typename std::iterator_traits<_OutputIterator>::value_type;
- for (; __first != __last; ++__first, ++__result)
+ for (; __first != __last; ++__first, (void) ++__result)
{
::new (std::addressof(*__result)) _ValueType(*__first);
}
diff --git a/libstdc++-v3/include/pstl/numeric_impl.h b/libstdc++-v3/include/pstl/numeric_impl.h
index e1ebec1..af6f6a2 100644
--- a/libstdc++-v3/include/pstl/numeric_impl.h
+++ b/libstdc++-v3/include/pstl/numeric_impl.h
@@ -35,7 +35,7 @@ __brick_transform_reduce(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2,
/*is_vector=*/std::false_type) noexcept
{
- return std::inner_product(__first1, __last1, __first2, __init, __binary_op1, __binary_op2);
+ return std::inner_product(__first1, __last1, __first2, std::move(__init), __binary_op1, __binary_op2);
}
template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp, class _BinaryOperation1,
@@ -48,7 +48,7 @@ __brick_transform_reduce(_RandomAccessIterator1 __first1, _RandomAccessIterator1
{
typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType;
return __unseq_backend::__simd_transform_reduce(
- __last1 - __first1, __init, __binary_op1,
+ __last1 - __first1, std::move(__init), __binary_op1,
[=, &__binary_op2](_DifferenceType __i) { return __binary_op2(__first1[__i], __first2[__i]); });
}
@@ -59,7 +59,7 @@ __pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1,
_ForwardIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1,
_BinaryOperation2 __binary_op2) noexcept
{
- return __brick_transform_reduce(__first1, __last1, __first2, __init, __binary_op1, __binary_op2,
+ return __brick_transform_reduce(__first1, __last1, __first2, std::move(__init), __binary_op1, __binary_op2,
typename _Tag::__is_vector{});
}
@@ -79,12 +79,12 @@ __pattern_transform_reduce(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& _
__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
[__first1, __first2, __binary_op2](_RandomAccessIterator1 __i) mutable
{ return __binary_op2(*__i, *(__first2 + (__i - __first1))); },
- __init,
+ std::move(__init),
__binary_op1, // Combine
[__first1, __first2, __binary_op1, __binary_op2](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j,
_Tp __init) -> _Tp
{
- return __internal::__brick_transform_reduce(__i, __j, __first2 + (__i - __first1), __init,
+ return __internal::__brick_transform_reduce(__i, __j, __first2 + (__i - __first1), std::move(__init),
__binary_op1, __binary_op2, _IsVector{});
});
});
@@ -99,7 +99,7 @@ _Tp
__brick_transform_reduce(_ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation __binary_op,
_UnaryOperation __unary_op, /*is_vector=*/std::false_type) noexcept
{
- return std::transform_reduce(__first, __last, __init, __binary_op, __unary_op);
+ return std::transform_reduce(__first, __last, std::move(__init), __binary_op, __unary_op);
}
template <class _RandomAccessIterator, class _Tp, class _UnaryOperation, class _BinaryOperation>
@@ -110,7 +110,7 @@ __brick_transform_reduce(_RandomAccessIterator __first, _RandomAccessIterator __
{
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
return __unseq_backend::__simd_transform_reduce(
- __last - __first, __init, __binary_op,
+ __last - __first, std::move(__init), __binary_op,
[=, &__unary_op](_DifferenceType __i) { return __unary_op(__first[__i]); });
}
@@ -120,7 +120,7 @@ _Tp
__pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
_BinaryOperation __binary_op, _UnaryOperation __unary_op) noexcept
{
- return __internal::__brick_transform_reduce(__first, __last, __init, __binary_op, __unary_op,
+ return __internal::__brick_transform_reduce(__first, __last, std::move(__init), __binary_op, __unary_op,
typename _Tag::__is_vector{});
}
@@ -138,9 +138,9 @@ __pattern_transform_reduce(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& _
{
return __par_backend::__parallel_transform_reduce(
__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
- [__unary_op](_RandomAccessIterator __i) mutable { return __unary_op(*__i); }, __init, __binary_op,
+ [__unary_op](_RandomAccessIterator __i) mutable { return __unary_op(*__i); }, std::move(__init), __binary_op,
[__unary_op, __binary_op](_RandomAccessIterator __i, _RandomAccessIterator __j, _Tp __init) {
- return __internal::__brick_transform_reduce(__i, __j, __init, __binary_op, __unary_op, _IsVector{});
+ return __internal::__brick_transform_reduce(__i, __j, std::move(__init), __binary_op, __unary_op, _IsVector{});
});
});
}
@@ -158,7 +158,7 @@ __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _Outpu
_UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
/*Inclusive*/ std::false_type, /*is_vector=*/std::false_type) noexcept
{
- for (; __first != __last; ++__first, ++__result)
+ for (; __first != __last; ++__first, (void) ++__result)
{
_Tp __v = std::move(__init);
_PSTL_PRAGMA_FORCEINLINE
@@ -175,13 +175,13 @@ __brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __la
_UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
/*Inclusive*/ std::true_type, /*is_vector=*/std::false_type) noexcept
{
- for (; __first != __last; ++__first, ++__result)
+ for (; __first != __last; ++__first, (void) ++__result)
{
_PSTL_PRAGMA_FORCEINLINE
__init = __binary_op(__init, __unary_op(*__first));
*__result = __init;
}
- return std::make_pair(__result, __init);
+ return std::make_pair(__result, std::move(__init));
}
// type is arithmetic and binary operation is a user defined operation.
@@ -199,11 +199,11 @@ __brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __la
/*is_vector=*/std::true_type) noexcept
{
#if defined(_PSTL_UDS_PRESENT)
- return __unseq_backend::__simd_scan(__first, __last - __first, __result, __unary_op, __init, __binary_op,
+ return __unseq_backend::__simd_scan(__first, __last - __first, __result, __unary_op, std::move(__init), __binary_op,
_Inclusive());
#else
// We need to call serial brick here to call function for inclusive and exclusive scan that depends on _Inclusive() value
- return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
+ return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, std::move(__init), __binary_op, _Inclusive(),
/*is_vector=*/std::false_type());
#endif
}
@@ -215,7 +215,7 @@ __brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __la
_UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, _Inclusive,
/*is_vector=*/std::true_type) noexcept
{
- return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
+ return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, std::move(__init), __binary_op, _Inclusive(),
/*is_vector=*/std::false_type());
}
@@ -247,19 +247,19 @@ __pattern_transform_scan(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __e
{
__par_backend::__parallel_transform_scan(
__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __last - __first,
- [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, __init,
+ [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, std::move(__init),
__binary_op,
[__first, __unary_op, __binary_op](_DifferenceType __i, _DifferenceType __j, _Tp __init)
{
// Execute serial __brick_transform_reduce, due to the explicit SIMD vectorization (reduction) requires a commutative operation for the guarantee of correct scan.
- return __internal::__brick_transform_reduce(__first + __i, __first + __j, __init, __binary_op,
+ return __internal::__brick_transform_reduce(__first + __i, __first + __j, std::move(__init), __binary_op,
__unary_op,
/*__is_vector*/ std::false_type());
},
[__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __j, _Tp __init)
{
return __internal::__brick_transform_scan(__first + __i, __first + __j, __result + __i, __unary_op,
- __init, __binary_op, _Inclusive(), _IsVector{})
+ std::move(__init), __binary_op, _Inclusive(), _IsVector{})
.second;
});
return __result + (__last - __first);
@@ -286,7 +286,7 @@ __pattern_transform_scan(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __e
[&]()
{
__par_backend::__parallel_strict_scan(
- __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, __init,
+ __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, std::move(__init),
[__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __len)
{
return __internal::__brick_transform_scan(__first + __i, __first + (__i + __len), __result + __i,
diff --git a/libstdc++-v3/include/pstl/parallel_backend_tbb.h b/libstdc++-v3/include/pstl/parallel_backend_tbb.h
index bb6fa8f..ff5236f 100644
--- a/libstdc++-v3/include/pstl/parallel_backend_tbb.h
+++ b/libstdc++-v3/include/pstl/parallel_backend_tbb.h
@@ -521,7 +521,7 @@ class __root_task
friend class __func_task<_Func>;
};
-#else // TBB_INTERFACE_VERSION <= 12000
+#else // TBB_INTERFACE_VERSION > 12000
class __task : public tbb::detail::d1::task
{
protected:
@@ -656,10 +656,16 @@ class __func_task : public __task
_PSTL_ASSERT(__parent != nullptr);
_PSTL_ASSERT(__parent->_M_refcount.load(std::memory_order_relaxed) > 0);
- if (--__parent->_M_refcount == 0)
+
+ auto __refcount = --__parent->_M_refcount;
+
+ // Placing the deallocation after the refcount decrement allows another thread to proceed with tree
+ // folding concurrently with this task cleanup.
+ __alloc.deallocate(this, *__ed);
+
+ if (__refcount == 0)
{
_PSTL_ASSERT(__next == nullptr);
- __alloc.deallocate(this, *__ed);
return __parent;
}
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/array b/libstdc++-v3/include/std/array
index fdcf0b0..12f0109 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -381,6 +381,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ __one.swap(__two); }
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2766. Swapping non-swappable types
template<typename _Tp, std::size_t _Nm>
__enable_if_t<!__array_traits<_Tp, _Nm>::_Is_swappable::value>
swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic
index 9b1aca0..0a510d8 100644
--- a/libstdc++-v3/include/std/atomic
+++ b/libstdc++-v3/include/std/atomic
@@ -217,6 +217,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(sizeof(_Tp) > 0,
"Incomplete or zero-sized types are not supported");
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4069. std::atomic<volatile T> should be ill-formed
+ static_assert(is_same<_Tp, typename remove_cv<_Tp>::type>::value,
+ "template argument for std::atomic must not be const or volatile");
+
#if __cplusplus > 201703L
static_assert(is_copy_constructible_v<_Tp>);
static_assert(is_move_constructible_v<_Tp>);
@@ -401,21 +406,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
{
- std::__atomic_wait_address_v(&_M_i, __old,
- [__m, this] { return this->load(__m); });
+ std::__atomic_wait_address_v(std::addressof(_M_i), __old,
+ [__m, this] { return this->load(__m); });
}
// TODO add const volatile overload
void
notify_one() noexcept
- { std::__atomic_notify_address(&_M_i, false); }
+ { std::__atomic_notify_address(std::addressof(_M_i), false); }
void
notify_all() noexcept
- { std::__atomic_notify_address(&_M_i, true); }
+ { std::__atomic_notify_address(std::addressof(_M_i), true); }
#endif // __cpp_lib_atomic_wait
-
};
/// Partial specialization for pointer types.
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..ece3593 100644
--- a/libstdc++-v3/include/std/bitset
+++ b/libstdc++-v3/include/std/bitset
@@ -61,8 +61,13 @@
#endif
#define __glibcxx_want_constexpr_bitset
+#define __glibcxx_want_bitset // ...construct from string_view
#include <bits/version.h>
+#ifdef __cpp_lib_bitset // ...construct from string_view
+# include <string_view>
+#endif
+
#define _GLIBCXX_BITSET_BITS_PER_WORD (__CHAR_BIT__ * __SIZEOF_LONG__)
#define _GLIBCXX_BITSET_WORDS(__n) \
((__n) / _GLIBCXX_BITSET_BITS_PER_WORD + \
@@ -715,7 +720,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
namespace __bitset
{
-#if _GLIBCXX_HOSTED
+#ifdef __cpp_lib_bitset // ...construct from string_view
+ template<typename _CharT>
+ using __string = std::basic_string_view<_CharT>;
+#elif _GLIBCXX_HOSTED
template<typename _CharT>
using __string = std::basic_string<_CharT>;
#else
@@ -752,7 +760,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* (Note that %bitset does @e not meet the formal requirements of a
* <a href="tables.html#65">container</a>. Mainly, it lacks iterators.)
*
- * The template argument, @a Nb, may be any non-negative number,
+ * The template argument, `Nb`, may be any non-negative number,
* specifying the number of bits (e.g., "0", "12", "1024*1024").
*
* In the general unoptimized case, storage is allocated in word-sized
@@ -816,28 +824,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base;
typedef unsigned long _WordT;
-#if _GLIBCXX_HOSTED
- template<class _CharT, class _Traits, class _Alloc>
- _GLIBCXX23_CONSTEXPR
- void
- _M_check_initial_position(const std::basic_string<_CharT, _Traits, _Alloc>& __s,
- size_t __position) const
+ template<class _Str>
+ _GLIBCXX23_CONSTEXPR void
+ _M_check_initial_position(
+ const _Str& __s, typename _Str::size_type __position) const
{
if (__position > __s.size())
- __throw_out_of_range_fmt(__N("bitset::bitset: __position "
- "(which is %zu) > __s.size() "
- "(which is %zu)"),
- __position, __s.size());
+ __throw_out_of_range_fmt(
+ __N("bitset::bitset:"
+ " __position (which is %zu) > __s.size() (which is %zu)"),
+ size_t(__position), size_t(__s.size()));
}
-#endif // HOSTED
_GLIBCXX23_CONSTEXPR
void _M_check(size_t __position, const char *__s) const
{
if (__position >= _Nb)
- __throw_out_of_range_fmt(__N("%s: __position (which is %zu) "
- ">= _Nb (which is %zu)"),
- __s, __position, _Nb);
+ __throw_out_of_range_fmt(
+ __N("%s: __position (which is %zu) >= _Nb (which is %zu)"),
+ __s, size_t(__position), size_t(_Nb));
}
_GLIBCXX23_CONSTEXPR
@@ -954,12 +959,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if _GLIBCXX_HOSTED
/**
* Use a subset of a string.
- * @param __s A string of @a 0 and @a 1 characters.
- * @param __position Index of the first character in @a __s to use;
+ * @param __s A string of `0` and `1` characters.
+ * @param __position Index of the first character in `__s` to use;
* defaults to zero.
- * @throw std::out_of_range If @a pos is bigger the size of @a __s.
+ * @throw std::out_of_range If `__position > __s.size()`.
* @throw std::invalid_argument If a character appears in the string
- * which is neither @a 0 nor @a 1.
+ * which is neither `0` nor `1`.
*/
template<class _CharT, class _Traits, class _Alloc>
_GLIBCXX23_CONSTEXPR
@@ -976,13 +981,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
* Use a subset of a string.
- * @param __s A string of @a 0 and @a 1 characters.
- * @param __position Index of the first character in @a __s to use.
+ * @param __s A string of `0` and `1` characters.
+ * @param __position Index of the first character in `__s` to use.
* @param __n The number of characters to copy.
- * @throw std::out_of_range If @a __position is bigger the size
- * of @a __s.
+ * @throw std::out_of_range If `__position > __s.size()`.
* @throw std::invalid_argument If a character appears in the string
- * which is neither @a 0 nor @a 1.
+ * which is neither `0` nor `1`.
*/
template<class _CharT, class _Traits, class _Alloc>
_GLIBCXX23_CONSTEXPR
@@ -1008,17 +1012,50 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
#endif // HOSTED
+#ifdef __cpp_lib_bitset // C++ >= 23
+ /**
+ * Use a subset of a string view.
+ * @param __s A `string_view` of a sequence of `0` and `1` characters.
+ * @param __position Index of the first character in `__s` to use.
+ * @param __n The maximum number of characters from `__s` to use.
+ * @param __zero The character corresponding to the value 0.
+ * @param __one The character corresponding to the value 1.
+ * @throw std::out_of_range If `__position > __s.size()`.
+ * @throw std::invalid_argument If a character appears in `__s`
+ * which is neither `0` nor `1`.
+ */
+ template<class _CharT, class _Traits>
+ constexpr explicit
+ bitset(basic_string_view<_CharT, _Traits> __s,
+ basic_string_view<_CharT, _Traits>::size_type __position = 0,
+ basic_string_view<_CharT, _Traits>::size_type __n =
+ basic_string_view<_CharT, _Traits>::npos,
+ _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'))
+ : _Base()
+ {
+ _M_check_initial_position(__s, __position);
+ _M_copy_from_ptr<_CharT, _Traits>(
+ __s.data(), __s.size(), __position, __n, __zero, __one);
+ }
+#endif
+
#if __cplusplus >= 201103L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4294. bitset(const CharT*) constructor needs to be constrained
/**
* Construct from a character %array.
- * @param __str An %array of characters @a zero and @a one.
+ * @param __str An %array of characters `__zero` and `__one`.
* @param __n The number of characters to use.
* @param __zero The character corresponding to the value 0.
* @param __one The character corresponding to the value 1.
* @throw std::invalid_argument If a character appears in the string
- * which is neither @a __zero nor @a __one.
+ * which is neither `__zero` nor `__one`.
*/
- template<typename _CharT>
+ template<typename _CharT,
+ typename = _Require<is_trivially_copyable<_CharT>,
+ is_standard_layout<_CharT>,
+ is_trivially_default_constructible<_CharT>,
+ __not_<is_array<_CharT>>>>
[[__gnu__::__nonnull__]]
_GLIBCXX23_CONSTEXPR
explicit
@@ -1028,10 +1065,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_CharT __zero = _CharT('0'), _CharT __one = _CharT('1'))
: _Base()
{
-#if _GLIBCXX_HOSTED
if (!__str)
__throw_logic_error(__N("bitset::bitset(const _CharT*, ...)"));
-#endif
using _Traits = typename __bitset::__string<_CharT>::traits_type;
if (__n == __bitset::__string<_CharT>::npos)
@@ -1514,7 +1549,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
size_t __pos, size_t __n, _CharT __zero, _CharT __one)
{
reset();
- const size_t __nbits = std::min(_Nb, std::min(__n, size_t(__len - __pos)));
+ const size_t __rlen = std::min(__n, size_t(__len - __pos));
+ const size_t __nbits = std::min(_Nb, __rlen);
+ for (size_t __i = __rlen - __nbits; __i > 0; --__i)
+ {
+ const _CharT __c = __s[__pos + __rlen - __i];
+ if (!_Traits::eq(__c, __zero) && !_Traits::eq(__c, __one))
+ __throw_invalid_argument(__N("bitset::_M_copy_from_ptr"));
+ }
for (size_t __i = __nbits; __i > 0; --__i)
{
const _CharT __c = __s[__pos + __nbits - __i];
@@ -1605,6 +1647,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 +1657,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 +1718,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 +1729,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..47f5aaa 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++ = '-';
@@ -389,6 +390,10 @@ _GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_2)
_GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_3)
_GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_3)
#endif
+#if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
+_GLIBCXX_TO_CHARS(signed __int128)
+_GLIBCXX_TO_CHARS(unsigned __int128)
+#endif
#undef _GLIBCXX_TO_CHARS
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -452,7 +457,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];
@@ -549,10 +554,10 @@ namespace __detail
} // namespace __detail
- /// std::from_chars for integral types.
+ /// std::from_chars for integer types.
template<typename _Tp,
- enable_if_t<__or_<__is_standard_integer<_Tp>,
- is_same<char, remove_cv_t<_Tp>>>::value, int> = 0>
+ enable_if_t<__or_<__is_signed_or_unsigned_integer<_Tp>,
+ is_same<char, _Tp>>::value, int> = 0>
_GLIBCXX23_CONSTEXPR from_chars_result
from_chars(const char* __first, const char* __last, _Tp& __value,
int __base = 10)
@@ -562,7 +567,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 +600,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 +610,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..3e0cf42e 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -22,6 +22,8 @@
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
+// [time]
+
/** @file include/chrono
* This is a Standard C++ Library header.
* @ingroup chrono
@@ -42,23 +44,29 @@
# include <bits/c++0x_warning.h>
#else
+#define __glibcxx_want_chrono
+#define __glibcxx_want_chrono_udls
+#include <bits/version.h>
+
#include <bits/chrono.h>
-#if __cplusplus >= 202002L
+#if __cpp_lib_bitops >= 201907L
# include <bit> // __countr_zero
#endif
-#if __cplusplus >= 202002L && _GLIBCXX_HOSTED
+#ifdef __glibcxx_chrono_cxx20
+# include <bits/stl_algo.h> // upper_bound
+# include <bits/range_access.h> // begin/end for arrays
+#endif
+#if __cpp_lib_chrono >= 201803L // C++20 && HOSTED && USE_CXX11_ABI
# include <sstream>
# include <string>
# include <vector>
-# include <bits/stl_algo.h> // upper_bound
# include <bits/shared_ptr.h>
# include <bits/unique_ptr.h>
#endif
-
-#define __glibcxx_want_chrono
-#define __glibcxx_want_chrono_udls
-#include <bits/version.h>
+#if __glibcxx_chrono_cxx20 >= 202306L // C++26
+# include <bits/functional_hash.h>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -79,7 +87,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
namespace chrono
{
-#if __cplusplus >= 202002L
+#ifdef __glibcxx_chrono_cxx20
/// @addtogroup chrono
/// @{
struct local_t { };
@@ -175,13 +183,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using period = system_clock::period;
using duration = chrono::duration<rep, period>;
using time_point = chrono::time_point<tai_clock>;
- static constexpr bool is_steady = false; // XXX true for CLOCK_TAI?
+ static constexpr bool is_steady = false;
- // TODO move into lib, use CLOCK_TAI on linux, add extension point.
[[nodiscard]]
static time_point
- now()
- { return from_utc(utc_clock::now()); }
+ now(); // in src/c++20/clock.cc
template<typename _Duration>
[[nodiscard]]
@@ -215,13 +221,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using period = system_clock::period;
using duration = chrono::duration<rep, period>;
using time_point = chrono::time_point<gps_clock>;
- static constexpr bool is_steady = false; // XXX
+ static constexpr bool is_steady = false;
- // TODO move into lib, add extension point.
[[nodiscard]]
static time_point
- now()
- { return from_utc(utc_clock::now()); }
+ now(); // in src/c++20/clock.cc
template<typename _Duration>
[[nodiscard]]
@@ -2305,8 +2309,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__r *= 10;
return __r;
}
-
- template<typename _Duration> struct __utc_leap_second;
}
/// @endcond
@@ -2481,30 +2483,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
@@ -3345,7 +3325,328 @@ namespace __detail
#endif // C++20
} // namespace chrono
-#if __cplusplus >= 202002L
+#if __glibcxx_chrono_cxx20 >= 202306 // C++26
+ // Hash support [time.hash]
+
+ template<typename _Tp>
+ concept __is_nothrow_copy_hashable = requires(const _Tp& __t) {
+ { hash<_Tp>{}(_Tp(__t)) } noexcept -> same_as<size_t>;
+ };
+
+ namespace chrono {
+
+ template<typename _T1, typename... _Ts>
+ [[__gnu__::__always_inline__]]
+ constexpr auto
+ __pack_ints(_T1 __v1, _Ts... __vs)
+ {
+ using _ResT = decltype([] {
+ constexpr size_t __tsize = (sizeof(_T1) + ... + sizeof(_Ts));
+ if constexpr (__tsize <= 1)
+ return static_cast<unsigned char>(0);
+ else if constexpr (__tsize <= 2)
+ return static_cast<__UINT16_TYPE__>(0);
+ else if constexpr (__tsize <= 4)
+ return static_cast<__UINT32_TYPE__>(0);
+ else if constexpr (__tsize <= 8)
+ return static_cast<__UINT64_TYPE__>(0);
+ else
+ static_assert(__tsize <= 8);
+ }());
+
+ _ResT __res = __v1;
+ ((__res = (__res << (sizeof(_Ts) * __CHAR_BIT__) | _ResT(__vs))), ...);
+ return __res;
+ }
+
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ constexpr auto
+ __as_int(_Tp __val)
+ {
+ if constexpr (is_same_v<_Tp, year>)
+ return static_cast<unsigned short>(static_cast<int>(__val));
+ else if constexpr (is_same_v<_Tp, month> || is_same_v<_Tp, day>)
+ return static_cast<unsigned char>(static_cast<unsigned>(__val));
+ else if constexpr (is_same_v<_Tp, weekday>)
+ return static_cast<unsigned char>(__val.c_encoding());
+ else if constexpr (is_same_v<_Tp, weekday_indexed>)
+ return __pack_ints(chrono::__as_int(__val.weekday()),
+ static_cast<unsigned char>(__val.index()));
+ else if constexpr (is_same_v<_Tp, weekday_last>)
+ return chrono::__as_int(__val.weekday());
+ else
+ static_assert(false);
+ }
+
+ template<typename _Arg, typename... _Args>
+ size_t
+ __int_hash(_Arg __arg, _Args... __args)
+ {
+ static_assert((is_integral_v<_Arg> && ... && is_integral_v<_Args>));
+
+ // TODO consider using a better quality hasher
+ using _Hasher = _Hash_impl;
+ size_t __result = _Hasher::hash(__arg);
+ ((__result = _Hasher::__hash_combine(__args, __result)), ...);
+ return __result;
+ }
+
+ template<typename... _Tps>
+ [[__gnu__::__always_inline__]]
+ inline size_t
+ __hash(_Tps... __vals)
+ {
+ if constexpr (sizeof...(_Tps) == 1)
+ return chrono::__int_hash(chrono::__as_int(__vals)...);
+ else
+ {
+ auto __res = chrono::__pack_ints(chrono::__as_int(__vals)...);
+ return chrono::__int_hash(__res);
+ }
+ }
+ } // namespace chrono
+
+ // duration
+ template<typename _Rep, typename _Period>
+ requires __is_hash_enabled_for<_Rep>
+ struct hash<chrono::duration<_Rep, _Period>>
+ {
+ size_t
+ operator()(const chrono::duration<_Rep, _Period>& __val) const
+ noexcept(__is_nothrow_copy_hashable<_Rep>)
+ {
+ if constexpr (is_integral_v<_Rep>)
+ return chrono::__int_hash(__val.count());
+ else
+ return hash<_Rep>{}(__val.count());
+ }
+ };
+
+ template<typename _Rep, typename _Period>
+ struct __is_fast_hash<hash<chrono::duration<_Rep, _Period>>>
+ : __is_fast_hash<hash<_Rep>>
+ {};
+
+ // time_point
+ template<typename _Clock, typename _Dur>
+ requires __is_hash_enabled_for<_Dur>
+ struct hash<chrono::time_point<_Clock, _Dur>>
+ {
+ size_t
+ operator()(const chrono::time_point<_Clock, _Dur>& __val) const
+ noexcept(__is_nothrow_copy_hashable<_Dur>)
+ { return hash<_Dur>{}(__val.time_since_epoch()); }
+ };
+
+ template<typename _Clock, typename _Dur>
+ struct __is_fast_hash<hash<chrono::time_point<_Clock, _Dur>>>
+ : __is_fast_hash<hash<_Dur>>
+ {};
+
+ // day
+ template<>
+ struct hash<chrono::day>
+ {
+ size_t
+ operator()(chrono::day __val) const noexcept
+ { return chrono::__hash(__val); }
+ };
+
+ // month
+ template<>
+ struct hash<chrono::month>
+ {
+ size_t
+ operator()(chrono::month __val) const noexcept
+ { return chrono::__hash(__val); }
+ };
+
+ // year
+ template<>
+ struct hash<chrono::year>
+ {
+ size_t
+ operator()(chrono::year __val) const noexcept
+ { return chrono::__hash(__val); }
+ };
+
+ // weekday
+ template<>
+ struct hash<chrono::weekday>
+ {
+ size_t
+ operator()(chrono::weekday __val) const noexcept
+ { return chrono::__hash(__val); }
+ };
+
+ // weekday_indexed
+ template<>
+ struct hash<chrono::weekday_indexed>
+ {
+ size_t
+ operator()(chrono::weekday_indexed __val) const noexcept
+ { return chrono::__hash(__val); }
+ };
+
+ // weekday_last
+ template<>
+ struct hash<chrono::weekday_last>
+ {
+ size_t
+ operator()(chrono::weekday_last __val) const noexcept
+ { return chrono::__hash(__val); }
+ };
+
+ // month_day
+ template<>
+ struct hash<chrono::month_day>
+ {
+ size_t
+ operator()(chrono::month_day __val) const noexcept
+ { return chrono::__hash(__val.month(), __val.day()); }
+ };
+
+ // month_day_last
+ template<>
+ struct hash<chrono::month_day_last>
+ {
+ size_t operator()(chrono::month_day_last __val) const noexcept
+ { return chrono::__hash(__val.month()); }
+ };
+
+ // month_weekday
+ template<>
+ struct hash<chrono::month_weekday>
+ {
+ size_t
+ operator()(chrono::month_weekday __val) const noexcept
+ { return chrono::__hash(__val.month(), __val.weekday_indexed()); }
+ };
+
+ // month_weekday_last
+ template<>
+ struct hash<chrono::month_weekday_last>
+ {
+ size_t
+ operator()(chrono::month_weekday_last __val) const noexcept
+ { return chrono::__hash(__val.month(), __val.weekday_last()); }
+ };
+
+ // year_month
+ template<>
+ struct hash<chrono::year_month>
+ {
+ size_t
+ operator()(chrono::year_month __val) const noexcept
+ { return chrono::__hash(__val.year(), __val.month()); }
+ };
+
+ // year_month_day
+ template<>
+ struct hash<chrono::year_month_day>
+ {
+ size_t
+ operator()(chrono::year_month_day __val) const noexcept
+ { return chrono::__hash(__val.year(), __val.month(), __val.day()); }
+ };
+
+ // year_month_day_last
+ template<>
+ struct hash<chrono::year_month_day_last>
+ {
+ size_t
+ operator()(chrono::year_month_day_last __val) const noexcept
+ { return chrono::__hash(__val.year(), __val.month()); }
+ };
+
+ // year_month_weekday
+ template<>
+ struct hash<chrono::year_month_weekday>
+ {
+ size_t
+ operator()(chrono::year_month_weekday __val) const noexcept
+ {
+ return chrono::__hash(__val.year(), __val.month(),
+ __val.weekday_indexed());
+ }
+ };
+
+ // year_month_weekday_last
+ template<>
+ struct hash<chrono::year_month_weekday_last>
+ {
+ size_t
+ operator()(chrono::year_month_weekday_last __val) const noexcept
+ {
+ return chrono::__hash(__val.year(), __val.month(),
+ __val.weekday_last());
+ }
+ };
+
+#if _GLIBCXX_HOSTED
+#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
+ // zoned_time
+ template<typename _Duration, typename _TimeZonePtr>
+ requires __is_hash_enabled_for<
+ typename chrono::zoned_time<_Duration, _TimeZonePtr>::duration>
+ && __is_hash_enabled_for<_TimeZonePtr>
+ struct hash<chrono::zoned_time<_Duration, _TimeZonePtr>>
+ {
+ private:
+ using _ActualDuration =
+ typename chrono::zoned_time<_Duration, _TimeZonePtr>::duration;
+
+ public:
+ size_t
+ operator()(const chrono::zoned_time<_Duration, _TimeZonePtr>& __val) const
+ noexcept(__is_nothrow_copy_hashable<_ActualDuration>
+ && __is_nothrow_copy_hashable<_TimeZonePtr>)
+ {
+ const auto __iduration = [&] {
+ const _ActualDuration __sd = __val.get_sys_time().time_since_epoch();
+ if constexpr (is_integral_v<typename _ActualDuration::rep>)
+ return __sd.count();
+ else
+ return hash<_ActualDuration>{}(__sd);
+ }();
+
+ const auto __izone = [&] {
+ const _TimeZonePtr __tz = __val.get_time_zone();
+ if constexpr (is_same_v<_TimeZonePtr, const chrono::time_zone*>)
+ return reinterpret_cast<uintptr_t>(__tz);
+ else
+ return hash<_TimeZonePtr>{}(__tz);
+ }();
+
+ return chrono::__int_hash(__iduration, __izone);
+ }
+ };
+
+ template<typename _Duration, typename _TimeZonePtr>
+ struct __is_fast_hash<hash<chrono::zoned_time<_Duration, _TimeZonePtr>>>
+ : __and_<__is_fast_hash<hash<
+ typename chrono::zoned_time<_Duration, _TimeZonePtr>::duration>>,
+ __is_fast_hash<hash<_TimeZonePtr>>>
+ {};
+
+ // leap_second
+ template<>
+ struct hash<chrono::leap_second>
+ {
+ size_t
+ operator()(chrono::leap_second __val) const noexcept
+ {
+ return chrono::__int_hash(
+ __val.date().time_since_epoch().count(),
+ __val.value().count());
+ }
+ };
+#endif // _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
+#endif // _GLIBCXX_HOSTED
+#endif // __glibcxx_chrono_cxx20 >= 202306
+
+#ifdef __glibcxx_chrono_cxx20
inline namespace literals
{
inline namespace chrono_literals
@@ -3374,7 +3675,7 @@ namespace __detail
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
-#if __cplusplus >= 202002L && _GLIBCXX_HOSTED
+#if defined __glibcxx_chrono_cxx20 && _GLIBCXX_HOSTED
# include <bits/chrono_io.h>
#endif
diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex
index 59ef905..4765425 100644
--- a/libstdc++-v3/include/std/complex
+++ b/libstdc++-v3/include/std/complex
@@ -96,7 +96,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
_GLIBCXX20_CONSTEXPR complex<_Tp> conj(const complex<_Tp>&);
/// Return complex with magnitude @a rho and angle @a theta.
- template<typename _Tp> complex<_Tp> polar(const _Tp&, const _Tp& = 0);
+ template<typename _Tp> complex<_Tp> polar(const _Tp&, const _Tp& = _Tp(0));
// Transcendentals:
/// Return complex cosine of @a z.
@@ -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)
@@ -1038,7 +1038,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline complex<_Tp>
polar(const _Tp& __rho, const _Tp& __theta)
{
- __glibcxx_assert( __rho >= 0 );
+ __glibcxx_assert( __rho >= _Tp(0) );
return complex<_Tp>(__rho * cos(__theta), __rho * sin(__theta));
}
@@ -1238,13 +1238,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__x == _Tp())
{
- _Tp __t = sqrt(abs(__y) / 2);
+ _Tp __t = sqrt(abs(__y) / _Tp(2));
return complex<_Tp>(__t, __y < _Tp() ? -__t : __t);
}
else
{
- _Tp __t = sqrt(2 * (std::abs(__z) + abs(__x)));
- _Tp __u = __t / 2;
+ _Tp __t = sqrt(_Tp(2) * (std::abs(__z) + abs(__x)));
+ _Tp __u = __t / _Tp(2);
return __x > _Tp()
? complex<_Tp>(__u, __y / __t)
: complex<_Tp>(abs(__y) / __t, __y < _Tp() ? -__u : __u);
@@ -1334,7 +1334,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
complex<_Tp>
__complex_pow_unsigned(complex<_Tp> __x, unsigned __n)
{
- complex<_Tp> __y = __n % 2 ? __x : complex<_Tp>(1);
+ complex<_Tp> __y = __n % 2 ? __x : complex<_Tp>(_Tp(1));
while (__n >>= 1)
{
@@ -1357,7 +1357,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
pow(const complex<_Tp>& __z, int __n)
{
return __n < 0
- ? complex<_Tp>(1) / std::__complex_pow_unsigned(__z, -(unsigned)__n)
+ ? complex<_Tp>(_Tp(1)) / std::__complex_pow_unsigned(__z,
+ -(unsigned)__n)
: std::__complex_pow_unsigned(__z, __n);
}
@@ -2123,8 +2124,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 +2308,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 +2344,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 +2388,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 +2424,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 +2463,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 +2507,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 +2517,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/concepts b/libstdc++-v3/include/std/concepts
index 5899f03..870b0a4 100644
--- a/libstdc++-v3/include/std/concepts
+++ b/libstdc++-v3/include/std/concepts
@@ -204,7 +204,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
private:
template<typename _Tp, typename _Up>
- static constexpr bool
+ static consteval bool
_S_noexcept()
{
if constexpr (__adl_swap<_Tp, _Up>)
@@ -296,6 +296,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; };
} // namespace __detail
+ // [concept.comparisoncommontype], helpers for comparison common types
+ namespace __detail
+ {
+ template<typename _Tp, typename _Up,
+ typename _Cref = common_reference_t<const _Tp&, const _Up&>>
+ concept __comparison_common_type_with_impl
+ = same_as<common_reference_t<const _Tp&, const _Up&>,
+ common_reference_t<const _Up&, const _Tp&>>
+ && requires {
+ requires convertible_to<const _Tp&, const _Cref&>
+ || convertible_to<_Tp, const _Cref&>;
+ requires convertible_to<const _Up&, const _Cref&>
+ || convertible_to<_Up, const _Cref&>;
+ };
+
+ template<typename _Tp, typename _Up>
+ concept __comparison_common_type_with
+ = __comparison_common_type_with_impl<remove_cvref_t<_Tp>,
+ remove_cvref_t<_Up>>;
+ } // namespace __detail
+
// [concept.equalitycomparable], concept equality_comparable
namespace __detail
@@ -316,7 +337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Up>
concept equality_comparable_with
= equality_comparable<_Tp> && equality_comparable<_Up>
- && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>>
+ && __detail::__comparison_common_type_with<_Tp, _Up>
&& equality_comparable<common_reference_t<__detail::__cref<_Tp>,
__detail::__cref<_Up>>>
&& __detail::__weakly_eq_cmp_with<_Tp, _Up>;
diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable
index 3525ff3..dcf0b92 100644
--- a/libstdc++-v3/include/std/condition_variable
+++ b/libstdc++-v3/include/std/condition_variable
@@ -193,15 +193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__wait_until_impl(unique_lock<mutex>& __lock,
const chrono::time_point<steady_clock, _Dur>& __atime)
{
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
-
- __gthread_time_t __ts =
- {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
-
+ __gthread_time_t __ts = chrono::__to_timeout_gthread_time_t(__atime);
_M_cond.wait_until(*__lock.mutex(), CLOCK_MONOTONIC, __ts);
return (steady_clock::now() < __atime
@@ -214,15 +206,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__wait_until_impl(unique_lock<mutex>& __lock,
const chrono::time_point<system_clock, _Dur>& __atime)
{
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
-
- __gthread_time_t __ts =
- {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
-
+ __gthread_time_t __ts = chrono::__to_timeout_gthread_time_t(__atime);
_M_cond.wait_until(*__lock.mutex(), __ts);
return (system_clock::now() < __atime
diff --git a/libstdc++-v3/include/std/debugging b/libstdc++-v3/include/std/debugging
new file mode 100644
index 0000000..4cf7e4a
--- /dev/null
+++ b/libstdc++-v3/include/std/debugging
@@ -0,0 +1,77 @@
+// Debugging support -*- 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.
+
+// 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 include/debugging
+ * This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_DEBUGGING
+#define _GLIBCXX_DEBUGGING 1
+
+#define __glibcxx_want_debugging
+#include <bits/version.h>
+
+#if __cpp_lib_debugging // C++ >= 26
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+// N.B. _GLIBCXX_BEGIN_NAMESPACE_VERSION is not used here.
+
+/** Try to determine if the program is running under control of a debugger.
+ *
+ * On GNU/Linux systems this function will only return true if the program
+ * is being traced by another program which is known to be a debugger.
+ * This is determined by checking the command name of the tracing program
+ * against a list of known debuggers, such as "gdb".
+ *
+ * On other POSIX-based systems, this function will return true if the
+ * program is being traced by any other process, which means it can return
+ * true for non-debugger utilities that use the ptrace system call.
+ *
+ * @since C++26
+ */
+bool
+is_debugger_present() noexcept;
+
+/** Stop the program with a breakpoint or debug trap.
+ *
+ * The details of how a breakpoint is implemented are platform-specific.
+ * Some systems provide a special instruction, such as `int3` in x86.
+ * When no more appropriate mechanism is available, this will stop the
+ * program using `__builtin_trap()`. It might not be possible for the
+ * program to continue after such a breakpoint.
+ *
+ * @since C++26
+ */
+void
+breakpoint() noexcept;
+
+/** Stop the program if it is running under control of a debugger.
+ *
+ * @since C++26
+ */
+void
+breakpoint_if_debugging() noexcept;
+
+} // namespace std
+#endif
+#endif // _GLIBCXX_DEBUGGING
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index 2badab8..600f607 100644
--- a/libstdc++-v3/include/std/deque
+++ b/libstdc++-v3/include/std/deque
@@ -66,7 +66,6 @@
#include <bits/stl_construct.h>
#include <bits/stl_uninitialized.h>
#include <bits/stl_deque.h>
-#include <bits/refwrap.h>
#include <bits/range_access.h>
#include <bits/deque.tcc>
@@ -101,19 +100,16 @@ namespace std _GLIBCXX_VISIBILITY(default)
_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Alloc, typename _Predicate>
- inline typename deque<_Tp, _Alloc>::size_type
- erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred)
+ inline typename _GLIBCXX_STD_C::deque<_Tp, _Alloc>::size_type
+ erase_if(_GLIBCXX_STD_C::deque<_Tp, _Alloc>& __cont, _Predicate __pred)
{
- using namespace __gnu_cxx;
- _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __ucont = __cont;
const auto __osz = __cont.size();
- const auto __end = __ucont.end();
- auto __removed = std::__remove_if(__ucont.begin(), __end,
- __ops::__pred_iter(std::ref(__pred)));
+ const auto __end = __cont.end();
+ auto __removed = std::__remove_if(__cont.begin(), __end,
+ std::move(__pred));
if (__removed != __end)
{
- __cont.erase(__niter_wrap(__cont.begin(), __removed),
- __cont.end());
+ __cont.erase(__removed, __end);
return __osz - __cont.size();
}
@@ -122,24 +118,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Alloc,
typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>
- inline typename deque<_Tp, _Alloc>::size_type
- erase(deque<_Tp, _Alloc>& __cont, const _Up& __value)
- {
- using namespace __gnu_cxx;
- _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __ucont = __cont;
- const auto __osz = __cont.size();
- const auto __end = __ucont.end();
- auto __removed = std::__remove_if(__ucont.begin(), __end,
- __ops::__iter_equals_val(__value));
- if (__removed != __end)
- {
- __cont.erase(__niter_wrap(__cont.begin(), __removed),
- __cont.end());
- return __osz - __cont.size();
- }
+ inline typename _GLIBCXX_STD_C::deque<_Tp, _Alloc>::size_type
+ erase(_GLIBCXX_STD_C::deque<_Tp, _Alloc>& __cont, const _Up& __value)
+ { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }
- return 0;
- }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cpp_lib_erase_if
diff --git a/libstdc++-v3/include/std/expected b/libstdc++-v3/include/std/expected
index 5dc1dfb..a03a7d3 100644
--- a/libstdc++-v3/include/std/expected
+++ b/libstdc++-v3/include/std/expected
@@ -474,6 +474,7 @@ namespace __expected
template<typename _Up = remove_cv_t<_Tp>>
requires (!is_same_v<remove_cvref_t<_Up>, expected>)
&& (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
+ && (!is_same_v<remove_cvref_t<_Up>, unexpect_t>)
&& is_constructible_v<_Tp, _Up>
&& (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
&& __expected::__not_constructing_bool_from_expected<_Tp, _Up>
@@ -821,32 +822,36 @@ namespace __expected
return std::move(_M_unex);
}
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4406. value_or return statement is inconsistent with Mandates
template<typename _Up = remove_cv_t<_Tp>>
- constexpr _Tp
+ constexpr remove_cv_t<_Tp>
value_or(_Up&& __v) const &
noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
is_nothrow_convertible<_Up, _Tp>>)
{
- static_assert( is_copy_constructible_v<_Tp> );
+ using _Xp = remove_cv_t<_Tp>;
+ static_assert( is_convertible_v<const _Tp&, _Xp> );
static_assert( is_convertible_v<_Up, _Tp> );
if (_M_has_value)
return _M_val;
- return static_cast<_Tp>(std::forward<_Up>(__v));
+ return std::forward<_Up>(__v);
}
template<typename _Up = remove_cv_t<_Tp>>
- constexpr _Tp
+ constexpr remove_cv_t<_Tp>
value_or(_Up&& __v) &&
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
is_nothrow_convertible<_Up, _Tp>>)
{
- static_assert( is_move_constructible_v<_Tp> );
- static_assert( is_convertible_v<_Up, _Tp> );
+ using _Xp = remove_cv_t<_Tp>;
+ static_assert( is_convertible_v<_Tp, _Xp> );
+ static_assert( is_convertible_v<_Up, _Xp> );
if (_M_has_value)
return std::move(_M_val);
- return static_cast<_Tp>(std::forward<_Up>(__v));
+ return std::forward<_Up>(__v);
}
template<typename _Gr = _Er>
@@ -1158,35 +1163,47 @@ namespace __expected
{ __t == __u } -> convertible_to<bool>;
{ __e == __e2 } -> convertible_to<bool>;
}
+ [[nodiscard]]
friend constexpr bool
operator==(const expected& __x, const expected<_Up, _Er2>& __y)
noexcept(noexcept(bool(*__x == *__y))
&& noexcept(bool(__x.error() == __y.error())))
{
+ if (__x.has_value() != __y.has_value())
+ return false;
if (__x.has_value())
- return __y.has_value() && bool(*__x == *__y);
- else
- return !__y.has_value() && bool(__x.error() == __y.error());
+ return *__x == *__y;
+ return __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>;
}
+ [[nodiscard]]
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); }
+ {
+ if (__x.has_value())
+ return *__x == __v;
+ return false;
+ }
template<typename _Er2>
requires requires (const _Er& __e, const _Er2& __e2) {
{ __e == __e2 } -> convertible_to<bool>;
}
+ [[nodiscard]]
friend constexpr bool
operator==(const expected& __x, const unexpected<_Er2>& __e)
noexcept(noexcept(bool(__x.error() == __e.error())))
- { return !__x.has_value() && bool(__x.error() == __e.error()); }
+ {
+ if (!__x.has_value())
+ return __x.error() == __e.error();
+ return false;
+ }
friend constexpr void
swap(expected& __x, expected& __y)
@@ -1836,24 +1853,31 @@ namespace __expected
&& requires (const _Er& __e, const _Er2& __e2) {
{ __e == __e2 } -> convertible_to<bool>;
}
+ [[nodiscard]]
friend constexpr bool
operator==(const expected& __x, const expected<_Up, _Er2>& __y)
noexcept(noexcept(bool(__x.error() == __y.error())))
{
+ if (__x.has_value() != __y.has_value())
+ return false;
if (__x.has_value())
- return __y.has_value();
- else
- return !__y.has_value() && bool(__x.error() == __y.error());
+ return true;
+ return __x.error() == __y.error();
}
template<typename _Er2>
requires requires (const _Er& __e, const _Er2& __e2) {
{ __e == __e2 } -> convertible_to<bool>;
}
+ [[nodiscard]]
friend constexpr bool
operator==(const expected& __x, const unexpected<_Er2>& __e)
noexcept(noexcept(bool(__x.error() == __e.error())))
- { return !__x.has_value() && bool(__x.error() == __e.error()); }
+ {
+ if (!__x.has_value())
+ return __x.error() == __e.error();
+ return false;
+ }
friend constexpr void
swap(expected& __x, expected& __y)
diff --git a/libstdc++-v3/include/std/flat_map b/libstdc++-v3/include/std/flat_map
index 405caa8..e48c3ea 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;
}
@@ -947,7 +953,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
using iterator_category = input_iterator_tag;
using iterator_concept = random_access_iterator_tag;
- using value_type = pair<const key_type, mapped_type>;
+ using value_type = pair<key_type, mapped_type>;
using reference = pair<const key_type&,
ranges::__maybe_const_t<_Const, mapped_type>&>;
using difference_type = ptrdiff_t;
@@ -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 23f0097..f64f35a 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> // 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
@@ -97,22 +97,29 @@ namespace __format
#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 _Seq> class _Seq_sink;
-
- template<typename _CharT, typename _Alloc = allocator<_CharT>>
- using _Str_sink
- = _Seq_sink<basic_string<_CharT, char_traits<_CharT>, _Alloc>>;
-
- // template<typename _CharT, typename _Alloc = allocator<_CharT>>
- // using _Vec_sink = _Seq_sink<vector<_CharT, _Alloc>>;
+ template<typename _Out, typename _CharT> class _Padding_sink;
+ template<typename _Out, typename _CharT> class _Escaping_sink;
// Output iterator that writes to a type-erase character sink.
template<typename _CharT>
class _Sink_iter;
+ // Output iterator that ignores the characters
+ template<typename _CharT>
+ class _Drop_iter;
+
+ // An unspecified output iterator type used in the `formattable` concept.
+ template<typename _CharT>
+ struct _Iter_for
+ { using type = _Drop_iter<_CharT>; };
+
template<typename _CharT>
using __format_context = basic_format_context<_Sink_iter<_CharT>, _CharT>;
@@ -131,6 +138,7 @@ namespace __format
template<typename, typename...> friend struct std::basic_format_string;
};
+
} // namespace __format
/// @endcond
@@ -469,36 +477,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.
+ _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 _Align {
- _Align_default,
- _Align_left,
- _Align_right,
- _Align_centre,
- };
-
- 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
@@ -510,9 +515,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;
@@ -520,12 +533,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;
@@ -544,42 +556,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;
}
@@ -600,7 +618,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;
@@ -827,7 +845,7 @@ namespace __format
{
// Encode fill char as multiple code units of type _CharT.
const char32_t __arr[1]{ __fill_char };
- _Utf_view<_CharT, const char32_t(&)[1]> __v(__arr);
+ _Utf_view<_CharT, span<const char32_t, 1>> __v(__arr);
basic_string<_CharT> __padstr(__v.begin(), __v.end());
__padding = __padstr;
while (__l-- > 0)
@@ -868,18 +886,37 @@ 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);
}
- // Values are indices into _Escapes::all.
+ 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 {
- _Tc_quote = 12,
- _Tc_apos = 15
+ _Term_none,
+ _Term_quote,
+ _Term_apos,
};
+ using enum _Term_char;
template<typename _CharT>
struct _Escapes
@@ -890,10 +927,6 @@ namespace __format
_Str_view _S_all()
{ return _GLIBCXX_WIDEN("\t\\t\n\\n\r\\r\\\\\\\"\\\"'\\'\\u\\x"); }
- static constexpr
- _CharT _S_term(_Term_char __term)
- { return _S_all()[static_cast<unsigned char>(__term)]; }
-
static consteval
_Str_view _S_tab()
{ return _S_all().substr(0, 3); }
@@ -925,6 +958,21 @@ namespace __format
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>
@@ -934,11 +982,27 @@ namespace __format
static consteval
_Str_view _S_all()
- { return _GLIBCXX_WIDEN("{}"); }
+ { return _GLIBCXX_WIDEN("[]{}(), : "); }
static consteval
- _Str_view _S_braces()
+ _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>
@@ -953,9 +1017,9 @@ namespace __format
case _Esc::_S_bslash()[0]:
return true;
case _Esc::_S_quote()[0]:
- return __term == _Term_char::_Tc_quote;
+ return __term == _Term_quote;
case _Esc::_S_apos()[0]:
- return __term == _Term_char::_Tc_apos;
+ return __term == _Term_apos;
default:
return (__c >= 0 && __c < 0x20) || __c == 0x7f;
};
@@ -1005,6 +1069,17 @@ namespace __format
template<typename _Out, typename _CharT>
_Out
+ __write_escape_seqs(_Out __out, basic_string_view<_CharT> __units)
+ {
+ using _UChar = make_unsigned_t<_CharT>;
+ for (_CharT __c : __units)
+ __out = __format::__write_escape_seq(
+ __out, static_cast<_UChar>(__c), _Escapes<_CharT>::_S_x());
+ return __out;
+ }
+
+ template<typename _Out, typename _CharT>
+ _Out
__write_escaped_char(_Out __out, _CharT __c)
{
using _UChar = make_unsigned_t<_CharT>;
@@ -1024,9 +1099,8 @@ namespace __format
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());
+ return __format::__write_escape_seq(
+ __out, static_cast<_UChar>(__c), _Esc::_S_u());
}
}
@@ -1062,12 +1136,10 @@ namespace __format
template<typename _CharT, typename _Out>
_Out
- __write_escaped_unicode(_Out __out,
- basic_string_view<_CharT> __str,
- _Term_char __term)
+ __write_escaped_unicode_part(_Out __out, basic_string_view<_CharT>& __str,
+ bool& __prev_esc, _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';
@@ -1081,10 +1153,10 @@ namespace __format
}();
__unicode::_Utf_view<char32_t, _Str_view> __v(std::move(__str));
+ __str = {};
+
auto __first = __v.begin();
auto const __last = __v.end();
-
- bool __prev_esc = true;
while (__first != __last)
{
bool __esc_ascii = false;
@@ -1123,15 +1195,32 @@ namespace __format
__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());
+ // __esc_replace
+ else if (_Str_view __units(__first.base(), __first._M_units());
+ __units.end() != __last.base())
+ __out = __format::__write_escape_seqs(__out, __units);
+ else
+ {
+ __str = __units;
+ return __out;
+ }
+
__prev_esc = true;
++__first;
-
}
+
+ return __out;
+ }
+
+ template<typename _CharT, typename _Out>
+ _Out
+ __write_escaped_unicode(_Out __out, basic_string_view<_CharT> __str,
+ _Term_char __term)
+ {
+ bool __prev_escape = true;
+ __out = __format::__write_escaped_unicode_part(__out, __str,
+ __prev_escape, __term);
+ __out = __format::__write_escape_seqs(__out, __str);
return __out;
}
@@ -1139,8 +1228,7 @@ namespace __format
_Out
__write_escaped(_Out __out, basic_string_view<_CharT> __str, _Term_char __term)
{
- *__out = _Escapes<_CharT>::_S_term(__term);
- ++__out;
+ __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);
@@ -1151,8 +1239,7 @@ namespace __format
// TODO Handle non-ascii extended encoding
__out = __format::__write_escaped_ascii(__out, __str, __term);
- *__out = _Escapes<_CharT>::_S_term(__term);
- return ++__out;
+ return __format::__write(__out, _Escapes<_CharT>::_S_term(__term));
}
// A lightweight optional<locale>.
@@ -1231,6 +1318,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)
{
@@ -1267,11 +1361,14 @@ namespace __format
return __first;
if (*__first == 's')
- ++__first;
+ {
+ __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
@@ -1287,71 +1384,90 @@ namespace __format
format(basic_string_view<_CharT> __s,
basic_format_context<_Out, _CharT>& __fc) const
{
- constexpr auto __term = __format::_Term_char::_Tc_quote;
- const auto __write_direct = [&]
- {
- if (_M_spec._M_type == _Pres_esc)
- return __format::__write_escaped(__fc.out(), __s, __term);
- else
- return __format::__write(__fc.out(), __s);
- };
+ 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 __write_direct();
+ return __format::__write(__fc.out(), __s);
- const size_t __prec =
- _M_spec._M_prec_kind != _WP_none
- ? _M_spec._M_get_precision(__fc)
- : basic_string_view<_CharT>::npos;
+ 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);
+ }
- const size_t __estimated_width = _S_trunc(__s, __prec);
- // N.B. Escaping only increases width
- if (_M_spec._M_get_width(__fc) <= __estimated_width
- && _M_spec._M_prec_kind == _WP_none)
- return __write_direct();
+ 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);
- if (_M_spec._M_type != _Pres_esc)
- return __format::__write_padded_as_spec(__s, __estimated_width,
- __fc, _M_spec);
+ 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);
- __format::_Str_sink<_CharT> __sink;
- __format::_Sink_iter<_CharT> __out(__sink);
- __format::__write_escaped(__out, __s, __term);
- basic_string_view<_CharT> __escaped(__sink.view().data(),
- __sink.view().size());
- const size_t __escaped_width = _S_trunc(__escaped, __prec);
// 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.
- return __format::__write_padded_as_spec(__escaped, __escaped_width,
- __fc, _M_spec);
+ _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_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
+ {
+ auto __handle_debug = [this, &__rg]<typename _NOut>(_NOut __nout)
+ {
+ if (!_M_spec._M_debug)
+ return ranges::copy(__rg, std::move(__nout)).out;
+
+ _Escaping_sink<_NOut, _CharT>
+ __sink(std::move(__nout), _Term_quote);
+ ranges::copy(__rg, __sink.out());
+ return __sink._M_finish();
+ };
+
+ const size_t __padwidth = _M_spec._M_get_width(__fc);
+ if (__padwidth == 0 && _M_spec._M_prec_kind == _WP_none)
+ return __handle_debug(__fc.out());
+
+ _Padding_sink<_Out, _CharT>
+ __sink(__fc.out(), __padwidth, _M_spec._M_get_precision(__fc));
+ __handle_debug(__sink.out());
+ return __sink._M_finish(_M_spec._M_align, _M_spec._M_fill);
+ }
+ }
+
constexpr void
set_debug_format() noexcept
- { _M_spec._M_type = _Pres_esc; }
+ { _M_spec._M_debug = true; }
#endif
private:
- static size_t
- _S_trunc(basic_string_view<_CharT>& __s, size_t __prec)
- {
- if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
- {
- if (__prec != basic_string_view<_CharT>::npos)
- return __unicode::__truncate(__s, __prec);
- else
- return __unicode::__field_width(__s);
- }
- else
- {
- __s = __s.substr(0, __prec);
- return __s.size();
- }
- }
-
_Spec<_CharT> _M_spec{};
};
@@ -1364,6 +1480,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)
{
@@ -1451,7 +1577,7 @@ 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;
@@ -1459,7 +1585,7 @@ namespace __format
case '?':
if (__type == _AsChar)
{
- __spec._M_type = _Pres_esc;
+ __spec._M_debug = true;
++__first;
}
#endif
@@ -1480,7 +1606,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'");
@@ -1489,8 +1616,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 "
@@ -1602,52 +1730,34 @@ 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);
- template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- _M_format_character_escaped(_CharT __c,
- basic_format_context<_Out, _CharT>& __fc) const
- {
- using _Esc = _Escapes<_CharT>;
- constexpr auto __term = __format::_Term_char::_Tc_apos;
- const basic_string_view<_CharT> __in(&__c, 1u);
- if (_M_spec._M_get_width(__fc) <= 3u)
- return __format::__write_escaped(__fc.out(), __in, __term);
+ __width += 2;
+ if (_M_spec._M_get_width(__fc) <= __width)
+ return __format::__write_escaped(__fc.out(), __in, _Term_apos);
_CharT __buf[12];
- __format::_Fixedbuf_sink<_CharT> __sink(__buf);
- __format::_Sink_iter<_CharT> __out(__sink);
- __format::__write_escaped(__out, __in, __term);
-
- const basic_string_view<_CharT> __escaped = __sink.view();
- size_t __estimated_width;
- if (__escaped[1] == _Esc::_S_bslash()[0]) // escape sequence
- __estimated_width = __escaped.size();
- else
- __estimated_width = 2 + _S_character_width(__c);
- return __format::__write_padded_as_spec(__escaped,
- __estimated_width,
+ _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);
}
@@ -1747,37 +1857,27 @@ namespace __format
__align, __nfill, __fill_char);
}
-#if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
- template<typename _Tp>
- using make_unsigned_t
- = typename __conditional_t<(sizeof(_Tp) <= sizeof(long long)),
- std::make_unsigned<_Tp>,
- type_identity<unsigned __int128>>::type;
-
- // std::to_chars is not overloaded for int128 in strict mode.
- template<typename _Int>
- static to_chars_result
- to_chars(char* __first, char* __last, _Int __value, int __base)
- { return std::__to_chars_i<_Int>(__first, __last, __value, __base); }
-#endif
-
_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__
@@ -1811,14 +1911,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.
@@ -2287,9 +2387,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)
@@ -2312,6 +2419,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
@@ -2331,11 +2582,8 @@ 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)
- return _M_f._M_format_character_escaped(__u, __fc);
else
return _M_f.format(static_cast<make_unsigned_t<_CharT>>(__u), __fc);
}
@@ -2343,13 +2591,18 @@ namespace __format
#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:
__format::__formatter_int<_CharT> _M_f;
};
+#if __glibcxx_print >= 202403L
+ template<__format::__char _CharT>
+ constexpr bool enable_nonlocking_formatter_optimization<_CharT> = true;
+#endif
+
#ifdef _GLIBCXX_USE_WCHAR_T
/// Format a char value for wide character output.
template<>
@@ -2367,11 +2620,8 @@ 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)
- return _M_f._M_format_character_escaped(__u, __fc);
else
return _M_f.format(static_cast<unsigned char>(__u), __fc);
}
@@ -2379,7 +2629,7 @@ namespace __format
#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:
@@ -2414,6 +2664,11 @@ namespace __format
__format::__formatter_str<_CharT> _M_f;
};
+#if __glibcxx_print >= 202403L
+ template<__format::__char _CharT>
+ constexpr bool enable_nonlocking_formatter_optimization<_CharT*> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<const _CharT*, _CharT>
{
@@ -2439,6 +2694,12 @@ namespace __format
__format::__formatter_str<_CharT> _M_f;
};
+#if __glibcxx_print >= 202403L
+ template<__format::__char _CharT>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<const _CharT*> = true;
+#endif
+
template<__format::__char _CharT, size_t _Nm>
struct formatter<_CharT[_Nm], _CharT>
{
@@ -2463,6 +2724,11 @@ namespace __format
__format::__formatter_str<_CharT> _M_f;
};
+#if __glibcxx_print >= 202403L
+ template<__format::__char _CharT, size_t _Nm>
+ constexpr bool enable_nonlocking_formatter_optimization<_CharT[_Nm]> = true;
+#endif
+
template<typename _Traits, typename _Alloc>
struct formatter<basic_string<char, _Traits, _Alloc>, char>
{
@@ -2487,6 +2753,13 @@ namespace __format
__format::__formatter_str<char> _M_f;
};
+#if __glibcxx_print >= 202403L
+ template<typename _Tr, typename _Alloc>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<basic_string<char, _Tr, _Alloc>>
+ = true;
+#endif
+
#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _Traits, typename _Alloc>
struct formatter<basic_string<wchar_t, _Traits, _Alloc>, wchar_t>
@@ -2511,6 +2784,14 @@ namespace __format
private:
__format::__formatter_str<wchar_t> _M_f;
};
+
+#if __glibcxx_print >= 202403L
+ template<typename _Tr, typename _Alloc>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<basic_string<wchar_t, _Tr, _Alloc>>
+ = true;
+#endif
+
#endif // USE_WCHAR_T
template<typename _Traits>
@@ -2537,6 +2818,13 @@ namespace __format
__format::__formatter_str<char> _M_f;
};
+#if __glibcxx_print >= 202403L
+ template<typename _Tr>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<basic_string_view<char, _Tr>>
+ = true;
+#endif
+
#ifdef _GLIBCXX_USE_WCHAR_T
template<typename _Traits>
struct formatter<basic_string_view<wchar_t, _Traits>, wchar_t>
@@ -2561,6 +2849,13 @@ namespace __format
private:
__format::__formatter_str<wchar_t> _M_f;
};
+
+#if __glibcxx_print >= 202403L
+ template<typename _Tr>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<basic_string_view<wchar_t, _Tr>>
+ = true;
+#endif
#endif // USE_WCHAR_T
/// @}
@@ -2585,12 +2880,14 @@ namespace __format
#endif
template<> inline constexpr bool __is_formattable_integer<char16_t> = false;
template<> inline constexpr bool __is_formattable_integer<char32_t> = false;
+
+ template<typename _Tp>
+ concept __formattable_integer = __is_formattable_integer<_Tp>;
}
/// @endcond
/// Format an integer.
- template<typename _Tp, __format::__char _CharT>
- requires __format::__is_formattable_integer<_Tp>
+ template<__format::__formattable_integer _Tp, __format::__char _CharT>
struct formatter<_Tp, _CharT>
{
formatter() = default;
@@ -2611,6 +2908,12 @@ namespace __format
__format::__formatter_int<_CharT> _M_f;
};
+#if __glibcxx_print >= 202403L
+ template<__format::__formattable_integer _Tp>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<_Tp> = true;
+#endif
+
#if defined __glibcxx_to_chars
/// Format a floating-point value.
template<__format::__formattable_float _Tp, __format::__char _CharT>
@@ -2632,6 +2935,12 @@ namespace __format
__format::__formatter_fp<_CharT> _M_f;
};
+#if __glibcxx_print >= 202403L
+ template<__format::__formattable_float _Tp>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<_Tp> = true;
+#endif
+
#if __LDBL_MANT_DIG__ == __DBL_MANT_DIG__
// Reuse __formatter_fp<C>::format<double, Out> for long double.
template<__format::__char _CharT>
@@ -2720,8 +3029,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>
{
@@ -2735,7 +3044,30 @@ 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 == 2
+ // Use __formatter_fp<C>::format<__format::__flt128_t, Out> for __float128,
+ // when long double is not 128bit IEEE type.
+ 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;
@@ -2745,7 +3077,7 @@ namespace __format
#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;
@@ -2776,122 +3108,23 @@ 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;
};
+#if __glibcxx_print >= 202403L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<const void*> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<void*, _CharT>
{
@@ -2908,9 +3141,15 @@ namespace __format
{ return _M_f.format(__v, __fc); }
private:
- formatter<const void*, _CharT> _M_f;
+ __format::__formatter_ptr<_CharT> _M_f;
};
+#if __glibcxx_print >= 202403l
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<void*> = true;
+#endif
+
template<__format::__char _CharT>
struct formatter<nullptr_t, _CharT>
{
@@ -2927,98 +3166,44 @@ 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 __glibcxx_print >= 202403L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<nullptr_t> = true;
+#endif
+
+#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> { };
+ : private __formatter_disabled { };
#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>;
-#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>
@@ -3036,6 +3221,43 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
namespace __format
{
template<typename _CharT>
+ class _Drop_iter
+ {
+ public:
+ using iterator_category = output_iterator_tag;
+ using value_type = void;
+ using difference_type = ptrdiff_t;
+ using pointer = void;
+ using reference = void;
+
+ _Drop_iter() = default;
+ _Drop_iter(const _Drop_iter&) = default;
+ _Drop_iter& operator=(const _Drop_iter&) = default;
+
+ [[__gnu__::__always_inline__]]
+ constexpr _Drop_iter&
+ operator=(_CharT __c)
+ { return *this; }
+
+ [[__gnu__::__always_inline__]]
+ constexpr _Drop_iter&
+ operator=(basic_string_view<_CharT> __s)
+ { return *this; }
+
+ [[__gnu__::__always_inline__]]
+ constexpr _Drop_iter&
+ operator*() { return *this; }
+
+ [[__gnu__::__always_inline__]]
+ constexpr _Drop_iter&
+ operator++() { return *this; }
+
+ [[__gnu__::__always_inline__]]
+ constexpr _Drop_iter
+ operator++(int) { return *this; }
+ };
+
+ template<typename _CharT>
class _Sink_iter
{
_Sink<_CharT>* _M_sink = nullptr;
@@ -3086,6 +3308,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.
@@ -3205,6 +3431,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;
@@ -3246,7 +3477,7 @@ namespace __format
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
@@ -3260,12 +3491,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
@@ -3337,6 +3568,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?
@@ -3362,7 +3604,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())
@@ -3373,9 +3615,21 @@ namespace __format
}
return __s;
}
+
+ basic_string_view<_CharT>
+ view()
+ {
+ auto __span = _M_span();
+ return basic_string_view<_CharT>(__span.data(), __span.size());
+ }
};
- // A sink that writes to an output iterator.
+ template<typename _CharT, typename _Alloc = allocator<_CharT>>
+ using _Str_sink
+ = _Seq_sink<basic_string<_CharT, char_traits<_CharT>, _Alloc>>;
+
+ // template<typename _CharT, typename _Alloc = allocator<_CharT>>
+ // 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>
@@ -3407,6 +3661,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
@@ -3469,6 +3731,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
{
@@ -3543,20 +3813,289 @@ 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);
+ }
+ };
+
+ template<typename _Out, typename _CharT>
+ class _Escaping_sink : public _Buf_sink<_CharT>
+ {
+ using _Esc = _Escapes<_CharT>;
+
+ _Out _M_out;
+ _Term_char _M_term : 2;
+ unsigned _M_prev_escape : 1;
+ unsigned _M_out_discards : 1;
+
+ void
+ _M_sync_discarding()
+ {
+ if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
+ _M_out_discards = _M_out._M_discarding();
+ }
+
+ void
+ _M_write()
+ {
+ span<_CharT> __bytes = this->_M_used();
+ basic_string_view<_CharT> __str(__bytes.data(), __bytes.size());
+
+ size_t __rem = 0;
+ if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
+ {
+ bool __prev_escape = _M_prev_escape;
+ _M_out = __format::__write_escaped_unicode_part(
+ std::move(_M_out), __str, __prev_escape, _M_term);
+ _M_prev_escape = __prev_escape;
+
+ __rem = __str.size();
+ if (__rem > 0 && __str.data() != this->_M_buf) [[unlikely]]
+ ranges::move(__str, this->_M_buf);
+ }
+ else
+ _M_out = __format::__write_escaped_ascii(
+ std::move(_M_out), __str, _M_term);
+
+ this->_M_reset(this->_M_buf, __rem);
+ _M_sync_discarding();
+ }
+
+ void
+ _M_overflow() override
+ {
+ if (_M_out_discards)
+ this->_M_rewind();
+ else
+ _M_write();
+ }
+
+ bool
+ _M_discarding() const override
+ { return _M_out_discards; }
+
+ public:
+ [[__gnu__::__always_inline__]]
+ explicit
+ _Escaping_sink(_Out __out, _Term_char __term)
+ : _M_out(std::move(__out)), _M_term(__term),
+ _M_prev_escape(true), _M_out_discards(false)
+ {
+ _M_out = __format::__write(std::move(_M_out), _Esc::_S_term(_M_term));
+ _M_sync_discarding();
+ }
+
+ _Out
+ _M_finish()
+ {
+ if (_M_out_discards)
+ return std::move(_M_out);
+
+ if (!this->_M_used().empty())
+ {
+ _M_write();
+ if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
+ if (auto __rem = this->_M_used(); !__rem.empty())
+ {
+ basic_string_view<_CharT> __str(__rem.data(), __rem.size());
+ _M_out = __format::__write_escape_seqs(std::move(_M_out), __str);
+ }
+ }
+ return __format::__write(std::move(_M_out), _Esc::_S_term(_M_term));
+ }
+ };
+
+ 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
@@ -3582,6 +4121,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;
@@ -3591,11 +4136,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
};
@@ -3633,10 +4184,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;
@@ -3650,9 +4205,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);
@@ -3831,36 +4398,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>)
@@ -3916,7 +4472,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;
@@ -3930,11 +4506,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;
}
@@ -4007,13 +4578,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:
@@ -4031,14 +4622,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();
}
}
@@ -4124,7 +4708,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
@@ -4137,7 +4721,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...>;
@@ -5088,22 +5672,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()
@@ -5133,28 +5703,597 @@ 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)
+ {
+ if constexpr (is_same_v<_Out, _Drop_iter<_CharT>>)
+ return __fc.out();
+ else
+ {
+ // 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, _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); }
+ };
+
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4399. enable_nonlocking_formatter_optimization for pair and tuple needs remove_cvref_t
+ template<typename _Fp, typename _Sp>
+ constexpr bool enable_nonlocking_formatter_optimization<pair<_Fp, _Sp>>
+ = enable_nonlocking_formatter_optimization<remove_cvref_t<_Fp>>
+ && enable_nonlocking_formatter_optimization<remove_cvref_t<_Sp>>;
+#endif
+
+ 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); }
+ };
+
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4399. enable_nonlocking_formatter_optimization for pair and tuple needs remove_cvref_t
+ template<typename... _Tps>
+ constexpr bool enable_nonlocking_formatter_optimization<tuple<_Tps...>>
+ = (enable_nonlocking_formatter_optimization<remove_cvref_t<_Tps>> && ...);
+#endif
+
+ // [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 (format_kind<_Rg> == range_format::sequence)
+ { _M_under.set_separator(__sep); }
+
+ constexpr void
+ set_brackets(basic_string_view<_CharT> __open,
+ basic_string_view<_CharT> __close) noexcept
+ requires (format_kind<_Rg> == range_format::sequence)
+ { _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;
+ };
+
+#if __glibcxx_print >= 202406L
+ template<ranges::input_range _Rg>
+ requires (format_kind<_Rg> != range_format::disabled)
+ constexpr bool enable_nonlocking_formatter_optimization<_Rg> = false;
+#endif
+
#endif // C++23 formatting ranges
#undef _GLIBCXX_WIDEN
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 1077e96..570e9e9 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -52,8 +52,23 @@
#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_common_reference_wrapper
+#define __glibcxx_want_transparent_operators
+#include <bits/version.h>
+
#include <tuple>
-#include <type_traits>
#include <bits/functional_hash.h>
#include <bits/invoke.h>
#include <bits/refwrap.h> // std::reference_wrapper and _Mem_fn_traits
@@ -69,26 +84,15 @@
# include <bits/stl_algobase.h> // std::search
#endif
#if __cplusplus >= 202002L
+# include <bits/binders.h>
# 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)
@@ -492,6 +496,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
# define _GLIBCXX_DEPR_BIND
#endif
+#if _GLIBCXX_EXPLICIT_THIS_PARAMETER
+ // Return a _Up that has the same cv-quals as _Tp.
+ template<typename _Tp, typename _Up> // _Up should be cv-unqualified
+ struct __cv_like
+ { using type = _Up; };
+
+ template<typename _Tp, typename _Up>
+ struct __cv_like<const _Tp, _Up>
+ { using type = const _Up; };
+
+ template<typename _Tp, typename _Up>
+ struct __cv_like<volatile _Tp, _Up>
+ { using type = volatile _Up; };
+
+ template<typename _Tp, typename _Up>
+ struct __cv_like<const volatile _Tp, _Up>
+ { using type = const volatile _Up; };
+
+ template<typename _Tp, typename _Up>
+ using __cv_like_t = typename __cv_like<_Tp, _Up>::type;
+#endif
+
/// Type of the function object returned from bind().
template<typename _Signature>
class _Bind;
@@ -561,6 +587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using _Res_type_impl
= __invoke_result_t<_Fn&, _Mu_type<_BArgs, _CallArgs>&&...>;
+#if !_GLIBCXX_EXPLICIT_THIS_PARAMETER
template<typename _CallArgs>
using _Res_type = _Res_type_impl<_Functor, _CallArgs, _Bound_args...>;
@@ -573,6 +600,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename __cv_quals<__dependent<_CallArgs>>::type,
_CallArgs,
typename __cv_quals<_Bound_args>::type...>;
+#endif
public:
template<typename... _Args>
@@ -590,6 +618,63 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Bind(const _Bind&) = default;
_Bind(_Bind&&) = default;
+#if _GLIBCXX_EXPLICIT_THIS_PARAMETER
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this
+ template<typename... _Args,
+ typename _Self,
+ typename _Self_nonref = typename remove_reference<_Self>::type,
+ __enable_if_t<!is_volatile<_Self_nonref>::value, int> = 0,
+ typename _Result
+ = _Res_type_impl<__cv_like_t<_Self_nonref, _Functor>,
+ tuple<_Args...>,
+ __cv_like_t<_Self_nonref, _Bound_args>...>>
+ _GLIBCXX20_CONSTEXPR
+ _Result
+ operator()(this _Self&& __self, _Args&&... __args)
+ {
+ using _Bind_ref = __cv_like_t<_Self_nonref, _Bind>&;
+ if constexpr (is_const<_Self_nonref>::value)
+ return _Bind_ref(__self)
+ .template __call_c<_Result>(std::forward_as_tuple
+ (std::forward<_Args>(__args)...),
+ _Bound_indexes());
+ else
+ return _Bind_ref(__self)
+ .template __call<_Result>(std::forward_as_tuple
+ (std::forward<_Args>(__args)...),
+ _Bound_indexes());
+ }
+
+# if defined(_GLIBCXX_VOLATILE_BIND)
+ template<typename... _Args,
+ typename _Self,
+ typename _Self_nonref = typename remove_reference<_Self>::type,
+ __enable_if_t<is_volatile<_Self_nonref>::value, int> = 0,
+ typename _Result
+ = _Res_type_impl<__cv_like_t<_Self_nonref, _Functor>,
+ tuple<_Args...>,
+ __cv_like_t<_Self_nonref, _Bound_args>...>>
+ _GLIBCXX_DEPR_BIND
+ _Result
+ operator()(this _Self&& __self, _Args&&... __args)
+ {
+ using _Bind_ref = __cv_like_t<_Self_nonref, _Bind>&;
+ if constexpr (is_const<_Self_nonref>::value)
+ return _Bind_ref(__self)
+ .template __call_c_v<_Result>(std::forward_as_tuple
+ (std::forward<_Args>(__args)...),
+ _Bound_indexes());
+ else
+ return _Bind_ref(__self)
+ .template __call_v<_Result>(std::forward_as_tuple
+ (std::forward<_Args>(__args)...),
+ _Bound_indexes());
+ }
+# endif
+# pragma GCC diagnostic pop
+#else
// Call unqualified
template<typename... _Args,
typename _Result = _Res_type<tuple<_Args...>>>
@@ -639,6 +724,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Bound_indexes());
}
#endif // volatile
+#endif
};
/// Type of the function object returned from bind<R>().
@@ -919,116 +1005,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::forward<_BoundArgs>(__args)...);
}
-#ifdef __cpp_lib_bind_front // C++ >= 20
-
- template<typename _Fd, typename... _BoundArgs>
- struct _Bind_front
+#if __cpp_lib_bind_front >= 202306L || __cpp_lib_bind_back >= 202306L
+ template <auto __fn>
+ struct _Bind_fn_t
{
- static_assert(is_move_constructible_v<_Fd>);
- static_assert((is_move_constructible_v<_BoundArgs> && ...));
-
- // First parameter is to ensure this constructor is never used
- // instead of the copy/move constructor.
- template<typename _Fn, typename... _Args>
- explicit constexpr
- _Bind_front(int, _Fn&& __fn, _Args&&... __args)
- noexcept(__and_<is_nothrow_constructible<_Fd, _Fn>,
- is_nothrow_constructible<_BoundArgs, _Args>...>::value)
- : _M_fd(std::forward<_Fn>(__fn)),
- _M_bound_args(std::forward<_Args>(__args)...)
- { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); }
-
-#if __cpp_explicit_this_parameter
- template<typename _Self, typename... _CallArgs>
- constexpr
- invoke_result_t<__like_t<_Self, _Fd>, __like_t<_Self, _BoundArgs>..., _CallArgs...>
- operator()(this _Self&& __self, _CallArgs&&... __call_args)
- noexcept(is_nothrow_invocable_v<__like_t<_Self, _Fd>,
- __like_t<_Self, _BoundArgs>..., _CallArgs...>)
- {
- return _S_call(__like_t<_Self, _Bind_front>(__self), _BoundIndices(),
- std::forward<_CallArgs>(__call_args)...);
- }
-#else
- template<typename... _CallArgs>
- requires true
- constexpr
- invoke_result_t<_Fd&, _BoundArgs&..., _CallArgs...>
- operator()(_CallArgs&&... __call_args) &
- noexcept(is_nothrow_invocable_v<_Fd&, _BoundArgs&..., _CallArgs...>)
- {
- return _S_call(*this, _BoundIndices(),
- std::forward<_CallArgs>(__call_args)...);
- }
-
- template<typename... _CallArgs>
- requires true
- constexpr
- invoke_result_t<const _Fd&, const _BoundArgs&..., _CallArgs...>
- operator()(_CallArgs&&... __call_args) const &
- noexcept(is_nothrow_invocable_v<const _Fd&, const _BoundArgs&...,
- _CallArgs...>)
- {
- return _S_call(*this, _BoundIndices(),
- std::forward<_CallArgs>(__call_args)...);
- }
-
- template<typename... _CallArgs>
- requires true
- constexpr
- invoke_result_t<_Fd, _BoundArgs..., _CallArgs...>
- operator()(_CallArgs&&... __call_args) &&
- noexcept(is_nothrow_invocable_v<_Fd, _BoundArgs..., _CallArgs...>)
- {
- return _S_call(std::move(*this), _BoundIndices(),
- std::forward<_CallArgs>(__call_args)...);
- }
-
- template<typename... _CallArgs>
- requires true
- constexpr
- invoke_result_t<const _Fd, const _BoundArgs..., _CallArgs...>
- operator()(_CallArgs&&... __call_args) const &&
- noexcept(is_nothrow_invocable_v<const _Fd, const _BoundArgs...,
- _CallArgs...>)
- {
- return _S_call(std::move(*this), _BoundIndices(),
- std::forward<_CallArgs>(__call_args)...);
- }
-
- template<typename... _CallArgs>
- void operator()(_CallArgs&&...) & = delete;
-
- template<typename... _CallArgs>
- void operator()(_CallArgs&&...) const & = delete;
-
- template<typename... _CallArgs>
- void operator()(_CallArgs&&...) && = delete;
-
- template<typename... _CallArgs>
- void operator()(_CallArgs&&...) const && = delete;
-#endif
-
- private:
- using _BoundIndices = index_sequence_for<_BoundArgs...>;
-
- template<typename _Tp, size_t... _Ind, typename... _CallArgs>
- static constexpr
- decltype(auto)
- _S_call(_Tp&& __g, index_sequence<_Ind...>, _CallArgs&&... __call_args)
- {
- return std::invoke(std::forward<_Tp>(__g)._M_fd,
- std::get<_Ind>(std::forward<_Tp>(__g)._M_bound_args)...,
- std::forward<_CallArgs>(__call_args)...);
- }
-
- [[no_unique_address]] _Fd _M_fd;
- [[no_unique_address]] std::tuple<_BoundArgs...> _M_bound_args;
+ using _Fn = const decltype(__fn)&;
+ template <typename... _Args>
+ requires is_invocable_v<_Fn, _Args...>
+ constexpr static decltype(auto)
+ operator()(_Args&&... __args)
+ noexcept(is_nothrow_invocable_v<_Fn, _Args...>)
+ { return std::invoke(__fn, std::forward<_Args>(__args)...); }
};
+#endif
- template<typename _Fn, typename... _Args>
- using _Bind_front_t = _Bind_front<decay_t<_Fn>, decay_t<_Args>...>;
-
+#ifdef __cpp_lib_bind_front // C++ >= 20
/** Create call wrapper by partial application of arguments to function.
*
* The result of `std::bind_front(f, args...)` is a function object that
@@ -1047,57 +1038,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return _Bind_front_t<_Fn, _Args...>(0, std::forward<_Fn>(__fn),
std::forward<_Args>(__args)...);
}
-#endif // __cpp_lib_bind_front
-#ifdef __cpp_lib_bind_back // C++ >= 23
- template<typename _Fd, typename... _BoundArgs>
- struct _Bind_back
+#if __cpp_lib_bind_front >= 202306L
+ /** Create call wrapper by partial application of arguments to function.
+ *
+ * The result of `std::bind_front<fn>(bind_args...)` is a function object
+ * that stores the bound arguments, `bind_args...`. When that function
+ * object is invoked with `call_args...` it returns the result of calling
+ * `fn(bind_args..., call_args...)`.
+ *
+ * @since C++26
+ */
+ template<auto __fn, typename... _BindArgs>
+ constexpr decltype(auto)
+ bind_front(_BindArgs&&... __bind_args)
+ noexcept(__and_v<is_nothrow_constructible<_BindArgs>...>)
{
- static_assert(is_move_constructible_v<_Fd>);
- static_assert((is_move_constructible_v<_BoundArgs> && ...));
-
- // First parameter is to ensure this constructor is never used
- // instead of the copy/move constructor.
- template<typename _Fn, typename... _Args>
- explicit constexpr
- _Bind_back(int, _Fn&& __fn, _Args&&... __args)
- noexcept(__and_<is_nothrow_constructible<_Fd, _Fn>,
- is_nothrow_constructible<_BoundArgs, _Args>...>::value)
- : _M_fd(std::forward<_Fn>(__fn)),
- _M_bound_args(std::forward<_Args>(__args)...)
- { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); }
-
- template<typename _Self, typename... _CallArgs>
- constexpr
- invoke_result_t<__like_t<_Self, _Fd>, _CallArgs..., __like_t<_Self, _BoundArgs>...>
- operator()(this _Self&& __self, _CallArgs&&... __call_args)
- noexcept(is_nothrow_invocable_v<__like_t<_Self, _Fd>,
- _CallArgs..., __like_t<_Self, _BoundArgs>...>)
- {
- return _S_call(__like_t<_Self, _Bind_back>(__self), _BoundIndices(),
- std::forward<_CallArgs>(__call_args)...);
- }
-
- private:
- using _BoundIndices = index_sequence_for<_BoundArgs...>;
-
- template<typename _Tp, size_t... _Ind, typename... _CallArgs>
- static constexpr
- decltype(auto)
- _S_call(_Tp&& __g, index_sequence<_Ind...>, _CallArgs&&... __call_args)
- {
- return std::invoke(std::forward<_Tp>(__g)._M_fd,
- std::forward<_CallArgs>(__call_args)...,
- std::get<_Ind>(std::forward<_Tp>(__g)._M_bound_args)...);
- }
-
- [[no_unique_address]] _Fd _M_fd;
- [[no_unique_address]] std::tuple<_BoundArgs...> _M_bound_args;
- };
+ using _Fn = decltype(__fn);
+ if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
+ static_assert(__fn != nullptr);
+
+ if constexpr (sizeof...(_BindArgs) == 0)
+ return _Bind_fn_t<__fn>{};
+ else
+ return _Bind_front_t<_Bind_fn_t<__fn>, _BindArgs...>(0,
+ _Bind_fn_t<__fn>{}, std::forward<_BindArgs>(__bind_args)...);
+ }
- template<typename _Fn, typename... _Args>
- using _Bind_back_t = _Bind_back<decay_t<_Fn>, decay_t<_Args>...>;
+#endif // __cpp_lib_bind_front // C++26
+#endif // __cpp_lib_bind_front
+#ifdef __cpp_lib_bind_back // C++ >= 23
/** Create call wrapper by partial application of arguments to function.
*
* The result of `std::bind_back(f, args...)` is a function object that
@@ -1116,6 +1087,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return _Bind_back_t<_Fn, _Args...>(0, std::forward<_Fn>(__fn),
std::forward<_Args>(__args)...);
}
+
+#if __cpp_lib_bind_back >= 202306L
+
+ /** Create call wrapper by partial application of arguments to function.
+ *
+ * The result of `std::bind_back<fn>(bind_args...)` is a function object
+ * that stores the arguments, `bind_args...`. When that function object
+ * is invoked with `call_args...` it returns the result of calling
+ * `fn(call_args..., bind_args...)`.
+ *
+ * @since C++26
+ */
+ template<auto __fn, typename... _BindArgs>
+ constexpr decltype(auto)
+ bind_back(_BindArgs&&... __bind_args)
+ noexcept(__and_v<is_nothrow_constructible<_BindArgs>...>)
+ {
+ using _Fn = decltype(__fn);
+ if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
+ static_assert(__fn != nullptr);
+
+ if constexpr (sizeof...(_BindArgs) == 0)
+ return _Bind_fn_t<__fn>{};
+ else
+ return _Bind_back_t<_Bind_fn_t<__fn>, _BindArgs...>(0,
+ _Bind_fn_t<__fn>{}, std::forward<_BindArgs>(__bind_args)...);
+ }
+#endif // __cpp_lib_bind_back // C++26, nttp
#endif // __cpp_lib_bind_back
#if __cplusplus >= 201402L
@@ -1140,6 +1139,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Not_fn(_Not_fn&& __fn) = default;
~_Not_fn() = default;
+#if _GLIBCXX_EXPLICIT_THIS_PARAMETER
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this
+ template<typename _Self, typename... _Args>
+ _GLIBCXX20_CONSTEXPR
+ decltype(_S_not<__inv_res_t<__like_t<_Self, _Fn>, _Args...>>())
+ operator()(this _Self&& __self, _Args&&... __args)
+ noexcept(__is_nothrow_invocable<__like_t<_Self, _Fn>, _Args...>::value
+ && noexcept(_S_not<__inv_res_t<__like_t<_Self, _Fn>, _Args...>>()))
+ {
+ return !std::__invoke(__like_t<_Self, _Not_fn>(__self)._M_fn,
+ std::forward<_Args>(__args)...);
+ }
+# pragma GCC diagnostic pop
+#else
// Macro to define operator() with given cv-qualifiers ref-qualifiers,
// forwarding _M_fn and the function arguments with the same qualifiers,
// and deducing the return type and exception-specification.
@@ -1165,6 +1179,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NOT_FN_CALL_OP( && )
_GLIBCXX_NOT_FN_CALL_OP( const && )
#undef _GLIBCXX_NOT_FN_CALL_OP
+#endif
private:
_Fn _M_fn;
@@ -1216,7 +1231,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
return _Not_fn<std::decay_t<_Fn>>{std::forward<_Fn>(__fn), 0};
}
-#endif
+
+#if __cpp_lib_not_fn >= 202306L
+ /** Wrap a function type to create a function object that negates its result.
+ *
+ * The function template `std::not_fn` creates a "forwarding call wrapper",
+ * which is a function object that when called forwards its arguments to
+ * its invocable template argument.
+ *
+ * The result of invoking the wrapper is the negation (using `!`) of
+ * the wrapped function object.
+ *
+ * @ingroup functors
+ * @since C++26
+ */
+ template<auto __fn>
+ constexpr decltype(auto)
+ not_fn() noexcept
+ {
+ using _Fn = decltype(__fn);
+ if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
+ static_assert(__fn != nullptr);
+ return []<typename... _Args>(_Args&&... __args) static
+ noexcept(noexcept(
+ !std::invoke(__fn, std::forward<_Args>(__args)...) ))
+ -> decltype(auto)
+ requires requires {
+ !std::invoke(__fn, std::forward<_Args>(__args)...); }
+ { return !std::invoke(__fn, std::forward<_Args>(__args)...); };
+ };
+#endif // __cpp_lib_not_fn >= 202306L
+#endif // __cpp_lib_not_fn
#if __cplusplus >= 201703L
// Searchers
@@ -1410,6 +1455,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator()(_RandomAccessIterator2 __first,
_RandomAccessIterator2 __last) const
{
+#ifdef __glibcxx_concepts // >= C++20
+ // Value types must be the same for hash function and predicate
+ // to give consistent results for lookup in the map.
+ static_assert(is_same_v<iter_value_t<_RAIter>,
+ iter_value_t<_RandomAccessIterator2>>);
+#endif
const auto& __pred = this->_M_pred();
auto __patlen = _M_pat_end - _M_pat;
if (__patlen == 0)
@@ -1471,6 +1522,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator()(_RandomAccessIterator2 __first,
_RandomAccessIterator2 __last) const
{
+#ifdef __glibcxx_concepts // >= C++20
+ // Value types must be the same for hash function and predicate
+ // to give consistent results for lookup in the map.
+ static_assert(is_same_v<iter_value_t<_RAIter>,
+ iter_value_t<_RandomAccessIterator2>>);
+#endif
auto __patlen = _M_pat_end - _M_pat;
if (__patlen == 0)
return std::make_pair(__first, __first);
@@ -1487,7 +1544,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
if (__j < 0)
{
- const auto __match = __first + __i + 1;
+ const auto __match = __first + __diff_type(__i + 1);
return std::make_pair(__match, __match + __patlen);
}
__i += std::max(_M_bad_char_shift(__first[__i]),
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/inplace_vector b/libstdc++-v3/include/std/inplace_vector
new file mode 100644
index 0000000..0f7716c
--- /dev/null
+++ b/libstdc++-v3/include/std/inplace_vector
@@ -0,0 +1,1369 @@
+// Sequence container with fixed capacity -*- 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 include/inplace_vector
+ * This is a Standard C++ Library header.
+ * @ingroup sequences
+ */
+
+#ifndef _GLIBCXX_INPLACE_VECTOR
+#define _GLIBCXX_INPLACE_VECTOR 1
+
+#pragma GCC system_header
+
+#define __glibcxx_want_inplace_vector
+#include <bits/version.h>
+
+#ifdef __glibcxx_inplace_vector // C++ >= 26
+#include <compare>
+#include <initializer_list>
+#include <bits/range_access.h>
+#include <bits/ranges_base.h> // borrowed_iterator_t, __detail::__container_compatible_range
+#include <bits/ranges_util.h> // subrange
+#include <bits/ranges_uninitialized.h>
+#include <bits/stl_construct.h>
+#include <bits/stl_uninitialized.h>
+#include <bits/stl_algo.h> // rotate
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+
+ // [indirect], class template indirect
+ template<typename _Tp, size_t _Nm>
+ class inplace_vector
+ {
+ public:
+
+ // types:
+ using value_type = _Tp;
+ using pointer = _Tp*;
+ using const_pointer = const _Tp*;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+ using iterator
+ = __gnu_cxx::__normal_iterator<_Tp*, inplace_vector>;
+ using const_iterator
+ = __gnu_cxx::__normal_iterator<const _Tp*, inplace_vector>;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ // [containers.sequences.inplace.vector.cons], construct/copy/destroy
+ constexpr
+ inplace_vector() noexcept
+ { _M_init(); }
+
+ constexpr explicit
+ inplace_vector(size_type __n)
+ {
+ _M_init();
+ _S_reserve(__n);
+ std::uninitialized_value_construct_n(data(), __n);
+ _M_size = __n;
+ }
+
+ constexpr
+ inplace_vector(size_type __n, const _Tp& __value)
+ {
+ _M_init();
+ _S_reserve(__n);
+ std::uninitialized_fill_n(data(), __n, __value);
+ _M_size = __n;
+ }
+
+ template<__any_input_iterator _InputIterator>
+ constexpr
+ inplace_vector(_InputIterator __first, _InputIterator __last)
+ : inplace_vector()
+ {
+ if (const auto __n = _S_distance(__first, __last))
+ {
+ _S_reserve(__n);
+ std::uninitialized_copy(__first, __last, data());
+ _M_size = __n;
+ }
+ else
+ {
+ while (__first != __last)
+ emplace_back(*__first++);
+ }
+ }
+
+ template <__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr
+ inplace_vector(from_range_t, _Rg&& __rg)
+ : inplace_vector()
+ { append_range(__rg); }
+
+ constexpr
+ inplace_vector(initializer_list<_Tp> __il)
+ {
+ _M_init();
+ _S_reserve(__il.size());
+ std::uninitialized_copy(__il.begin(), __il.end(), data());
+ _M_size = __il.size();
+ }
+
+ inplace_vector(const inplace_vector&)
+ requires is_trivially_copy_constructible_v<_Tp>
+ = default;
+
+ constexpr
+ inplace_vector(const inplace_vector& __other)
+ noexcept(is_nothrow_copy_constructible_v<_Tp>)
+ {
+ _M_init();
+ std::uninitialized_copy(__other.begin(), __other.end(), data());
+ _M_size = __other.size();
+ }
+
+ inplace_vector(inplace_vector&&)
+ requires is_trivially_move_constructible_v<_Tp>
+ = default;
+
+ constexpr
+ inplace_vector(inplace_vector&& __other)
+ noexcept(is_nothrow_move_constructible_v<_Tp>)
+ {
+ _M_init();
+ std::uninitialized_move(__other.begin(), __other.end(), data());
+ _M_size = __other.size();
+ }
+
+ ~inplace_vector()
+ requires is_trivially_destructible_v<_Tp>
+ = default;
+
+ constexpr
+ ~inplace_vector()
+ { clear(); }
+
+ inplace_vector&
+ operator=(const inplace_vector&)
+ requires is_trivially_copy_assignable_v<_Tp>
+ && is_trivially_copy_constructible_v<_Tp>
+ && is_trivially_destructible_v<_Tp>
+ = default;
+
+ constexpr inplace_vector&
+ operator=(const inplace_vector& __other)
+ noexcept(is_nothrow_copy_assignable_v<_Tp>
+ && is_nothrow_copy_constructible_v<_Tp>)
+ {
+ if (std::addressof(__other) != this) [[likely]]
+ assign(__other.begin(), __other.end());
+ return *this;
+ }
+
+ inplace_vector&
+ operator=(inplace_vector&&)
+ requires is_trivially_move_assignable_v<_Tp>
+ && is_trivially_move_constructible_v<_Tp>
+ && is_trivially_destructible_v<_Tp>
+ = default;
+
+ constexpr inplace_vector&
+ operator=(inplace_vector&& __other)
+ noexcept(is_nothrow_move_assignable_v<_Tp>
+ && is_nothrow_move_constructible_v<_Tp>)
+ {
+ if (std::addressof(__other) != this) [[likely]]
+ assign(std::make_move_iterator(__other.begin()),
+ std::make_move_iterator(__other.end()));
+ return *this;
+ }
+
+ constexpr inplace_vector&
+ operator=(initializer_list<_Tp> __il)
+ {
+ assign(__il.begin(), __il.end());
+ return *this;
+ }
+
+ template<__any_input_iterator _InputIterator>
+ constexpr void
+ assign(_InputIterator __first, _InputIterator __last)
+ {
+ if (const auto __n = _S_distance(__first, __last))
+ {
+ _S_reserve(__n);
+ if (_M_size <= __n)
+ {
+ for (size_t __i = 0; __i < _M_size; ++__i, (void)++__first)
+ _M_elems[__i] = *__first;
+ std::uninitialized_copy(__first, __last, end());
+ }
+ else
+ std::destroy(std::copy(__first, __last, begin()), end());
+ _M_size = __n;
+ }
+ else
+ {
+ size_t __i = 0;
+ for (;__first != __last && __i < _M_size; ++__first)
+ _M_elems[__i++] = *__first;
+ if (__first == __last)
+ {
+ std::_Destroy_n(data() + __i, _M_size - __i);
+ _M_size = __i;
+ }
+ else
+ {
+ while (__first != __last)
+ emplace_back(*__first++);
+ }
+ }
+ }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr void
+ assign_range(_Rg&& __rg)
+ {
+ if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
+ {
+ const auto __sz = ranges::distance(__rg);
+ if (__sz > _Nm)
+ __throw_bad_alloc();
+ if (__sz <= size())
+ {
+ ranges::copy_n(ranges::begin(__rg), __sz, data());
+ std::destroy(data() + __sz, data() + _M_size);
+ }
+ else
+ {
+ auto [__in, __out] = ranges::copy_n(
+ ranges::begin(__rg), _M_size,
+ data());
+ ranges::uninitialized_copy(
+ std::move(__in), ranges::end(__rg),
+ __out, unreachable_sentinel);
+ }
+ _M_size = __sz;
+ }
+ else
+ {
+ auto __in = ranges::begin(__rg);
+ auto __end = ranges::end(__rg);
+ size_type __n = 0;
+ for (; __n < _M_size && __in != __end; ++__in)
+ _M_elems[__n++] = *__in;
+
+ if (__in == __end)
+ {
+ std::destroy(data() + __n, data() + _M_size);
+ _M_size = __n;
+ return;
+ }
+ else if (__n < _Nm)
+ {
+ auto __res = ranges::uninitialized_copy(
+ std::move(__in), __end,
+ data() + __n, data() + _Nm);
+ _M_size = __res.out - data();
+ if (__res.in == ranges::end(__rg))
+ return;
+ }
+ __throw_bad_alloc();
+ }
+ }
+
+ constexpr void
+ assign(size_type __n, const _Tp& __u)
+ {
+ _S_reserve(__n);
+ if (_M_size <= __n)
+ std::uninitialized_fill_n(std::fill_n(data(), _M_size, __u),
+ __n - _M_size, __u);
+ else
+ std::destroy_n(std::fill_n(data(), __n, __u), _M_size - __n);
+ _M_size = __n;
+ }
+
+ constexpr void
+ assign(initializer_list<_Tp> __il)
+ { assign(__il.begin(), __il.end()); }
+
+ // iterators
+ [[nodiscard]]
+ constexpr iterator
+ begin() noexcept { return iterator(data()); }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ begin() const noexcept { return const_iterator(data()); }
+
+ [[nodiscard]]
+ constexpr iterator
+ end() noexcept
+ { return iterator(data() + _M_size); }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ end() const noexcept
+ { return const_iterator(data() + _M_size); }
+
+ [[nodiscard]]
+ constexpr reverse_iterator
+ rbegin() noexcept
+ { return reverse_iterator(end()); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ rbegin() const noexcept
+ { return const_reverse_iterator(end()); }
+
+ [[nodiscard]]
+ constexpr reverse_iterator
+ rend() noexcept { return reverse_iterator(begin()); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ rend() const noexcept { return const_reverse_iterator(begin()); }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ cbegin() const noexcept { return begin(); }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ cend() const noexcept { return end(); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ crbegin() const noexcept { return rbegin(); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ crend() const noexcept { return rend(); }
+
+ // [containers.sequences.inplace.vector.members] size/capacity
+ [[nodiscard]]
+ constexpr bool
+ empty() const noexcept { return _M_size == 0; }
+
+ [[nodiscard]]
+ constexpr size_type
+ size() const noexcept
+ {
+ if (_M_size > _Nm)
+ __builtin_unreachable();
+ return _M_size;
+ }
+
+ [[nodiscard]]
+ static constexpr size_type
+ max_size() noexcept { return _Nm; }
+
+ [[nodiscard]]
+ static constexpr size_type
+ capacity() noexcept { return _Nm; }
+
+ constexpr void
+ resize(size_type __n)
+ {
+ _S_reserve(__n);
+ if (__n > _M_size)
+ std::uninitialized_value_construct_n(data() + _M_size, __n - _M_size);
+ else if (__n < _M_size)
+ std::destroy_n(data() + __n, _M_size - __n);
+ _M_size = __n;
+ }
+
+ constexpr void
+ resize(size_type __n, const _Tp& __c)
+ {
+ _S_reserve(__n);
+ if (__n > _M_size)
+ std::uninitialized_fill_n(data() + _M_size, __n - _M_size, __c);
+ else if (__n < _M_size)
+ std::destroy_n(data() + __n, _M_size - __n);
+ _M_size = __n;
+ }
+
+ static constexpr void
+ reserve(size_type __n)
+ { _S_reserve(__n); }
+
+ static constexpr void
+ shrink_to_fit() { }
+
+ // element access
+ [[nodiscard]]
+ constexpr reference
+ operator[](size_type __n)
+ {
+ __glibcxx_requires_subscript(__n);
+ return _M_elems[__n];
+ }
+
+ [[nodiscard]]
+ constexpr const_reference
+ operator[](size_type __n) const
+ {
+ __glibcxx_requires_subscript(__n);
+ return _M_elems[__n];
+ }
+
+ [[nodiscard]]
+ constexpr const_reference
+ at(size_type __n) const
+ {
+ if (__n >= _M_size)
+ std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
+ "(which is %zu) "
+ ">= size() (which is %zu)"),
+ __n, _M_size);
+ return _M_elems[__n];
+ }
+
+ [[nodiscard]]
+ constexpr reference
+ at(size_type __n)
+ {
+ if (__n >= _M_size)
+ std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
+ "(which is %zu) "
+ ">= size() (which is %zu)"),
+ __n, _M_size);
+ return _M_elems[__n];
+ }
+
+ [[nodiscard]]
+ constexpr reference
+ front()
+ {
+ __glibcxx_requires_nonempty();
+ return _M_elems[0];
+ }
+
+ [[nodiscard]]
+ constexpr const_reference
+ front() const
+ {
+ __glibcxx_requires_nonempty();
+ return _M_elems[0];
+ }
+
+ [[nodiscard]]
+ constexpr reference
+ back()
+ {
+ __glibcxx_requires_nonempty();
+ return _M_elems[_M_size - 1];
+ }
+
+ [[nodiscard]]
+ constexpr const_reference
+ back() const
+ {
+ __glibcxx_requires_nonempty();
+ return _M_elems[_M_size - 1];
+ }
+
+ // [containers.sequences.inplace.vector.data], data access
+
+ [[nodiscard]]
+ constexpr _Tp*
+ data() noexcept
+ { return static_cast<pointer>(_M_elems); }
+
+ [[nodiscard]]
+ constexpr const _Tp*
+ data() const noexcept
+ { return static_cast<const_pointer>(_M_elems); }
+
+ // [containers.sequences.inplace.vector.modifiers], modifiers
+ template<typename... _Args>
+ constexpr _Tp&
+ emplace_back(_Args&&... __args)
+ {
+ if (_M_size >= _Nm)
+ __throw_bad_alloc();
+ return unchecked_emplace_back(std::forward<_Args>(__args)...);
+ }
+
+ constexpr _Tp&
+ push_back(const _Tp& __x)
+ { return emplace_back(__x); }
+
+ constexpr _Tp&
+ push_back(_Tp&& __x)
+ { return emplace_back(std::move(__x)); }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr void
+ append_range(_Rg&& __rg)
+ {
+ if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
+ {
+ const auto __sz = ranges::distance(__rg);
+ if (__sz > (_Nm - size()))
+ __throw_bad_alloc();
+ // Bounded on output range due PR121143
+ ranges::uninitialized_copy(
+ ranges::begin(__rg), unreachable_sentinel,
+ data() + _M_size, data() + _M_size + __sz);
+ _M_size += size_type(__sz);
+ }
+ else
+ {
+ ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm);
+ auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail);
+ _M_size = __out - data();
+ if (__in != ranges::end(__rg))
+ __throw_bad_alloc();
+ }
+ }
+
+ constexpr void
+ pop_back()
+ {
+ __glibcxx_requires_nonempty();
+ --_M_size;
+ _M_elems[_M_size].~_Tp();
+ }
+
+ template<typename... _Args>
+ constexpr _Tp*
+ try_emplace_back(_Args&&... __args)
+ {
+ if (_M_size >= _Nm) [[unlikely]]
+ return nullptr;
+ auto& __r = unchecked_emplace_back(std::forward<_Args>(__args)...);
+ return __builtin_addressof(__r);
+ }
+
+ constexpr _Tp*
+ try_push_back(const _Tp& __x)
+ {
+ if (_M_size >= _Nm) [[unlikely]]
+ return nullptr;
+ return __builtin_addressof(unchecked_emplace_back(__x));
+ }
+
+ constexpr _Tp*
+ try_push_back(_Tp&& __x)
+ {
+ if (_M_size >= _Nm) [[unlikely]]
+ return nullptr;
+ return __builtin_addressof(unchecked_emplace_back(std::move(__x)));
+ }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr ranges::borrowed_iterator_t<_Rg>
+ try_append_range(_Rg&& __rg)
+ {
+ if constexpr (ranges::sized_range<_Rg>)
+ {
+ auto __n = ranges::distance(__rg);
+ if (__n == 0) [[unlikely]]
+ return ranges::begin(__rg);
+
+ const auto __end = data() + _M_size;
+ const size_t __avail = _Nm - size();
+ if (__n <= __avail)
+ _M_size += size_type(__n);
+ else
+ {
+ __n = __avail;
+ _M_size = _Nm;
+ }
+ return ranges::uninitialized_copy_n(
+ ranges::begin(__rg), __n,
+ __end, unreachable_sentinel).in;
+ }
+ else
+ {
+ ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm);
+ auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail);
+ _M_size = __out - data();
+ return std::move(__in);
+ }
+ }
+
+ template<typename... _Args>
+ constexpr _Tp&
+ unchecked_emplace_back(_Args&&... __args)
+ {
+ __glibcxx_assert(_M_size < _Nm);
+ auto __p = std::construct_at(data() + _M_size,
+ std::forward<_Args>(__args)...);
+ ++_M_size;
+ return *__p;
+ }
+
+ constexpr _Tp&
+ unchecked_push_back(const _Tp& __x)
+ { return unchecked_emplace_back(__x); }
+
+ constexpr _Tp&
+ unchecked_push_back(_Tp&& __x)
+ { return unchecked_emplace_back(std::move(__x)); }
+
+ template<typename... _Args>
+ constexpr iterator
+ emplace(const_iterator __position, _Args&&... __args)
+ {
+ size_t __b = __position - cbegin(); // elements before position
+ __glibcxx_assert(__b <= _M_size);
+ if (_M_size >= _Nm)
+ __throw_bad_alloc();
+ iterator __pos = begin() + __b;
+ std::construct_at(data() + _M_size, std::forward<_Args>(__args)...);
+ if (_M_size++)
+ std::rotate(__pos, end() - 1, end());
+ return __pos;
+ }
+
+ constexpr iterator
+ insert(const_iterator __position, const _Tp& __x)
+ { return emplace(__position, __x); }
+
+ constexpr iterator
+ insert(const_iterator __position, _Tp&& __x)
+ { return emplace(__position, std::move(__x)); }
+
+ constexpr iterator
+ insert(const_iterator __position, size_type __n, const _Tp& __x)
+ {
+ size_t __b = __position - cbegin(); // elements before position
+ __glibcxx_assert(__b <= _M_size);
+ if ((_Nm - _M_size) < __n)
+ __throw_bad_alloc();
+ iterator __pos = begin() + __b;
+ std::uninitialized_fill_n(data() + _M_size, __n, __x);
+ if (std::__exchange(_M_size, _M_size + __n))
+ std::rotate(__pos, end() - __n, end());
+ return __pos;
+ }
+
+ template<__any_input_iterator _InputIterator>
+ constexpr iterator
+ insert(const_iterator __position, _InputIterator __first,
+ _InputIterator __last)
+ {
+ size_t __b = __position - cbegin(); // elements before position
+ __glibcxx_assert(__b <= _M_size);
+ iterator __pos = begin() + __b;
+ const size_t __s = _M_size;
+ if (const auto __n = _S_distance(__first, __last))
+ {
+ if ((_Nm - _M_size) < __n)
+ __throw_bad_alloc();
+ std::uninitialized_copy(__first, __last, data() + _M_size);
+ _M_size += __n;
+ }
+ else
+ {
+ while (__first != __last)
+ emplace_back(*__first++);
+ }
+ if (__s)
+ std::rotate(__pos, begin() + __s, end());
+ return __pos;
+ }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr iterator
+ insert_range(const_iterator __position, _Rg&& __rg)
+ {
+ iterator __pos = begin() + (__position - cbegin());
+ const auto __end = end();
+ if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
+ {
+ const auto __len = ranges::distance(__rg);
+ if (__len > (_Nm - size()))
+ __throw_bad_alloc();
+ if (!__len) [[unlikely]]
+ return __pos;
+
+ const size_type __n = size_type(__len);
+ const size_type __num_after = __end - __pos;
+ if (__num_after >= __n)
+ {
+ ranges::uninitialized_move(__end - __n, __end,
+ __end, unreachable_sentinel);
+ _M_size += __n;
+ ranges::move_backward(__pos, __end - __n, __end);
+ ranges::copy(__rg, __pos);
+ }
+ else if constexpr (ranges::forward_range<_Rg>)
+ {
+ auto __mid = ranges::next(ranges::begin(__rg), __num_after);
+ ranges::uninitialized_copy(__mid, ranges::end(__rg),
+ __end, unreachable_sentinel);
+ _M_size += __n - __num_after;
+ ranges::uninitialized_move(__pos, __end,
+ __pos + __n, unreachable_sentinel);
+ _M_size += __num_after;
+ ranges::copy(ranges::begin(__rg), __mid, __pos);
+ }
+ else
+ {
+ ranges::uninitialized_copy(
+ ranges::begin(__rg), ranges::end(__rg),
+ __end, unreachable_sentinel);
+ _M_size += __n;
+ std::rotate(__pos, __end, end());
+ }
+ }
+ else
+ {
+ append_range(__rg);
+ std::rotate(__pos, __end, end());
+ }
+ return __pos;
+ }
+
+ constexpr iterator
+ insert(const_iterator __position, initializer_list<_Tp> __il)
+ { return insert(__position, __il.begin(), __il.end()); }
+
+ constexpr iterator
+ erase(const_iterator __position)
+ {
+ size_t __n = __position - cbegin();
+ __glibcxx_assert(__n < _M_size);
+ iterator __pos = begin() + __n;
+ std::move(__pos + 1, end(), __pos);
+ pop_back();
+ return __pos;
+ }
+
+ constexpr iterator
+ erase(const_iterator __first, const_iterator __last)
+ {
+ size_t __n = __first - cbegin();
+ size_t __x = __last - __first;
+ __glibcxx_assert(__n <= _M_size);
+ __glibcxx_assert(__x <= _M_size);
+ iterator __pos = begin() + __n;
+ iterator __end = std::move(__pos + __x, end(), __pos);
+ std::destroy_n(__end, __x);
+ _M_size -= __x;
+ return __pos;
+ }
+
+ constexpr void
+ swap(inplace_vector& __x)
+ noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)
+ {
+ inplace_vector* __vs[2]{ this, std::addressof(__x) };
+ const auto __smaller = __vs[__x.size() < size()];
+ const auto __bigger = __vs[__x.size() >= size()];
+ size_type __n = __smaller->size();
+ size_type __n2 = __bigger->size();
+
+ if constexpr (is_nothrow_move_constructible_v<_Tp>)
+ {
+ for (size_type __i = __n; __i < __n2; ++__i)
+ {
+ std::construct_at(__smaller->data() + __i,
+ std::move(*(__bigger->data() + __i)));
+ std::destroy_at(__bigger->data() + __i);
+ }
+ }
+ else
+ {
+ std::uninitialized_copy(__bigger->data() + __n,
+ __bigger->data() + __n2,
+ __smaller->data() + __n);
+ std::destroy(__bigger->data() + __n, __bigger->data() + __n2);
+ }
+ __smaller->_M_size = __n2;
+ __bigger->_M_size = __n;
+
+ using std::swap;
+ for (size_type __i = 0; __i < __n; __i++)
+ swap(_M_elems[__i], __x._M_elems[__i]);
+ }
+
+ constexpr void
+ clear() noexcept
+ {
+ std::destroy_n(data(), size_t(_M_size));
+ _M_size = 0;
+ }
+
+ constexpr friend bool
+ operator==(const inplace_vector& __x, const inplace_vector& __y)
+ { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); }
+
+ constexpr friend auto
+ operator<=>(const inplace_vector& __x, const inplace_vector& __y)
+ requires requires (const _Tp __t) {
+ { __t < __t } -> __detail::__boolean_testable;
+ }
+ {
+ return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
+ __y.begin(), __y.end(),
+ __detail::__synth3way);
+ }
+
+ // [inplace.vector.special], specialized algorithms
+ constexpr friend void
+ swap(inplace_vector& __x, inplace_vector& __y)
+ noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)
+ { __x.swap(__y); }
+
+ private:
+ union {
+ _Tp _M_elems[_Nm];
+ };
+
+ // Check whether integer type _UInt is wide enough to store _Nm,
+ // so that we use a smaller type for _M_size when that saves space.
+ template<typename _UInt, bool = (alignof(_Tp) <= sizeof(_UInt))>
+ static constexpr bool __fits
+ = _Nm <= __gnu_cxx::__int_traits<_UInt>::__max;
+
+ // Don't bother using a smaller type if alignment of the array elements
+ // means that it doesn't actually save space.
+ template<typename _UInt>
+ static constexpr bool __fits<_UInt, false> = false;
+
+ static consteval auto __select_size_type()
+ {
+ if constexpr (__fits<unsigned char>)
+ return (unsigned char)0;
+#if __SHRT_WIDTH__ < __SIZE_WIDTH__
+ else if constexpr (__fits<unsigned short>)
+ return (unsigned short)0;
+#endif
+#if __INT_WIDTH__ < __SIZE_WIDTH__ && __INT_WIDTH__ > __SHRT_WIDTH__
+ else if constexpr (__fits<unsigned int>)
+ return 0u;
+#endif
+#if __LONG_WIDTH__ < __SIZE_WIDTH__ && __LONG_WIDTH__ > __INT_WIDTH__
+ else if constexpr (__fits<unsigned long>)
+ return 0ul;
+#endif
+ else // Just use size_t.
+ return 0uz;
+ }
+ decltype(__select_size_type()) _M_size = 0;
+
+ constexpr void
+ _M_init()
+ {
+ if !consteval
+ {
+#if __glibcxx_start_lifetime_as
+ std::start_lifetime_as_array<_Tp>(data(), _Nm);
+#endif
+ }
+ else
+ {
+ // TODO: use new(_M_elems) _Tp[_Nm]() once PR121068 is fixed
+ if constexpr (is_trivial_v<_Tp>)
+ for (size_t __i = 0; __i < _Nm; ++__i)
+ _M_elems[__i] = _Tp();
+ else
+ __builtin_unreachable(); // only trivial types are supported at compile time
+ }
+ }
+
+ static constexpr void
+ _S_reserve(size_t __n)
+ {
+ if (__n > _Nm)
+ __throw_bad_alloc();
+ }
+
+ template<typename _InputIterator>
+ constexpr static auto
+ _S_distance(_InputIterator __first, _InputIterator __last)
+ {
+ if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>
+ || forward_iterator<_InputIterator>)
+ return (size_type)ranges::distance(__first, __last);
+ else if constexpr (derived_from<__iter_category_t<_InputIterator>,
+ forward_iterator_tag>)
+ return (size_type)std::distance(__first, __last);
+ else
+ return false_type{};
+ }
+ };
+
+ // specialization for zero capacity, that is required to be trivally copyable
+ // and empty regardless of _Tp.
+ template<typename _Tp>
+ class inplace_vector<_Tp, 0>
+ {
+ public:
+ // types:
+ using value_type = _Tp;
+ using pointer = _Tp*;
+ using const_pointer = const _Tp*;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+ using iterator
+ = __gnu_cxx::__normal_iterator<_Tp*, inplace_vector>;
+ using const_iterator
+ = __gnu_cxx::__normal_iterator<const _Tp*, inplace_vector>;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ // [containers.sequences.inplace.vector.cons], construct/copy/destroy
+ inplace_vector() = default;
+
+ constexpr explicit
+ inplace_vector(size_type __n)
+ {
+ if (__n != 0)
+ __throw_bad_alloc();
+ }
+
+ constexpr
+ inplace_vector(size_type __n, const _Tp& __value)
+ {
+ if (__n != 0)
+ __throw_bad_alloc();
+ }
+
+ template<__any_input_iterator _InputIterator>
+ constexpr
+ inplace_vector(_InputIterator __first, _InputIterator __last)
+ {
+ if (__first != __last)
+ __throw_bad_alloc();
+ }
+
+ template <__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr
+ inplace_vector(from_range_t, _Rg&& __rg)
+ {
+ if (ranges::begin(__rg) != ranges::end(__rg))
+ __throw_bad_alloc();
+ }
+
+ constexpr
+ inplace_vector(initializer_list<_Tp> __il)
+ {
+ if (__il.size() != 0)
+ __throw_bad_alloc();
+ }
+
+ inplace_vector(const inplace_vector&) = default;
+ inplace_vector(inplace_vector&&) = default;
+
+ constexpr
+ ~inplace_vector() = default;
+
+ inplace_vector&
+ operator=(const inplace_vector&) = default;
+
+ inplace_vector&
+ operator=(inplace_vector&&) = default;
+
+ constexpr inplace_vector&
+ operator=(initializer_list<_Tp> __il)
+ {
+ if (__il.size() != 0)
+ __throw_bad_alloc();
+ return *this;
+ }
+
+ template<__any_input_iterator _InputIterator>
+ constexpr void
+ assign(_InputIterator __first, _InputIterator __last)
+ {
+ if (__first != __last)
+ __throw_bad_alloc();
+ }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr void
+ assign_range(_Rg&& __rg)
+ {
+ if (ranges::begin(__rg) != ranges::end(__rg))
+ __throw_bad_alloc();
+ }
+
+ constexpr void
+ assign(size_type __n, const _Tp& __u)
+ {
+ if (__n != 0)
+ __throw_bad_alloc();
+ }
+
+ constexpr void
+ assign(initializer_list<_Tp> __il)
+ {
+ if (__il.size() != 0)
+ __throw_bad_alloc();
+ }
+
+ // iterators
+ [[nodiscard]]
+ constexpr iterator
+ begin() noexcept { return iterator(nullptr); }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ begin() const noexcept { return const_iterator(nullptr); }
+
+ [[nodiscard]]
+ constexpr iterator
+ end() noexcept { return iterator(nullptr); }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ end() const noexcept { return const_iterator(nullptr); }
+
+ [[nodiscard]]
+ constexpr reverse_iterator
+ rbegin() noexcept
+ { return reverse_iterator(end()); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ rbegin() const noexcept
+ { return const_reverse_iterator(end()); }
+
+ [[nodiscard]]
+ constexpr reverse_iterator
+ rend() noexcept { return reverse_iterator(begin()); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ rend() const noexcept { return const_reverse_iterator(begin()); }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ cbegin() const noexcept { return begin(); }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ cend() const noexcept { return end(); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ crbegin() const noexcept { return rbegin(); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ crend() const noexcept { return rend(); }
+
+ // [containers.sequences.inplace.vector.members] size/capacity
+ [[nodiscard]]
+ constexpr bool
+ empty() const noexcept { return true; }
+
+ [[nodiscard]]
+ constexpr size_type
+ size() const noexcept { return 0; }
+
+ [[nodiscard]]
+ static constexpr size_type
+ max_size() noexcept { return 0; }
+
+ [[nodiscard]]
+ static constexpr size_type
+ capacity() noexcept { return 0; }
+
+ constexpr void
+ resize(size_type __n)
+ {
+ if (__n != 0)
+ __throw_bad_alloc();
+ }
+
+ constexpr void
+ resize(size_type __n, const _Tp&)
+ {
+ if (__n != 0)
+ __throw_bad_alloc();
+ }
+
+ static constexpr void
+ reserve(size_type __n)
+ {
+ if (__n != 0)
+ __throw_bad_alloc();
+ }
+
+ static constexpr void
+ shrink_to_fit() { }
+
+ // element access
+ [[nodiscard,noreturn]]
+ constexpr reference
+ operator[](size_type)
+ { __builtin_trap(); }
+
+ [[nodiscard,noreturn]]
+ constexpr const_reference
+ operator[](size_type) const
+ { __builtin_trap(); }
+
+ [[nodiscard,noreturn]]
+ constexpr const_reference
+ at(size_type __n) const
+ {
+ std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
+ "(which is %zu) "
+ ">= size() (which is 0)"),
+ __n);
+ }
+
+ [[nodiscard,noreturn]]
+ constexpr reference
+ at(size_type __n)
+ {
+ std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
+ "(which is %zu) "
+ ">= size() (which is 0)"),
+ __n);
+ }
+
+ [[nodiscard,noreturn]]
+ constexpr reference
+ front()
+ { __builtin_trap(); }
+
+ [[nodiscard,noreturn]]
+ constexpr const_reference
+ front() const
+ { __builtin_trap(); }
+
+ [[nodiscard,noreturn]]
+ constexpr reference
+ back()
+ { __builtin_trap(); }
+
+ [[nodiscard,noreturn]]
+ constexpr const_reference
+ back() const
+ { __builtin_trap(); }
+
+ // [containers.sequences.inplace.vector.data], data access
+
+ [[nodiscard]]
+ constexpr _Tp*
+ data() noexcept
+ { return nullptr; }
+
+ [[nodiscard]]
+ constexpr const _Tp*
+ data() const noexcept
+ { return nullptr; }
+
+ // [containers.sequences.inplace.vector.modifiers], modifiers
+ template<typename... _Args>
+ [[noreturn]]
+ constexpr _Tp&
+ emplace_back(_Args&&...)
+ { __throw_bad_alloc(); }
+
+ [[noreturn]]
+ constexpr _Tp&
+ push_back(const _Tp&)
+ { __throw_bad_alloc(); }
+
+ [[noreturn]]
+ constexpr _Tp&
+ push_back(_Tp&&)
+ { __throw_bad_alloc(); }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr void
+ append_range(_Rg&& __rg)
+ {
+ if (ranges::begin(__rg) != ranges::end(__rg))
+ __throw_bad_alloc();
+ }
+
+ [[noreturn]]
+ constexpr void
+ pop_back()
+ { __builtin_trap(); }
+
+ template<typename... _Args>
+ constexpr _Tp*
+ try_emplace_back(_Args&&...)
+ { return nullptr; }
+
+ constexpr _Tp*
+ try_push_back(const _Tp&)
+ { return nullptr; }
+
+ constexpr _Tp*
+ try_push_back(_Tp&&)
+ { return nullptr; }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr ranges::borrowed_iterator_t<_Rg>
+ try_append_range(_Rg&& __rg)
+ { return ranges::begin(__rg); }
+
+ template<typename... _Args>
+ [[noreturn]]
+ constexpr _Tp&
+ unchecked_emplace_back(_Args&&...)
+ { __builtin_trap(); }
+
+ [[noreturn]]
+ constexpr _Tp&
+ unchecked_push_back(const _Tp&)
+ { __builtin_trap(); }
+
+ [[noreturn]]
+ constexpr _Tp&
+ unchecked_push_back(_Tp&&)
+ { __builtin_trap(); }
+
+ template<typename... _Args>
+ [[noreturn]]
+ constexpr iterator
+ emplace(const_iterator, _Args&&...)
+ { __throw_bad_alloc(); }
+
+ [[noreturn]]
+ constexpr iterator
+ insert(const_iterator, const _Tp&)
+ { __throw_bad_alloc(); }
+
+ [[noreturn]]
+ constexpr iterator
+ insert(const_iterator, _Tp&&)
+ { __throw_bad_alloc(); }
+
+ constexpr iterator
+ insert(const_iterator, size_type __n, const _Tp&)
+ {
+ if (__n != 0)
+ __throw_bad_alloc();
+ return begin();
+ }
+
+ template<typename _InputIterator>
+ constexpr iterator
+ insert(const_iterator, _InputIterator __first, _InputIterator __last)
+ {
+ if (__first != __last)
+ __throw_bad_alloc();
+ return begin();
+ }
+
+ template<__detail::__container_compatible_range<_Tp> _Rg>
+ constexpr iterator
+ insert_range(const_iterator, _Rg&& __rg)
+ {
+ if (ranges::begin(__rg) != ranges::end(__rg))
+ __throw_bad_alloc();
+ return begin();
+ }
+
+ constexpr iterator
+ insert(const_iterator, initializer_list<_Tp> __il)
+ {
+ if (__il.size() != 0)
+ __throw_bad_alloc();
+ return begin();
+ }
+
+ [[noreturn]]
+ constexpr iterator
+ erase(const_iterator)
+ { __builtin_trap(); }
+
+ constexpr iterator
+ erase(const_iterator __first, const_iterator __last)
+ {
+ __glibcxx_assert(__first == __last);
+ return begin();
+ }
+
+ constexpr void
+ swap(inplace_vector& __x)
+ noexcept
+ { }
+
+ constexpr void
+ clear() noexcept
+ { }
+
+ constexpr friend bool
+ operator==(const inplace_vector&, const inplace_vector&)
+ { return true; }
+
+ constexpr friend auto
+ operator<=>(const inplace_vector&, const inplace_vector&)
+ requires requires (const _Tp __t) {
+ { __t < __t } -> __detail::__boolean_testable;
+ }
+ { return std::strong_ordering::equal; }
+
+ // n.b. there is not explicit wording requiring that swap for inplace_vector,
+ // with zero size, works even if element type is not swappable. However given
+ // that move operations are required to be present and trivial, it makes sense
+ // to support them.
+ constexpr friend void
+ swap(inplace_vector&, inplace_vector&) noexcept
+ { }
+ };
+
+_GLIBCXX_END_NAMESPACE_CONTAINER
+
+ template<typename _Tp, size_t _Nm, typename _Predicate>
+ constexpr size_t
+ erase_if(_GLIBCXX_STD_C::inplace_vector<_Tp, _Nm>& __cont,
+ _Predicate __pred)
+ {
+ if constexpr (_Nm != 0)
+ {
+ const auto __osz = __cont.size();
+ const auto __end = __cont.end();
+ auto __removed = std::__remove_if(__cont.begin(), __end,
+ std::move(__pred));
+ if (__removed != __end)
+ {
+ __cont.erase(__removed, __end);
+ return __osz - __cont.size();
+ }
+ }
+
+ return 0;
+ }
+
+ template<typename _Tp, size_t _Nm, typename _Up = _Tp>
+ constexpr size_t
+ erase(_GLIBCXX_STD_C::inplace_vector<_Tp, _Nm>& __cont, const _Up& __value)
+ { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#ifdef _GLIBCXX_DEBUG
+# include <debug/inplace_vector>
+#endif
+
+#endif // __glibcxx_inplace_vector
+#endif // _GLIBCXX_INPLACE_VECTOR
diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream
index d5bb187..ea232a7 100644
--- a/libstdc++-v3/include/std/istream
+++ b/libstdc++-v3/include/std/istream
@@ -42,6 +42,10 @@
#include <ios>
#include <ostream>
+#if __cplusplus > 202302L
+#include <concepts>
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -537,7 +541,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* is extracted); note that this condition will never occur if
* @a __delim equals @c traits::eof().
*
- * NB: Provide three overloads, instead of the single function
+ * NB: Provide four overloads, instead of the single function
* (with defaults) mandated by the Standard: this leads to a
* better performing implementation, while still conforming to
* the Standard.
@@ -551,6 +555,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__istream_type&
ignore();
+#if __cplusplus > 202302L
+ [[__gnu__::__always_inline__]]
+ __istream_type&
+ ignore(streamsize __n, char __delim) requires same_as<_CharT, char>
+ { return ignore(__n, traits_type::to_int_type(__delim)); }
+#endif
+
/**
* @brief Looking ahead in the stream
* @return The next character, or eof().
diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch
index cf64854..df126c6 100644
--- a/libstdc++-v3/include/std/latch
+++ b/libstdc++-v3/include/std/latch
@@ -41,7 +41,7 @@
#ifdef __cpp_lib_latch // C++ >= 20 && atomic_wait
#include <bits/atomic_base.h>
#include <ext/numeric_traits.h>
-#include <utility> // cmp_equal, cmp_less_equal, etc.
+#include <bits/intcmp.h> // cmp_equal, cmp_less_equal, etc.
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -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/limits b/libstdc++-v3/include/std/limits
index 2331c25..49ce7c9 100644
--- a/libstdc++-v3/include/std/limits
+++ b/libstdc++-v3/include/std/limits
@@ -1639,7 +1639,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#define __INT_N_U201103(TYPE)
#endif
-#if !defined(__STRICT_ANSI__)
#ifdef __GLIBCXX_TYPE_INT_N_0
__INT_N(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0,
__INT_N_201103 (__GLIBCXX_TYPE_INT_N_0),
@@ -1661,7 +1660,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__INT_N_U201103 (__GLIBCXX_TYPE_INT_N_3))
#endif
-#elif defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
__INT_N(__int128, 128,
__INT_N_201103 (__int128),
__INT_N_U201103 (__int128))
@@ -2129,7 +2128,7 @@ __glibcxx_float_n(128)
static _GLIBCXX_USE_CONSTEXPR int digits = 113;
static _GLIBCXX_USE_CONSTEXPR int digits10 = 33;
#if __cplusplus >= 201103L
- static constexpr int max_digits10 = 35;
+ static constexpr int max_digits10 = 36;
#endif
static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
static _GLIBCXX_USE_CONSTEXPR bool is_integer = false;
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
new file mode 100644
index 0000000..dc0aa4f
--- /dev/null
+++ b/libstdc++-v3/include/std/mdspan
@@ -0,0 +1,3399 @@
+// <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 <utility>
+
+#define __glibcxx_want_mdspan
+#define __glibcxx_want_aligned_accessor
+#define __glibcxx_want_submdspan
+#include <bits/version.h>
+
+#if __glibcxx_aligned_accessor
+#include <bits/align.h>
+#endif
+
+#if __glibcxx_submdspan
+#include <tuple>
+#endif
+
+
+#ifdef __glibcxx_mdspan
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ namespace __mdspan
+ {
+ consteval bool
+ __all_static(std::span<const size_t> __extents)
+ {
+ for(auto __ext : __extents)
+ if (__ext == dynamic_extent)
+ return false;
+ return true;
+ }
+
+ consteval bool
+ __all_dynamic(std::span<const size_t> __extents)
+ {
+ for(auto __ext : __extents)
+ if (__ext != dynamic_extent)
+ return false;
+ return true;
+ }
+
+ template<typename _IndexType, typename _OIndexType>
+ constexpr _IndexType
+ __index_type_cast(_OIndexType&& __other)
+ {
+ if constexpr (std::is_integral_v<_OIndexType>)
+ {
+ constexpr _IndexType __index_type_max
+ = __gnu_cxx::__int_traits<_IndexType>::__max;
+ constexpr _OIndexType __oindex_type_max
+ = __gnu_cxx::__int_traits<_OIndexType>::__max;
+
+ if constexpr (__index_type_max < __oindex_type_max)
+ __glibcxx_assert(cmp_less_equal(__other, __index_type_max));
+
+ if constexpr (std::is_signed_v<_OIndexType>)
+ __glibcxx_assert(__other >= 0);
+ return static_cast<_IndexType>(__other);
+ }
+ else
+ {
+ auto __ret = static_cast<_IndexType>(std::move(__other));
+ if constexpr (std::is_signed_v<_IndexType>)
+ __glibcxx_assert(__ret >= 0);
+ return __ret;
+ }
+ }
+
+ template<array _Extents>
+ class _StaticExtents
+ {
+ public:
+ 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 size_t
+ _S_dynamic_index(size_t __r) noexcept
+ { return _S_dynamic_index_data[__r]; }
+
+ static constexpr auto _S_dynamic_index_data = [] 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 += (_Extents[__i] == dynamic_extent);
+ }
+ __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 size_t
+ _S_dynamic_index_inv(size_t __r) noexcept
+ { return _S_dynamic_index_inv_data[__r]; }
+
+ static constexpr auto _S_dynamic_index_inv_data = [] consteval
+ {
+ array<size_t, _S_rank_dynamic> __ret;
+ for (size_t __i = 0, __r = 0; __i < _S_rank; ++__i)
+ if (_Extents[__i] == dynamic_extent)
+ __ret[__r++] = __i;
+ return __ret;
+ }();
+
+ static constexpr size_t
+ _S_static_extent(size_t __r) noexcept
+ { return _Extents[__r]; }
+ };
+
+ template<array _Extents>
+ requires (__all_dynamic<_Extents>())
+ class _StaticExtents<_Extents>
+ {
+ public:
+ static constexpr size_t _S_rank = _Extents.size();
+
+ static constexpr size_t
+ _S_dynamic_index(size_t __r) noexcept
+ { return __r; }
+
+ static constexpr size_t _S_rank_dynamic = _S_rank;
+
+ static constexpr size_t
+ _S_dynamic_index_inv(size_t __k) noexcept
+ { return __k; }
+
+ static constexpr size_t
+ _S_static_extent(size_t) noexcept
+ { return dynamic_extent; }
+ };
+
+ template<typename _IndexType, array _Extents>
+ class _ExtentsStorage : public _StaticExtents<_Extents>
+ {
+ private:
+ using _Base = _StaticExtents<_Extents>;
+
+ public:
+ using _Base::_S_rank;
+ using _Base::_S_rank_dynamic;
+ using _Base::_S_dynamic_index;
+ using _Base::_S_dynamic_index_inv;
+ using _Base::_S_static_extent;
+
+ static constexpr bool
+ _S_is_dynamic(size_t __r) noexcept
+ {
+ if constexpr (__all_static(_Extents))
+ return false;
+ else if constexpr (__all_dynamic(_Extents))
+ return true;
+ else
+ return _Extents[__r] == dynamic_extent;
+ }
+
+ template<typename _OIndexType>
+ static constexpr _IndexType
+ _S_int_cast(const _OIndexType& __other) noexcept
+ { return _IndexType(__other); }
+
+ constexpr _IndexType
+ _M_extent(size_t __r) const noexcept
+ {
+ if (_S_is_dynamic(__r))
+ return _M_dyn_exts[_S_dynamic_index(__r)];
+ else
+ return _S_static_extent(__r);
+ }
+
+ template<size_t _OtherRank, typename _GetOtherExtent>
+ static constexpr bool
+ _S_is_compatible_extents(_GetOtherExtent __get_extent) noexcept
+ {
+ if constexpr (_OtherRank == _S_rank)
+ for (size_t __i = 0; __i < _S_rank; ++__i)
+ if (!_S_is_dynamic(__i)
+ && !cmp_equal(_Extents[__i], _S_int_cast(__get_extent(__i))))
+ return false;
+ return true;
+ }
+
+ template<size_t _OtherRank, typename _GetOtherExtent>
+ constexpr void
+ _M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept
+ {
+ __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent));
+ 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 const array<size_t, _S_rank>&
+ _S_static_extents() noexcept
+ { return _Extents; }
+
+ 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),
+ _S_dynamic_index(__end) - _S_dynamic_index(__begin)};
+ }
+
+ private:
+ using _Storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type;
+ [[no_unique_address]] _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 <= __gnu_cxx::__int_traits<_IndexType>::__max;
+
+ template<typename _Extents>
+ constexpr const array<size_t, _Extents::rank()>&
+ __static_extents() noexcept
+ { return _Extents::_Storage::_S_static_extents(); }
+
+ template<typename _Extents>
+ constexpr span<const size_t>
+ __static_extents(size_t __begin, size_t __end) noexcept
+ {
+ const auto& __sta_exts = __static_extents<_Extents>();
+ return span<const size_t>(__sta_exts.data() + __begin, __end - __begin);
+ }
+
+ // Pre-compute: \prod_{i = 0}^r _Extents[i], for r = 0,..., n (exclusive)
+ template<array _Extents>
+ constexpr auto __fwd_partial_prods = [] consteval
+ {
+ constexpr size_t __rank = _Extents.size();
+ std::array<size_t, __rank> __ret;
+ size_t __prod = 1;
+ for (size_t __r = 0; __r < __rank; ++__r)
+ {
+ __ret[__r] = __prod;
+ if (size_t __ext = _Extents[__r]; __ext != dynamic_extent)
+ __prod *= __ext;
+ }
+ return __ret;
+ }();
+
+ // Pre-compute: \prod_{i = r+1}^{n-1} _Extents[i]
+ template<array _Extents>
+ constexpr auto __rev_partial_prods = [] consteval
+ {
+ constexpr size_t __rank = _Extents.size();
+ std::array<size_t, __rank> __ret;
+ size_t __prod = 1;
+ for (size_t __r = __rank; __r > 0; --__r)
+ {
+ __ret[__r - 1] = __prod;
+ if (size_t __ext = _Extents[__r - 1]; __ext != dynamic_extent)
+ __prod *= __ext;
+ }
+ return __ret;
+ }();
+
+ 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); }
+ }
+
+#if __glibcxx_submdspan
+ struct full_extent_t
+ {
+ explicit full_extent_t() = default;
+ };
+
+ inline constexpr full_extent_t full_extent{};
+
+ template<typename _OffsetType, typename _ExtentType, typename _StrideType>
+ struct strided_slice
+ {
+ static_assert(__is_signed_or_unsigned_integer<_OffsetType>::value
+ || __detail::__integral_constant_like<_OffsetType>);
+ static_assert(__is_signed_or_unsigned_integer<_ExtentType>::value
+ || __detail::__integral_constant_like<_ExtentType>);
+ static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
+ || __detail::__integral_constant_like<_StrideType>);
+
+ using offset_type = _OffsetType;
+ using extent_type = _ExtentType;
+ using stride_type = _StrideType;
+
+ [[no_unique_address]] offset_type offset{};
+ [[no_unique_address]] extent_type extent{};
+ [[no_unique_address]] stride_type stride{};
+ };
+
+ template<typename _Mapping>
+ struct submdspan_mapping_result
+ {
+ [[no_unique_address]] _Mapping mapping = _Mapping();
+ size_t offset{};
+ };
+
+ template<typename _Tp>
+ constexpr bool __is_submdspan_mapping_result = false;
+
+ template<typename _Mapping>
+ constexpr bool __is_submdspan_mapping_result<submdspan_mapping_result<_Mapping>> = true;
+
+ template<typename _Mapping>
+ concept __submdspan_mapping_result = __is_submdspan_mapping_result<_Mapping>;
+
+#endif // __glibcxx_submdspan
+
+ template<typename _IndexType, size_t... _Extents>
+ class extents
+ {
+ static_assert(__is_signed_or_unsigned_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");
+
+ using _Storage = __mdspan::_ExtentsStorage<
+ _IndexType, array<size_t, sizeof...(_Extents)>{_Extents...}>;
+ [[no_unique_address]] _Storage _M_exts;
+
+ 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 _Storage::_S_rank; }
+
+ static constexpr rank_type
+ rank_dynamic() noexcept { return _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 _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) || ...)
+ || (__gnu_cxx::__int_traits<index_type>::__max
+ < __gnu_cxx::__int_traits<_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{static_cast<_IndexType>(std::move(__exts))...}))
+ { }
+
+ template<typename _OIndexType, size_t _Nm>
+ requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+ && (_Nm == rank() || _Nm == rank_dynamic())
+ constexpr explicit(_Nm != rank_dynamic())
+ extents(span<_OIndexType, _Nm> __exts) noexcept
+ : _M_exts(span<const _OIndexType, _Nm>(__exts))
+ { }
+
+ template<typename _OIndexType, size_t _Nm>
+ requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+ && (_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
+ {
+ auto __impl = [&__self, &__other]<size_t... _Counts>(
+ index_sequence<_Counts...>)
+ { return (cmp_equal(__self.extent(_Counts),
+ __other.extent(_Counts)) && ...); };
+ return __impl(make_index_sequence<__self.rank()>());
+ }
+ }
+
+ private:
+ friend constexpr const array<size_t, rank()>&
+ __mdspan::__static_extents<extents>() noexcept;
+
+ friend constexpr span<const index_type>
+ __mdspan::__dynamic_extents<extents>(const extents&, size_t, size_t)
+ noexcept;
+
+ 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 _Tp, size_t _Nm>
+ consteval bool
+ __contains_zero(const array<_Tp, _Nm>& __exts) noexcept
+ { return __contains_zero(span<const _Tp>(__exts)); }
+
+ 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;
+ }
+
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __extents_prod(const _Extents& __exts, size_t __sta_prod, size_t __begin,
+ size_t __end) noexcept
+ {
+ if (__sta_prod == 0)
+ return 0;
+
+ size_t __ret = __sta_prod;
+ if constexpr (_Extents::rank_dynamic() > 0)
+ for (auto __factor : __dynamic_extents(__exts, __begin, __end))
+ __ret *= size_t(__factor);
+ return static_cast<typename _Extents::index_type>(__ret);
+ }
+
+ // Preconditions: _r < _Extents::rank()
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __fwd_prod(const _Extents& __exts, size_t __begin, size_t __end) noexcept
+ {
+ size_t __sta_prod = [__begin, __end] {
+ span<const size_t> __sta_exts
+ = __static_extents<_Extents>(__begin, __end);
+ size_t __ret = 1;
+ for(auto __ext : __sta_exts)
+ if (__ext != dynamic_extent)
+ __ret *= __ext;
+ return __ret;
+ }();
+ return __extents_prod(__exts, __sta_prod, __begin, __end);
+ }
+
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __fwd_prod(const _Extents& __exts, size_t __r) noexcept
+ {
+ constexpr size_t __rank = _Extents::rank();
+ constexpr auto& __sta_exts = __static_extents<_Extents>();
+ if constexpr (__rank == 1)
+ return 1;
+ else if constexpr (__rank == 2)
+ return __r == 0 ? 1 : __exts.extent(0);
+ else if constexpr (__all_dynamic(std::span(__sta_exts).first(__rank-1)))
+ return __extents_prod(__exts, 1, 0, __r);
+ else
+ {
+ size_t __sta_prod = __fwd_partial_prods<__sta_exts>[__r];
+ return __extents_prod(__exts, __sta_prod, 0, __r);
+ }
+ }
+
+ template<typename _IndexType, size_t _Nm>
+ consteval _IndexType
+ __fwd_prod(span<const _IndexType, _Nm> __values)
+ {
+ _IndexType __ret = 1;
+ for(auto __value : __values)
+ __ret *= __value;
+ return __ret;
+ }
+
+ // Preconditions: _r < _Extents::rank()
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __rev_prod(const _Extents& __exts, size_t __r) noexcept
+ {
+ constexpr size_t __rank = _Extents::rank();
+ constexpr auto& __sta_exts = __static_extents<_Extents>();
+ if constexpr (__rank == 1)
+ return 1;
+ else if constexpr (__rank == 2)
+ return __r == 0 ? __exts.extent(1) : 1;
+ else if constexpr (__all_dynamic(std::span(__sta_exts).last(__rank-1)))
+ return __extents_prod(__exts, 1, __r + 1, __rank);
+ else
+ {
+ size_t __sta_prod = __rev_partial_prods<__sta_exts>[__r];
+ return __extents_prod(__exts, __sta_prod, __r + 1, __rank);
+ }
+ }
+
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __size(const _Extents& __exts) noexcept
+ {
+ constexpr size_t __sta_prod = [] {
+ span<const size_t> __sta_exts = __static_extents<_Extents>();
+ size_t __ret = 1;
+ for(auto __ext : __sta_exts)
+ if (__ext != dynamic_extent)
+ __ret *= __ext;
+ return __ret;
+ }();
+ return __extents_prod(__exts, __sta_prod, 0, _Extents::rank());
+ }
+
+ template<typename _IndexType, size_t... _Counts>
+ auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
+ -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
+ }
+
+ template<typename _IndexType, size_t _Rank>
+ using dextents = decltype(__mdspan::__build_dextents_type<_IndexType>(
+ make_index_sequence<_Rank>()));
+
+#if __glibcxx_mdspan >= 202406L
+ template<size_t _Rank, typename _IndexType = size_t>
+ using dims = dextents<_IndexType, _Rank>;
+#endif
+
+ template<typename... _Integrals>
+ requires (is_convertible_v<_Integrals, size_t> && ...)
+ explicit extents(_Integrals...) ->
+ extents<size_t, __detail::__maybe_static_ext<_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;
+ };
+
+#ifdef __glibcxx_padded_layouts
+ template<size_t _PaddingValue>
+ struct layout_left_padded
+ {
+ template<typename _Extents>
+ class mapping;
+ };
+
+ template<size_t _PaddingValue>
+ struct layout_right_padded
+ {
+ template<typename _Extents>
+ class mapping;
+ };
+#endif
+
+ 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
+ {
+ _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, __exts.extent(__pos)));
+ __res += __idx * __mult;
+ __mult *= __exts.extent(__pos);
+ ++__pos;
+ };
+ (__update(__indices), ...);
+ }
+ return __res;
+ }
+
+ template<typename _IndexType>
+ consteval _IndexType
+ __static_quotient(std::span<const size_t> __sta_exts,
+ _IndexType __nom = __gnu_cxx::__int_traits<_IndexType>::__max)
+ {
+ for (auto __factor : __sta_exts)
+ {
+ if (__factor != dynamic_extent)
+ __nom /= _IndexType(__factor);
+ if (__nom == 0)
+ break;
+ }
+ return __nom;
+ }
+
+ template<typename _Extents,
+ typename _IndexType = typename _Extents::index_type>
+ requires __is_extents<_Extents>
+ consteval _IndexType
+ __static_quotient(_IndexType __nom
+ = __gnu_cxx::__int_traits<_IndexType>::__max)
+ {
+ std::span<const size_t> __sta_exts = __static_extents<_Extents>();
+ return __static_quotient<_IndexType>(__sta_exts, __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::template mapping<
+ typename _Mapping::extents_type>,
+ _Mapping>;
+
+ template<template<size_t> typename _Layout, typename _Mapping>
+ concept __padded_mapping_of = __mapping_of<
+ _Layout<_Mapping::padding_value>, _Mapping>;
+
+#ifdef __glibcxx_padded_layouts
+ template<typename _Mapping>
+ constexpr bool __is_left_padded_mapping = __padded_mapping_of<
+ layout_left_padded, _Mapping>;
+
+ template<typename _Mapping>
+ constexpr bool __is_right_padded_mapping = __padded_mapping_of<
+ layout_right_padded, _Mapping>;
+
+ template<typename _Mapping>
+ constexpr bool __is_padded_mapping = __is_left_padded_mapping<_Mapping>
+ || __is_right_padded_mapping<_Mapping>;
+#endif
+
+ template<typename _PaddedMapping>
+ consteval size_t
+ __get_static_stride()
+ { return _PaddedMapping::_PaddedStorage::_S_static_stride; }
+
+ template<typename _Mapping>
+ concept __standardized_mapping = __mapping_of<layout_left, _Mapping>
+ || __mapping_of<layout_right, _Mapping>
+ || __mapping_of<layout_stride, _Mapping>
+#ifdef __glibcxx_padded_layouts
+ || __is_left_padded_mapping<_Mapping>
+ || __is_right_padded_mapping<_Mapping>
+#endif
+ ;
+
+ // A tag type to create internal ctors.
+ class __internal_ctor
+ { };
+
+ 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>());
+ }
+ }
+
+#ifdef __glibcxx_submdspan
+ template<typename _Tp>
+ constexpr bool __is_strided_slice = false;
+
+ template<typename _OffsetType, typename _ExtentType, typename _StrideType>
+ constexpr bool __is_strided_slice<strided_slice<_OffsetType,
+ _ExtentType, _StrideType>> = true;
+
+ template<typename _IndexType, typename _OIndexType>
+ consteval bool
+ __is_representable_integer(_OIndexType __value)
+ {
+ constexpr auto __min = __gnu_cxx::__int_traits<_IndexType>::__min;
+ constexpr auto __max = __gnu_cxx::__int_traits<_IndexType>::__max;
+ return std::cmp_less_equal(__min, __value)
+ && std::cmp_less_equal(__value, __max);
+ }
+
+ template<typename _Tp>
+ constexpr bool __is_constant_wrapper = false;
+
+ template<_CwFixedValue _Xv, typename _Tp>
+ constexpr bool __is_constant_wrapper<constant_wrapper<_Xv, _Tp>>
+ = true;
+
+ template<size_t _Index, typename _Extents>
+ constexpr auto
+ __extract_extent(const _Extents& __exts)
+ {
+ using _IndexType = typename _Extents::index_type;
+ return extents<_IndexType, _Extents::static_extent(_Index)>{
+ __exts.extent(_Index)};
+ }
+
+ template<typename _Slice, typename _IndexType>
+ concept __acceptable_slice_type = same_as<_Slice, full_extent_t>
+ || same_as<_Slice, _IndexType> || __is_constant_wrapper<_Slice>
+ || __is_strided_slice<_Slice>;
+
+ template<typename _IndexType, typename... _Slices>
+ consteval auto
+ __subrank()
+ {
+ return (static_cast<size_t>(!convertible_to<_Slices, _IndexType>)
+ + ... + 0);
+ }
+
+ template<typename _IndexType, typename... _Slices>
+ consteval auto
+ __inv_map_rank()
+ {
+ constexpr auto __rank = sizeof...(_Slices);
+ constexpr auto __sub_rank = __subrank<_IndexType, _Slices...>();
+ auto __map = std::array<size_t, __sub_rank>{};
+ auto __is_int_like = std::array<bool, __rank>{
+ convertible_to<_Slices, _IndexType>...};
+
+ size_t __i = 0;
+ for (size_t __k = 0; __k < __rank; ++__k)
+ if (!__is_int_like[__k])
+ __map[__i++] = __k;
+ return __map;
+ }
+
+ template<typename _Slice>
+ constexpr auto
+ __slice_begin(_Slice __slice)
+ {
+ if constexpr (same_as<_Slice, full_extent_t>)
+ return 0;
+ else if constexpr (__is_strided_slice<_Slice>)
+ return __slice.offset;
+ else
+ return __slice; // collapsing slice
+ }
+
+ template<typename _Mapping, typename... _Slices>
+ constexpr size_t
+ __suboffset(const _Mapping& __mapping, const _Slices&... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ auto __any_past_the_end = [&]<size_t... _Is>(index_sequence<_Is...>)
+ {
+ auto __is_past_the_end = [](const auto& __slice, const auto& __ext)
+ {
+ using _Slice = remove_cvref_t<decltype(__slice)>;
+ if constexpr (is_convertible_v<_Slice, _IndexType>)
+ return false;
+ else if constexpr (same_as<_Slice, full_extent_t>
+ && __ext.static_extent(0) != 0
+ && __ext.static_extent(0) != dynamic_extent)
+ return false;
+ else
+ return __mdspan::__slice_begin(__slice) == __ext.extent(0);
+ };
+
+ const auto& __exts = __mapping.extents();
+ return ((__is_past_the_end(__slices...[_Is],
+ __mdspan::__extract_extent<_Is>(__exts))) || ...);
+ };
+
+ if constexpr ((same_as<_Slices, full_extent_t> && ...))
+ return __mdspan::__offset(__mapping);
+
+ if (__any_past_the_end(std::make_index_sequence<sizeof...(__slices)>()))
+ return __mapping.required_span_size();
+ return __mapping(__mdspan::__slice_begin(__slices)...);
+ }
+
+ template<typename _IndexType, size_t _Extent, typename _Slice>
+ consteval size_t
+ __static_slice_extent()
+ {
+ if constexpr (same_as<_Slice, full_extent_t>)
+ return _Extent;
+ else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>)
+ return 0;
+ else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>
+ && __is_constant_wrapper<typename _Slice::stride_type>)
+ return 1 + ((typename _Slice::extent_type{}) - 1)
+ / (typename _Slice::stride_type{});
+ else
+ return dynamic_extent;
+ }
+
+ template<size_t _K, typename _Extents, typename _Slice>
+ constexpr typename _Extents::index_type
+ __dynamic_slice_extent(const _Extents& __exts, _Slice __slice)
+ {
+ if constexpr (__is_strided_slice<_Slice>)
+ return __slice.extent == 0 ? 0 : 1 + (__slice.extent - 1) / __slice.stride;
+ else
+ return __exts.extent(_K);
+ }
+
+ template<typename _IndexType, size_t... _Extents, typename... _Slices>
+ requires (sizeof...(_Slices) == sizeof...(_Extents))
+ constexpr auto
+ __subextents(const extents<_IndexType, _Extents...>& __exts,
+ _Slices... __slices)
+ {
+ constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
+ auto __impl = [&]<size_t... _Indices>(std::index_sequence<_Indices...>)
+ {
+ using _SubExts = extents<_IndexType,
+ __mdspan::__static_slice_extent<_IndexType,
+ _Extents...[__inv_map[_Indices]],
+ _Slices...[__inv_map[_Indices]]>()...>;
+ if constexpr (_SubExts::rank_dynamic() == 0)
+ return _SubExts{};
+ else
+ {
+ using _StaticSubExtents = __mdspan::_StaticExtents<
+ __mdspan::__static_extents<_SubExts>()>;
+ auto __create = [&]<size_t... _Is>(std::index_sequence<_Is...>)
+ {
+ constexpr auto __slice_idx = [__inv_map](size_t __i) consteval
+ {
+ return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)];
+ };
+
+ return _SubExts{__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>(
+ __exts, __slices...[__slice_idx(_Is)])...};
+ };
+ constexpr auto __dyn_subrank = _SubExts::rank_dynamic();
+ return __create(std::make_index_sequence<__dyn_subrank>());
+ }
+ };
+
+ return __impl(std::make_index_sequence<__inv_map.size()>());
+ }
+
+ enum class _LayoutSide
+ {
+ __left,
+ __right,
+ __unknown
+ };
+
+ template<typename _Mapping>
+ consteval _LayoutSide
+ __mapping_side()
+ {
+ if constexpr (__is_left_padded_mapping<_Mapping>
+ || __mapping_of<layout_left, _Mapping>)
+ return _LayoutSide::__left;
+ if constexpr (__is_right_padded_mapping<_Mapping>
+ || __mapping_of<layout_right, _Mapping>)
+ return _LayoutSide::__right;
+ else
+ return _LayoutSide::__unknown;
+ }
+
+ template<_LayoutSide _Side, size_t _Rank>
+ struct _StridesTrait
+ {
+ static constexpr const _LayoutSide _S_side = _Side;
+
+ static constexpr size_t
+ _S_idx(size_t __k) noexcept
+ {
+ if constexpr (_Side == _LayoutSide::__left)
+ return __k;
+ else
+ return _Rank - 1 - __k;
+ }
+
+ // Unifies the formulas for computing strides for padded and unpadded
+ // layouts.
+ template<typename _Mapping>
+ static constexpr typename _Mapping::index_type
+ _S_padded_extent(const _Mapping& __mapping, size_t __k)
+ {
+ if (__k == 0)
+ return __mapping.stride(_S_idx(1));
+ else
+ return __mapping.extents().extent(_S_idx(__k));
+ }
+
+ template<typename _IndexType, typename... _Slices>
+ static consteval auto
+ _S_inv_map()
+ {
+ static_assert(_Side != _LayoutSide::__unknown);
+ auto __impl = [&]<size_t... _Is>(std::index_sequence<_Is...>)
+ {
+ return __mdspan::__inv_map_rank<_IndexType, _Slices...[_S_idx(_Is)]...>();
+ };
+ return __impl(std::make_index_sequence<_Rank>());
+ }
+ };
+
+ template<typename _SubExts, typename _Mapping, typename... _Slices>
+ constexpr auto
+ __substrides_generic(const _Mapping& __mapping, const _Slices&... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ if constexpr (_SubExts::rank() == 0)
+ return array<_IndexType, _SubExts::rank()>{};
+ else
+ {
+ auto __stride = [&__mapping](size_t __k, auto __slice) -> _IndexType
+ {
+ if constexpr (__is_strided_slice<decltype(__slice)>)
+ if (__slice.stride < __slice.extent)
+ return __mapping.stride(__k) * __slice.stride;
+ return __mapping.stride(__k);
+ };
+
+ auto __impl = [&]<size_t... _Is>(std::index_sequence<_Is...>)
+ {
+ constexpr auto __inv_map
+ = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
+ return array<_IndexType, _SubExts::rank()>{
+ __stride(__inv_map[_Is], __slices...[__inv_map[_Is]])...};
+ };
+ return __impl(std::make_index_sequence<_SubExts::rank()>());
+ }
+ };
+
+ template<typename _SubExts, typename _Mapping, typename... _Slices>
+ constexpr auto
+ __substrides_standardized(const _Mapping& __mapping,
+ const _Slices&... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ using _Trait = _StridesTrait<__mapping_side<_Mapping>(),
+ _Mapping::extents_type::rank()>;
+ using _SubTrait = _StridesTrait<__mapping_side<_Mapping>(), _SubExts::rank()>;
+
+ constexpr size_t __sub_rank = _SubExts::rank();
+
+ std::array<_IndexType, __sub_rank> __ret;
+ if constexpr (__sub_rank > 0)
+ {
+ constexpr auto __inv_map
+ = _Trait::template _S_inv_map<_IndexType, _Slices...>();
+ auto __loop = [&]<size_t... _Ks>(std::index_sequence<_Ks...>)
+ {
+ size_t __i0 = 0;
+ size_t __stride = 1;
+ auto __body = [&](size_t __k, auto __slice)
+ {
+ for (size_t __i = __i0; __i < __inv_map[__k]; ++__i)
+ __stride *= _Trait::_S_padded_extent(__mapping, __i);
+
+ size_t __krev = _SubTrait::_S_idx(__k);
+ if constexpr (__is_strided_slice<decltype(__slice)>)
+ {
+ if (__slice.stride < __slice.extent)
+ __ret[__krev] = __stride * __slice.stride;
+ else
+ __ret[__krev] = __stride;
+ }
+ else
+ __ret[__krev] = __stride;
+
+ __i0 = __inv_map[__k];
+ };
+
+ ((__body(_Ks, __slices...[_Trait::_S_idx(__inv_map[_Ks])])),...);
+ };
+ __loop(std::make_index_sequence<__sub_rank>());
+ }
+ return __ret;
+ }
+
+
+ template<typename _SubExts, typename _Mapping, typename... _Slices>
+ constexpr auto
+ __substrides(const _Mapping& __mapping, const _Slices&... __slices)
+ {
+ if constexpr (__mdspan::__mapping_side<_Mapping>() == _LayoutSide::__unknown)
+ return __mdspan::__substrides_generic<_SubExts>(__mapping, __slices...);
+ else
+ return __mdspan::__substrides_standardized<_SubExts>(__mapping, __slices...);
+ }
+
+ template<typename _Slice>
+ concept __is_unit_stride_slice = (__mdspan::__is_strided_slice<_Slice>
+ && __mdspan::__is_constant_wrapper<typename _Slice::stride_type>
+ && _Slice::stride_type::value == 1)
+ || std::same_as<_Slice, full_extent_t>;
+
+ // These are (forced) exclusive categories:
+ // - full & collapsing: obvious,
+ // - unit_strided_slice: strided_slice{a, b, cw<1>}, but not `full`,
+ // - strided_slice: strided_slice{a, b, c} with c != cw<1>.
+ enum class _SliceKind
+ {
+ __strided_slice,
+ __unit_strided_slice,
+ __full,
+ __collapsing
+ };
+
+ template<typename _Slice>
+ consteval _SliceKind
+ __make_slice_kind()
+ {
+ if constexpr (std::same_as<_Slice, full_extent_t>)
+ return _SliceKind::__full;
+ else if constexpr (__mdspan::__is_strided_slice<_Slice>)
+ {
+ if constexpr (__mdspan::__is_unit_stride_slice<_Slice>)
+ return _SliceKind::__unit_strided_slice;
+ else
+ return _SliceKind::__strided_slice;
+ }
+ else
+ return _SliceKind::__collapsing;
+ }
+
+ template<typename... _Slices>
+ consteval array<_SliceKind, sizeof...(_Slices)>
+ __make_slice_kind_array()
+ {
+ return array<_SliceKind, sizeof...(_Slices)>{
+ __mdspan::__make_slice_kind<_Slices>()...};
+ }
+
+ // __block_size - 1
+ // [full, ..., full, unit_slice , *]
+ consteval bool
+ __is_block(span<const _SliceKind> __slice_kinds, size_t __block_size)
+ {
+ if (__block_size == 0)
+ return false;
+
+ if (__block_size > __slice_kinds.size())
+ return false;
+
+ for (size_t __i = 0; __i < __block_size - 1; ++__i)
+ if (__slice_kinds[__i] != _SliceKind::__full)
+ return false;
+
+ auto __last = __slice_kinds[__block_size - 1];
+ return __last == _SliceKind::__full
+ || __last == _SliceKind::__unit_strided_slice;
+ }
+
+ // __u __u + __sub_rank-2
+ // [unit_slice, i, ..., k, full, ..., full, unit_slice, *]
+ static consteval size_t
+ __padded_block_begin_generic(span<const _SliceKind> __slice_kinds,
+ size_t __sub_rank)
+ {
+ if (__slice_kinds[0] != _SliceKind::__full
+ && __slice_kinds[0] != _SliceKind::__unit_strided_slice)
+ return dynamic_extent;
+ else if (__slice_kinds.size() == 1)
+ return dynamic_extent;
+ else
+ {
+ size_t __u = 1;
+ while(__u < __slice_kinds.size()
+ && __slice_kinds[__u] == _SliceKind::__collapsing)
+ ++__u;
+
+ if (__mdspan::__is_block(__slice_kinds.subspan(__u), __sub_rank -1))
+ return __u;
+ return dynamic_extent;
+ }
+ }
+
+ template<_LayoutSide _Side, size_t _Nm>
+ static consteval size_t
+ __padded_block_begin(span<const _SliceKind, _Nm> __slice_kinds, size_t __sub_rank)
+ {
+ if constexpr (_Side == _LayoutSide::__left)
+ return __mdspan::__padded_block_begin_generic(__slice_kinds, __sub_rank);
+ else
+ {
+ std::array<_SliceKind, _Nm> __rev_slices;
+ for(size_t __i = 0; __i < _Nm; ++__i)
+ __rev_slices[__i] = __slice_kinds[_Nm - 1 - __i];
+ auto __rev_slice_kinds = span<const _SliceKind>(__rev_slices);
+
+ auto __u = __mdspan::__padded_block_begin_generic(__rev_slice_kinds,
+ __sub_rank);
+ return __u == dynamic_extent ? dynamic_extent : _Nm - 1 - __u;
+ }
+ }
+
+ template<_LayoutSide _Side, bool _Padded>
+ struct _SubMdspanMapping;
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__left, false>
+ {
+ using _Layout = layout_left;
+ template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __sta_exts = __mdspan::__static_extents<_Extents>(0, _Us);
+ if constexpr (!__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __mdspan::__fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds, size_t __sub_rank)
+ { return __mdspan::__is_block(__slice_kinds, __sub_rank); }
+ };
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__left, true>
+ {
+ using _Layout = layout_left;
+ template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __sta_exts
+ = __mdspan::__static_extents<_Extents>(1, _Us);
+ constexpr auto __sta_padstride
+ = __mdspan::__get_static_stride<_Mapping>();
+ if constexpr (__sta_padstride == dynamic_extent
+ || !__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
+ size_t __sub_rank)
+ {
+ if (__sub_rank == 1)
+ return __slice_kinds[0] == _SliceKind::__unit_strided_slice
+ || __slice_kinds[0] == _SliceKind::__full;
+ else
+ return false;
+ }
+ };
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__right, false>
+ {
+ using _Layout = layout_right;
+ template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __rank = _Extents::rank();
+ constexpr auto __sta_exts
+ = __mdspan::__static_extents<_Extents>(_Us + 1, __rank);
+ if constexpr (!__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
+ size_t __sub_rank)
+ {
+ auto __rev_slice_kinds = array<_SliceKind, _Nm>{};
+ for(size_t __i = 0; __i < _Nm; ++__i)
+ __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i];
+ return __mdspan::__is_block(span(__rev_slice_kinds), __sub_rank);
+ }
+ };
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__right, true>
+ {
+ using _Layout = layout_right;
+ template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __rank = _Extents::rank();
+ constexpr auto __sta_exts
+ = __mdspan::__static_extents<_Extents>(_Us + 1, __rank - 1);
+ constexpr auto __sta_padstride
+ = __mdspan::__get_static_stride<_Mapping>();
+ if constexpr (__sta_padstride == dynamic_extent
+ || !__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
+ size_t __sub_rank)
+ {
+ if (__sub_rank == 1)
+ return __slice_kinds[_Nm - 1] == _SliceKind::__unit_strided_slice
+ || __slice_kinds[_Nm - 1] == _SliceKind::__full;
+ else
+ return false;
+ }
+ };
+
+
+ template<typename _Mapping>
+ constexpr auto
+ __submdspan_mapping_impl(const _Mapping& __mapping)
+ { return submdspan_mapping_result{__mapping, 0}; }
+
+ template<typename _Mapping, typename... _Slices>
+ requires (sizeof...(_Slices) > 0)
+ constexpr auto
+ __submdspan_mapping_impl(const _Mapping& __mapping, _Slices... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ static_assert((__acceptable_slice_type<_Slices, _IndexType> && ...));
+
+ constexpr auto __side = __mdspan::__mapping_side<_Mapping>();
+ constexpr auto __rank = sizeof...(_Slices);
+ using _Trait = _SubMdspanMapping<__side, __is_padded_mapping<_Mapping>>;
+ using _SliceView = span<const _SliceKind, __rank>;
+
+ constexpr auto __slice_kinds = __mdspan::__make_slice_kind_array<_Slices...>();
+ auto __offset = __mdspan::__suboffset(__mapping, __slices...);
+ auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
+ using _SubExts = decltype(__sub_exts);
+ constexpr auto __sub_rank = _SubExts::rank();
+ if constexpr (__sub_rank == 0)
+ return submdspan_mapping_result{
+ typename _Trait::_Layout::mapping(__sub_exts), __offset};
+ else if constexpr (_Trait::_S_is_unpadded_submdspan(
+ _SliceView(__slice_kinds), __sub_rank))
+ return submdspan_mapping_result{
+ typename _Trait::_Layout::mapping(__sub_exts), __offset};
+ else if constexpr (
+ constexpr auto __u = __padded_block_begin<__side>(
+ _SliceView(__slice_kinds), __sub_rank);
+ __u != dynamic_extent)
+ {
+ constexpr auto __pad = _Trait::template _S_pad<_Mapping, __u>();
+ using _Layout = typename _Trait::template _PaddedLayout<__pad>;
+ return submdspan_mapping_result{
+ typename _Layout::mapping(__sub_exts, __mapping.stride(__u)),
+ __offset};
+ }
+ else
+ {
+ auto __sub_strides
+ = __mdspan::__substrides<_SubExts>(__mapping, __slices...);
+ return submdspan_mapping_result{
+ layout_stride::mapping(__sub_exts, __sub_strides), __offset};
+ }
+ }
+#endif // __glibcxx_submdspan
+ }
+
+ 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
+ && is_convertible_v<_OExtents, extents_type>))
+ mapping(const layout_stride::mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { __glibcxx_assert(*this == __other); }
+
+#if __glibcxx_padded_layouts
+ template<typename _LeftpadMapping>
+ requires __mdspan::__is_left_padded_mapping<_LeftpadMapping>
+ && is_constructible_v<extents_type,
+ typename _LeftpadMapping::extents_type>
+ constexpr
+ explicit(!is_convertible_v<typename _LeftpadMapping::extents_type,
+ extents_type>)
+ mapping(const _LeftpadMapping& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ {
+ constexpr size_t __ostride_sta
+ = __mdspan::__get_static_stride<_LeftpadMapping>();
+
+ if constexpr (extents_type::rank() > 1)
+ {
+ if constexpr (extents_type::static_extent(0) != dynamic_extent
+ && __ostride_sta != dynamic_extent)
+ static_assert(extents_type::static_extent(0) == __ostride_sta);
+ else
+ __glibcxx_assert(__other.stride(1)
+ == __other.extents().extent(0));
+ }
+ }
+#endif // __glibcxx_padded_layouts
+
+ 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::__size(_M_extents); }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4314. Missing move in mdspan layout mapping::operator()
+ 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>(std::move(__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));
+ }
+
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
+
+ [[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;
+ _GLIBCXX_DEBUG_ASSERT(cmp_less(__ind_arr[__pos],
+ __exts.extent(__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
+ && is_convertible_v<_OExtents, extents_type>))
+ mapping(const layout_stride::mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { __glibcxx_assert(*this == __other); }
+
+#if __glibcxx_padded_layouts
+ template<typename _RightPaddedMapping>
+ requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
+ && is_constructible_v<extents_type,
+ typename _RightPaddedMapping::extents_type>
+ constexpr
+ explicit(!is_convertible_v<typename _RightPaddedMapping::extents_type,
+ extents_type>)
+ mapping(const _RightPaddedMapping& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ {
+ constexpr size_t __rank = extents_type::rank();
+ constexpr size_t __ostride_sta
+ = __mdspan::__get_static_stride<_RightPaddedMapping>();
+
+ if constexpr (__rank > 1)
+ {
+ if constexpr (extents_type::static_extent(__rank - 1) != dynamic_extent
+ && __ostride_sta != dynamic_extent)
+ static_assert(extents_type::static_extent(__rank - 1)
+ == __ostride_sta);
+ else
+ __glibcxx_assert(__other.stride(__rank - 2)
+ == __other.extents().extent(__rank - 1));
+ }
+ }
+#endif
+
+ 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::__size(_M_extents); }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4314. Missing move in mdspan layout mapping::operator()
+ 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>(std::move(__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));
+ }
+
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
+
+ [[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, 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
+ {
+ _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx,
+ __m.extents().extent(__pos)));
+ __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<typename _OIndexType>
+ requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+ 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<typename _OIndexType>
+ requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+ 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(__gnu_cxx::__int_traits<_OIndexType>::__max,
+ __gnu_cxx::__int_traits<index_type>::__max))
+ __glibcxx_assert(!cmp_less(
+ __gnu_cxx::__int_traits<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;
+ }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4314. Missing move in mdspan layout mapping::operator()
+ 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>(std::move(__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())
+ {
+ auto __size = __mdspan::__size(_M_extents);
+ 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:
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ {
+ if constexpr (sizeof...(_Slices) == 0)
+ return submdspan_mapping_result{__mapping, 0};
+ else
+ {
+ auto __offset = __mdspan::__suboffset(__mapping, __slices...);
+ auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
+ auto __sub_strides
+ = __mdspan::__substrides<decltype(__sub_exts)>(__mapping, __slices...);
+ return submdspan_mapping_result{
+ layout_stride::mapping(__sub_exts, __sub_strides), __offset};
+ }
+ }
+#endif
+
+ using _Strides = typename __array_traits<index_type,
+ extents_type::rank()>::_Type;
+ [[no_unique_address]] extents_type _M_extents;
+ [[no_unique_address]] _Strides _M_strides;
+ };
+
+#ifdef __glibcxx_padded_layouts
+ namespace __mdspan
+ {
+ constexpr size_t
+ __least_multiple(size_t __x, size_t __y)
+ {
+ if (__x <= 1)
+ return __y;
+ return (__y / __x + (__y % __x != 0)) * __x ;
+ }
+
+ template<typename _IndexType>
+ constexpr bool
+ __is_representable_least_multiple(size_t __x, size_t __y)
+ {
+ constexpr auto __y_max = __gnu_cxx::__int_traits<_IndexType>::__max;
+ if(std::cmp_greater(__y, __y_max))
+ return false;
+
+ if(__x <= 1)
+ return true;
+
+ auto __max_delta = __y_max - static_cast<_IndexType>(__y);
+ auto __y_mod_x = __y % __x;
+ auto __delta = (__y_mod_x == 0) ? size_t(0) : (__x - __y_mod_x);
+ return std::cmp_less_equal(__delta, __max_delta);
+ }
+
+ template<typename _Extents, size_t _PaddingValue, typename _LayoutTraits,
+ size_t _Rank = _Extents::rank()>
+ concept __valid_static_stride = (_Extents::rank() <= 1)
+ || (_PaddingValue == dynamic_extent)
+ || (_Extents::static_extent(_LayoutTraits::_S_ext_idx) == dynamic_extent)
+ || (__is_representable_least_multiple<size_t>(
+ _PaddingValue, _Extents::static_extent(_LayoutTraits::_S_ext_idx)));
+
+ template<size_t _PaddedStride, typename _Extents,
+ typename _LayoutTraits>
+ consteval bool
+ __is_representable_padded_size()
+ {
+ using _IndexType = typename _Extents::index_type;
+ auto __sta_exts = __static_extents<_Extents>(
+ _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
+ size_t __max = __gnu_cxx::__int_traits<_IndexType>::__max;
+ return __static_quotient(__sta_exts, __max / _PaddedStride) != 0;
+ }
+
+ template<typename _Extents, size_t _PaddedStride, typename _LayoutTraits,
+ size_t _Rank = _Extents::rank()>
+ concept __valid_padded_size = (_Rank <= 1)
+ || (_PaddedStride == dynamic_extent)
+ || (!__all_static(__static_extents<_Extents>()))
+ || (__contains_zero(__static_extents<_Extents>()))
+ || (__is_representable_padded_size<_PaddedStride, _Extents,
+ _LayoutTraits>());
+
+ template<typename _Extents, typename _Stride, typename... _Indices>
+ constexpr typename _Extents::index_type
+ __linear_index_leftpad(const _Extents& __exts, _Stride __stride,
+ _Indices... __indices)
+ {
+ // i0 + stride*(i1 + extents.extent(1)*...)
+ using _IndexType = typename _Extents::index_type;
+ _IndexType __res = 0;
+ if constexpr (sizeof...(__indices) > 0)
+ {
+ _IndexType __mult = 1;
+
+ auto __update_rest = [&, __pos = 1u](_IndexType __idx) mutable
+ {
+ __res += __idx * __mult;
+ __mult *= __exts.extent(__pos);
+ ++__pos;
+ };
+
+ auto __update = [&](_IndexType __idx, auto... __rest)
+ {
+ __res += __idx;
+ __mult = __stride.extent(0);
+ (__update_rest(__rest), ...);
+ };
+ __update(__indices...);
+ }
+ return __res;
+ }
+
+ template<typename _Extents, typename _Stride, typename... _Indices>
+ constexpr typename _Extents::index_type
+ __linear_index_rightpad(const _Extents& __exts, _Stride __stride,
+ _Indices... __indices)
+ {
+ // i[n-1] + stride*(i[n-2] + extents.extent(n-2])*...)
+ using _IndexType = typename _Extents::index_type;
+ _IndexType __res = 0;
+ if constexpr (sizeof...(__indices) > 0)
+ {
+ _IndexType __mult = 1;
+ array<_IndexType, sizeof...(__indices)> __ind_arr{__indices...};
+
+ auto __update_rest = [&, __pos = __exts.rank()-1](_IndexType) mutable
+ {
+ --__pos;
+ __res += __ind_arr[__pos] * __mult;
+ __mult *= __exts.extent(__pos);
+ };
+
+ auto __update = [&](_IndexType, auto... __rest)
+ {
+ __res += __ind_arr[__exts.rank() - 1];
+ __mult = __stride.extent(0);
+ (__update_rest(__rest), ...);
+ };
+ __update(__indices...);
+ }
+ return __res;
+ }
+
+ template<size_t _Rank>
+ struct _LeftPaddedLayoutTraits
+ {
+ using _LayoutSame = layout_left;
+ using _LayoutOther = layout_right;
+
+ constexpr static const size_t _S_ext_idx = 0;
+ constexpr static const size_t _S_stride_idx = 1;
+ constexpr static const size_t _S_unpad_begin = 1;
+ constexpr static const size_t _S_unpad_end = _Rank;
+
+ template<typename _IndexType, size_t _StaticStride, size_t..._Extents>
+ constexpr static auto
+ _S_make_padded_extent(
+ extents<_IndexType, _StaticStride> __stride,
+ const extents<_IndexType, _Extents...>& __exts)
+ {
+ auto __impl = [&]<size_t... _Is>(integer_sequence<size_t, _Is...>)
+ {
+ return extents<_IndexType, _StaticStride,
+ (_Extents...[_Is + 1])...>{
+ __stride.extent(0), __exts.extent(_Is + 1)...};
+ };
+ return __impl(make_index_sequence<sizeof...(_Extents) - 1>());
+ }
+ };
+
+ template<size_t _Rank>
+ struct _RightPaddedLayoutTraits
+ {
+ using _LayoutSame = layout_right;
+ using _LayoutOther = layout_left;
+
+ constexpr static size_t _S_ext_idx = _Rank - 1;
+ constexpr static size_t _S_stride_idx = _Rank - 2;
+ constexpr static size_t _S_unpad_begin = 0;
+ constexpr static size_t _S_unpad_end = _Rank - 1;
+
+ template<typename _IndexType, size_t _StaticStride, size_t..._Extents>
+ constexpr static auto
+ _S_make_padded_extent(
+ extents<_IndexType, _StaticStride> __stride,
+ const extents<_IndexType, _Extents...>& __exts)
+ {
+ auto __impl = [&]<size_t... _Is>(integer_sequence<size_t, _Is...>)
+ {
+ return extents<_IndexType, (_Extents...[_Is])..., _StaticStride>{
+ __exts.extent(_Is)..., __stride.extent(0)};
+ };
+ return __impl(make_index_sequence<sizeof...(_Extents) - 1>());
+ }
+ };
+
+ template<size_t _PaddingValue, typename _Extents, typename _LayoutTraits>
+ class _PaddedStorage
+ {
+ using _LayoutSame = typename _LayoutTraits::_LayoutSame;
+
+ public:
+ using _IndexType = typename _Extents::index_type;
+ constexpr static size_t _S_rank = _Extents::rank();
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4372. Weaken Mandates: for dynamic padding values in padded layouts
+ static_assert((_PaddingValue == dynamic_extent)
+ || (cmp_less_equal(_PaddingValue,
+ __gnu_cxx::__int_traits<_IndexType>::__max)),
+ "padding_value must be representable as index_type");
+
+ static_assert(__representable_size<_Extents, _IndexType>,
+ "The size of extents_type must be representable as index_type");
+
+ static_assert(__valid_static_stride<_Extents, _PaddingValue,
+ _LayoutTraits>,
+ "The padded stride must be representable as size_t");
+
+ static constexpr size_t _S_static_stride = [] consteval
+ {
+ constexpr size_t __rank = _Extents::rank();
+ if constexpr (__rank <= 1)
+ return 0;
+ else
+ {
+ constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
+ constexpr size_t __sta_ext = _Extents::static_extent(__ext_idx);
+ if constexpr (__sta_ext == 0)
+ return size_t(0);
+ else if constexpr (_PaddingValue == dynamic_extent
+ || __sta_ext == dynamic_extent)
+ return dynamic_extent;
+ else
+ return __least_multiple(_PaddingValue, __sta_ext);
+ }
+ }();
+
+ static_assert(_S_static_stride == dynamic_extent
+ || cmp_less_equal(_S_static_stride,
+ __gnu_cxx::__int_traits<_IndexType>::__max),
+ "Padded stride must be representable as index_type");
+
+ static_assert(__valid_padded_size<_Extents, _S_static_stride,
+ _LayoutTraits>);
+
+ constexpr
+ _PaddedStorage() noexcept
+ {
+ if constexpr (_S_rank > 1)
+ if constexpr (_S_static_stride == dynamic_extent
+ && _S_static_padextent() != dynamic_extent)
+ _M_stride = _Stride{_S_static_padextent()};
+ }
+
+ constexpr explicit
+ _PaddedStorage(const _Extents& __exts)
+ : _M_extents(__exts)
+ {
+ if constexpr (!__all_static(__static_extents<_Extents>()))
+ __glibcxx_assert(__is_representable_extents(_M_extents));
+
+ if constexpr (_S_rank > 1)
+ {
+ _IndexType __stride;
+ if constexpr (_PaddingValue == dynamic_extent)
+ __stride = _M_padextent();
+ else if constexpr (_S_static_padextent() != dynamic_extent)
+ return;
+ else
+ {
+ __glibcxx_assert(
+ __is_representable_least_multiple<_IndexType>(
+ _PaddingValue, _M_padextent()));
+
+ __stride = static_cast<_IndexType>(
+ __least_multiple(_PaddingValue, _M_padextent()));
+
+ __glibcxx_assert(__is_representable_extents(
+ _LayoutTraits::_S_make_padded_extent(
+ std::dextents<_IndexType, 1>{__stride},
+ _M_extents)));
+ }
+ _M_stride = _Stride{__stride};
+ }
+ }
+
+ constexpr explicit
+ _PaddedStorage(const _Extents& __exts, _IndexType __pad)
+ : _M_extents(__exts)
+ {
+ if constexpr (_PaddingValue != dynamic_extent)
+ __glibcxx_assert(cmp_equal(_PaddingValue, __pad));
+ if constexpr (_S_rank > 1 && _S_static_stride == dynamic_extent)
+ {
+ __glibcxx_assert(
+ __is_representable_least_multiple<_IndexType>(
+ __pad, _M_padextent()));
+
+ _M_stride = _Stride{static_cast<_IndexType>(
+ __least_multiple(__pad, _M_padextent()))};
+
+ __glibcxx_assert(__is_representable_extents(
+ _LayoutTraits::_S_make_padded_extent(
+ _M_stride, _M_extents)));
+ }
+ }
+
+ template<typename _OExtents>
+ constexpr explicit
+ _PaddedStorage(
+ const typename _LayoutSame::template mapping<_OExtents>& __other)
+ : _PaddedStorage(_Extents(__other.extents()))
+ {
+ constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
+ constexpr size_t __ext_idx = _LayoutTraits::_S_ext_idx;
+ if constexpr (_S_rank > 1 && _PaddingValue != dynamic_extent)
+ {
+ static_assert(_S_static_stride == dynamic_extent
+ || _OExtents::static_extent(__ext_idx) == dynamic_extent
+ || _S_static_stride == _OExtents::static_extent(__ext_idx),
+ "The padded stride must be compatible with other");
+
+ if constexpr (_S_static_stride == dynamic_extent
+ || _OExtents::static_extent(__stride_idx) == dynamic_extent)
+ __glibcxx_assert(std::cmp_equal(_M_padstride(),
+ _M_padextent()));
+ }
+ }
+
+ template<typename _OExtents>
+ constexpr explicit
+ _PaddedStorage(const typename layout_stride::mapping<_OExtents>&
+ __other)
+ : _M_extents(__other.extents())
+ {
+ __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
+ __gnu_cxx::__int_traits<_IndexType>
+ ::__max));
+
+ constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
+ if constexpr (_S_rank > 1)
+ {
+ if constexpr (_PaddingValue != dynamic_extent)
+ __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
+ _M_calc_padstride())
+ && "The padded stride must be compatible with other");
+ if constexpr (_S_static_stride == dynamic_extent)
+ _M_stride = _Stride{__other.stride(__stride_idx)};
+ }
+ }
+
+ template<typename _SamePaddedMapping>
+ constexpr explicit
+ _PaddedStorage(_LayoutTraits::_LayoutSame,
+ const _SamePaddedMapping& __other)
+ : _M_extents(__other.extents())
+ {
+ if constexpr (_S_rank > 1)
+ {
+ static_assert(_PaddingValue == dynamic_extent
+ || _SamePaddedMapping::padding_value == dynamic_extent
+ || _PaddingValue == _SamePaddedMapping::padding_value,
+ "If neither PaddingValue is dynamic_extent, then they must "
+ "be equal");
+
+ constexpr size_t __stride_idx = _LayoutTraits::_S_stride_idx;
+ if constexpr (_PaddingValue != dynamic_extent)
+ __glibcxx_assert(cmp_equal(__other.stride(__stride_idx),
+ _M_calc_padstride())
+ && "The padded stride must be compatible with other");
+ if constexpr (_S_static_stride == dynamic_extent)
+ _M_stride = _Stride{__other.stride(__stride_idx)};
+ }
+ __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
+ __gnu_cxx::__int_traits<_IndexType>::__max));
+ }
+
+ template<typename _OtherPaddedMapping>
+ constexpr explicit
+ _PaddedStorage(_LayoutTraits::_LayoutOther,
+ const _OtherPaddedMapping& __other) noexcept
+ : _M_extents(__other.extents())
+ {
+ __glibcxx_assert(cmp_less_equal(__other.required_span_size(),
+ __gnu_cxx::__int_traits<_IndexType>::__max));
+ }
+
+ static constexpr bool
+ _M_is_always_exhaustive() noexcept
+ {
+ if constexpr (_S_rank <= 1)
+ return true;
+ else
+ return _S_static_padextent() != dynamic_extent
+ && _S_static_stride != dynamic_extent
+ && _S_static_padextent() == _S_static_stride;
+ }
+
+ constexpr bool
+ _M_is_exhaustive() const noexcept
+ {
+ if constexpr (_M_is_always_exhaustive())
+ return true;
+ else
+ return cmp_equal(_M_padextent(), _M_padstride());
+ }
+
+ constexpr static size_t
+ _S_static_padextent() noexcept
+ { return _Extents::static_extent(_LayoutTraits::_S_ext_idx); }
+
+ constexpr _IndexType
+ _M_padextent() const noexcept
+ { return _M_extents.extent(_LayoutTraits::_S_ext_idx); }
+
+ constexpr _IndexType
+ _M_calc_padstride() const noexcept
+ {
+ if constexpr (_S_static_stride != dynamic_extent)
+ return _S_static_stride;
+ else if constexpr (_PaddingValue != dynamic_extent)
+ return __least_multiple(_PaddingValue, _M_padextent());
+ else
+ return _M_padextent();
+ }
+
+ constexpr _IndexType
+ _M_padstride() const noexcept
+ { return _M_stride.extent(0); }
+
+ constexpr _IndexType
+ _M_required_span_size() const noexcept
+ {
+ if constexpr (_S_rank == 0)
+ return 1;
+ else if (__mdspan::__empty(_M_extents))
+ return 0;
+ else
+ {
+ size_t __stride = static_cast<size_t>(_M_padstride());
+ size_t __prod_rest = __mdspan::__fwd_prod(_M_extents,
+ _LayoutTraits::_S_unpad_begin, _LayoutTraits::_S_unpad_end);
+ size_t __delta = _M_padstride() - _M_padextent();
+ return static_cast<_IndexType>(__stride * __prod_rest - __delta);
+ }
+ }
+
+ template<typename _SamePaddedMapping>
+ constexpr bool
+ _M_equal(const _SamePaddedMapping& __other) const noexcept
+ {
+ return _M_extents == __other.extents()
+ && (_S_rank < 2
+ || cmp_equal(_M_stride.extent(0),
+ __other.stride(_LayoutTraits::_S_stride_idx)));
+ }
+
+ using _Stride = std::extents<_IndexType, _S_static_stride>;
+ [[no_unique_address]] _Stride _M_stride;
+ [[no_unique_address]] _Extents _M_extents;
+ };
+ }
+
+ template<size_t _PaddingValue>
+ template<typename _Extents>
+ class layout_left_padded<_PaddingValue>::mapping
+ {
+ public:
+ static constexpr size_t padding_value = _PaddingValue;
+
+ 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_padded<padding_value>;
+
+ private:
+ static constexpr size_t _S_rank = extents_type::rank();
+ using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
+ _Extents, __mdspan::_LeftPaddedLayoutTraits<_S_rank>>;
+ [[no_unique_address]] _PaddedStorage _M_storage;
+
+ consteval friend size_t
+ __mdspan::__get_static_stride<mapping>();
+
+ constexpr index_type
+ _M_extent(size_t __r) const noexcept
+ { return _M_storage._M_extents.extent(__r); }
+
+ constexpr index_type
+ _M_padstride() const noexcept
+ { return _M_storage._M_stride.extent(0); }
+
+ public:
+ constexpr
+ mapping() noexcept
+ { }
+
+ constexpr
+ mapping(const mapping&) noexcept = default;
+
+ constexpr
+ mapping(const extents_type& __exts)
+ : _M_storage(__exts)
+ { }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType>
+ constexpr
+ mapping(const extents_type& __exts, _OIndexType __pad)
+ : _M_storage(__exts,
+ __mdspan::__index_type_cast<index_type>(std::move(__pad)))
+ { }
+
+ template<typename _OExtents>
+ requires is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+ mapping(const layout_left::mapping<_OExtents>& __other)
+ : _M_storage(__other)
+ { }
+
+ template<typename _OExtents>
+ requires is_constructible_v<_OExtents, extents_type>
+ constexpr explicit(!(_OExtents::rank() == 0
+ && is_convertible_v<_OExtents, extents_type>))
+ mapping(const typename layout_stride::mapping<_OExtents>& __other)
+ : _M_storage(__other)
+ { __glibcxx_assert(*this == __other); }
+
+ template<typename _LeftPaddedMapping>
+ requires __mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
+ && is_constructible_v<extents_type,
+ typename _LeftPaddedMapping::extents_type>
+ constexpr explicit(
+ !is_convertible_v<typename _LeftPaddedMapping::extents_type,
+ extents_type>
+ || _S_rank > 1 && (padding_value != dynamic_extent
+ || _LeftPaddedMapping::padding_value == dynamic_extent))
+ mapping(const _LeftPaddedMapping& __other)
+ : _M_storage(layout_left{}, __other)
+ { }
+
+ template<typename _RightPaddedMapping>
+ requires (__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
+ || __mdspan::__mapping_of<layout_right, _RightPaddedMapping>)
+ && (_S_rank <= 1)
+ && is_constructible_v<extents_type,
+ typename _RightPaddedMapping::extents_type>
+ constexpr explicit(!is_convertible_v<
+ typename _RightPaddedMapping::extents_type, extents_type>)
+ mapping(const _RightPaddedMapping& __other) noexcept
+ : _M_storage(layout_right{}, __other)
+ { }
+
+ constexpr mapping&
+ operator=(const mapping&) noexcept = default;
+
+ constexpr const extents_type&
+ extents() const noexcept { return _M_storage._M_extents; }
+
+ constexpr array<index_type, _S_rank>
+ strides() const noexcept
+ {
+ array<index_type, _S_rank> __ret;
+ if constexpr (_S_rank > 0)
+ __ret[0] = 1;
+ if constexpr (_S_rank > 1)
+ __ret[1] = _M_padstride();
+ if constexpr (_S_rank > 2)
+ for(size_t __i = 2; __i < _S_rank; ++__i)
+ __ret[__i] = __ret[__i - 1] * _M_extent(__i - 1);
+ return __ret;
+ }
+
+ constexpr index_type
+ required_span_size() const noexcept
+ { return _M_storage._M_required_span_size(); }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4314. Missing move in mdspan layout mapping::operator()
+ template<__mdspan::__valid_index_type<index_type>... _Indices>
+ requires (sizeof...(_Indices) == _S_rank)
+ constexpr index_type
+ operator()(_Indices... __indices) const noexcept
+ {
+ return __mdspan::__linear_index_leftpad(
+ extents(), _M_storage._M_stride,
+ static_cast<index_type>(std::move(__indices))...);
+ }
+
+ static constexpr bool
+ is_always_exhaustive() noexcept
+ { return _PaddedStorage::_M_is_always_exhaustive(); }
+
+ constexpr bool
+ is_exhaustive() noexcept
+ { return _M_storage._M_is_exhaustive(); }
+
+ static constexpr bool
+ is_always_unique() noexcept { return true; }
+
+ static constexpr bool
+ is_unique() noexcept { return true; }
+
+ static constexpr bool
+ is_always_strided() noexcept { return true; }
+
+ static constexpr bool
+ is_strided() noexcept { return true; }
+
+ constexpr index_type
+ stride(rank_type __r) const noexcept
+ {
+ __glibcxx_assert(__r < _S_rank);
+ if (__r == 0)
+ return 1;
+ else
+ return static_cast<index_type>(
+ static_cast<size_t>(_M_padstride()) *
+ static_cast<size_t>(__mdspan::__fwd_prod(extents(), 1, __r)));
+ }
+
+ template<typename _LeftpadMapping>
+ requires(__mdspan::__is_left_padded_mapping<_LeftpadMapping>
+ && _LeftpadMapping::extents_type::rank() == _S_rank)
+ friend constexpr bool
+ operator==(const mapping& __self, const _LeftpadMapping& __other)
+ noexcept
+ { return __self._M_storage._M_equal(__other); }
+
+ private:
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
+ };
+
+ template<size_t _PaddingValue>
+ template<typename _Extents>
+ class layout_right_padded<_PaddingValue>::mapping {
+ public:
+ static constexpr size_t padding_value = _PaddingValue;
+ 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_padded<_PaddingValue>;
+
+ private:
+ static constexpr size_t _S_rank = extents_type::rank();
+ using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue,
+ _Extents, __mdspan::_RightPaddedLayoutTraits<_S_rank>>;
+ [[no_unique_address]] _PaddedStorage _M_storage;
+
+ consteval friend size_t
+ __mdspan::__get_static_stride<mapping>();
+
+ constexpr index_type
+ _M_extent(size_t __r) const noexcept
+ { return _M_storage._M_extents.extent(__r); }
+
+ constexpr index_type
+ _M_padstride() const noexcept
+ { return _M_storage._M_stride.extent(0); }
+
+ public:
+ constexpr
+ mapping() noexcept
+ { }
+
+ constexpr
+ mapping(const mapping&) noexcept = default;
+
+ constexpr
+ mapping(const extents_type& __exts)
+ : _M_storage(__exts)
+ { }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType>
+ constexpr
+ mapping(const extents_type& __exts, _OIndexType __pad)
+ : _M_storage(__exts,
+ __mdspan::__index_type_cast<index_type>(std::move(__pad)))
+ { }
+
+ template<typename _OExtents>
+ requires is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+ mapping(const layout_right::mapping<_OExtents>& __other)
+ : _M_storage(__other)
+ { }
+
+ template<typename _OExtents>
+ requires is_constructible_v<_OExtents, extents_type>
+ constexpr explicit(!(_OExtents::rank() == 0
+ && is_convertible_v<_OExtents, extents_type>))
+ mapping(const typename layout_stride::mapping<_OExtents>& __other)
+ : _M_storage(__other)
+ { __glibcxx_assert(*this == __other); }
+
+ template<typename _RightPaddedMapping>
+ requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
+ && is_constructible_v<extents_type,
+ typename _RightPaddedMapping::extents_type>
+ constexpr explicit(
+ !is_convertible_v<typename _RightPaddedMapping::extents_type,
+ extents_type>
+ || _S_rank > 1 && (padding_value != dynamic_extent
+ || _RightPaddedMapping::padding_value == dynamic_extent))
+ mapping(const _RightPaddedMapping& __other)
+ : _M_storage(layout_right{}, __other)
+ { }
+
+ template<typename _LeftPaddedMapping>
+ requires (__mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
+ || __mdspan::__mapping_of<layout_left, _LeftPaddedMapping>)
+ && (_S_rank <= 1)
+ && is_constructible_v<extents_type,
+ typename _LeftPaddedMapping::extents_type>
+ constexpr explicit(!is_convertible_v<
+ typename _LeftPaddedMapping::extents_type, extents_type>)
+ mapping(const _LeftPaddedMapping& __other) noexcept
+ : _M_storage(layout_left{}, __other)
+ { }
+
+ constexpr mapping& operator=(const mapping&) noexcept = default;
+
+ constexpr const extents_type&
+ extents() const noexcept { return _M_storage._M_extents; }
+
+ constexpr array<index_type, _S_rank>
+ strides() const noexcept
+ {
+ array<index_type, _S_rank> __ret;
+ if constexpr (_S_rank > 0)
+ __ret[_S_rank - 1] = 1;
+ if constexpr (_S_rank > 1)
+ __ret[_S_rank - 2] = _M_padstride();
+ if constexpr (_S_rank > 2)
+ for(size_t __i = _S_rank - 2; __i > 0; --__i)
+ __ret[__i - 1] = __ret[__i] * _M_extent(__i);
+ return __ret;
+ }
+
+ constexpr index_type
+ required_span_size() const noexcept
+ { return _M_storage._M_required_span_size(); }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4314. Missing move in mdspan layout mapping::operator()
+ template<__mdspan::__valid_index_type<index_type>... _Indices>
+ requires (sizeof...(_Indices) == _S_rank)
+ constexpr index_type
+ operator()(_Indices... __indices) const noexcept
+ {
+ return __mdspan::__linear_index_rightpad(
+ extents(), _M_storage._M_stride,
+ static_cast<index_type>(std::move(__indices))...);
+ }
+
+ static constexpr bool
+ is_always_exhaustive() noexcept
+ { return _PaddedStorage::_M_is_always_exhaustive(); }
+
+ constexpr bool
+ is_exhaustive() noexcept
+ { return _M_storage._M_is_exhaustive(); }
+
+ static constexpr bool
+ is_always_unique() noexcept { return true; }
+
+ static constexpr bool
+ is_unique() noexcept { return true; }
+
+ static constexpr bool
+ is_always_strided() noexcept { return true; }
+
+ static constexpr bool
+ is_strided() noexcept { return true; }
+
+ constexpr index_type
+ stride(rank_type __r) const noexcept
+ {
+ __glibcxx_assert(__r < _S_rank);
+ if constexpr (_S_rank <= 1)
+ return 1;
+ else if (__r == _S_rank - 1)
+ return 1;
+ else if (__r == _S_rank - 2)
+ return _M_padstride();
+ else
+ return static_cast<index_type>(
+ static_cast<size_t>(_M_padstride()) *
+ static_cast<size_t>(__mdspan::__fwd_prod(
+ extents(), __r + 1, _S_rank - 1)));
+ }
+
+ template<typename _RightPaddedMapping>
+ requires(__mdspan::__is_right_padded_mapping<_RightPaddedMapping>
+ && _RightPaddedMapping::extents_type::rank() == _S_rank)
+ friend constexpr bool
+ operator==(const mapping& __self, const _RightPaddedMapping& __other)
+ noexcept
+ { return __self._M_storage._M_equal(__other); }
+
+#if __glibcxx_submdspan
+ private:
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
+ };
+#endif // __glibcxx_padded_layouts
+
+ 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; }
+ };
+
+#ifdef __glibcxx_aligned_accessor
+ template<typename _ElementType, size_t _ByteAlignment>
+ struct aligned_accessor
+ {
+ static_assert(has_single_bit(_ByteAlignment),
+ "ByteAlignment must be a power of two");
+ static_assert(_ByteAlignment >= alignof(_ElementType));
+
+ using offset_policy = default_accessor<_ElementType>;
+ using element_type = _ElementType;
+ using reference = element_type&;
+ using data_handle_type = element_type*;
+
+ static constexpr size_t byte_alignment = _ByteAlignment;
+
+ constexpr
+ aligned_accessor() noexcept = default;
+
+ template<typename _OElementType, size_t _OByteAlignment>
+ requires (_OByteAlignment >= byte_alignment)
+ && is_convertible_v<_OElementType(*)[], element_type(*)[]>
+ constexpr
+ aligned_accessor(aligned_accessor<_OElementType, _OByteAlignment>)
+ noexcept
+ { }
+
+ template<typename _OElementType>
+ requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
+ constexpr explicit
+ aligned_accessor(default_accessor<_OElementType>) noexcept
+ { }
+
+ template<typename _OElementType>
+ requires is_convertible_v<element_type(*)[], _OElementType(*)[]>
+ constexpr
+ operator default_accessor<_OElementType>() const noexcept
+ { return {}; }
+
+ constexpr reference
+ access(data_handle_type __p, size_t __i) const noexcept
+ { return std::assume_aligned<byte_alignment>(__p)[__i]; }
+
+ constexpr typename offset_policy::data_handle_type
+ offset(data_handle_type __p, size_t __i) const noexcept
+ { return std::assume_aligned<byte_alignment>(__p) + __i; }
+ };
+#endif
+
+ namespace __mdspan
+ {
+ template<typename _Extents, typename _IndexType, size_t _Nm>
+ constexpr bool
+ __is_multi_index(const _Extents& __exts, span<_IndexType, _Nm> __indices)
+ {
+ static_assert(__exts.rank() == _Nm);
+ for (size_t __i = 0; __i < __exts.rank(); ++__i)
+ if (__indices[__i] >= __exts.extent(__i))
+ return false;
+ return true;
+ }
+ }
+
+ template<typename _ElementType, typename _Extents,
+ typename _LayoutPolicy = layout_right,
+ typename _AccessorPolicy = default_accessor<_ElementType>>
+ class mdspan
+ {
+ 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");
+ static_assert(__mdspan::__is_extents<_Extents>,
+ "Extents must be a specialization of std::extents");
+ static_assert(is_same_v<_ElementType,
+ typename _AccessorPolicy::element_type>);
+
+ public:
+ using extents_type = _Extents;
+ using layout_type = _LayoutPolicy;
+ using accessor_type = _AccessorPolicy;
+ using mapping_type = typename layout_type::template mapping<extents_type>;
+ using element_type = _ElementType;
+ using value_type = remove_cv_t<element_type>;
+ 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 data_handle_type = typename accessor_type::data_handle_type;
+ using reference = typename accessor_type::reference;
+
+ static constexpr rank_type
+ rank() noexcept { return extents_type::rank(); }
+
+ static constexpr rank_type
+ rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
+
+ static constexpr size_t
+ static_extent(rank_type __r) noexcept
+ { return extents_type::static_extent(__r); }
+
+ constexpr index_type
+ extent(rank_type __r) const noexcept { return extents().extent(__r); }
+
+ constexpr
+ mdspan()
+ requires (rank_dynamic() > 0)
+ && is_default_constructible_v<data_handle_type>
+ && is_default_constructible_v<mapping_type>
+ && is_default_constructible_v<accessor_type> = default;
+
+ constexpr
+ mdspan(const mdspan& __other) = default;
+
+ constexpr
+ mdspan(mdspan&& __other) = default;
+
+ template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
+ requires (sizeof...(_OIndexTypes) == rank()
+ || sizeof...(_OIndexTypes) == rank_dynamic())
+ && is_constructible_v<mapping_type, extents_type>
+ && is_default_constructible_v<accessor_type>
+ constexpr explicit
+ mdspan(data_handle_type __handle, _OIndexTypes... __exts)
+ : _M_accessor(),
+ _M_mapping(_Extents(static_cast<index_type>(std::move(__exts))...)),
+ _M_handle(std::move(__handle))
+ { }
+
+ template<typename _OIndexType, size_t _Nm>
+ requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+ && (_Nm == rank() || _Nm == rank_dynamic())
+ && is_constructible_v<mapping_type, extents_type>
+ && is_default_constructible_v<accessor_type>
+ constexpr explicit(_Nm != rank_dynamic())
+ mdspan(data_handle_type __handle, span<_OIndexType, _Nm> __exts)
+ : _M_accessor(), _M_mapping(extents_type(__exts)),
+ _M_handle(std::move(__handle))
+ { }
+
+ template<typename _OIndexType, size_t _Nm>
+ requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+ && (_Nm == rank() || _Nm == rank_dynamic())
+ && is_constructible_v<mapping_type, extents_type>
+ && is_default_constructible_v<accessor_type>
+ constexpr explicit(_Nm != rank_dynamic())
+ mdspan(data_handle_type __handle, const array<_OIndexType, _Nm>& __exts)
+ : _M_accessor(), _M_mapping(extents_type(__exts)),
+ _M_handle(std::move(__handle))
+ { }
+
+ constexpr
+ mdspan(data_handle_type __handle, const extents_type& __exts)
+ requires is_constructible_v<mapping_type, const extents_type&>
+ && is_default_constructible_v<accessor_type>
+ : _M_accessor(), _M_mapping(__exts), _M_handle(std::move(__handle))
+ { }
+
+ constexpr
+ mdspan(data_handle_type __handle, const mapping_type& __mapping)
+ requires is_default_constructible_v<accessor_type>
+ : _M_accessor(), _M_mapping(__mapping), _M_handle(std::move(__handle))
+ { }
+
+ constexpr
+ mdspan(data_handle_type __handle, const mapping_type& __mapping,
+ const accessor_type& __accessor)
+ : _M_accessor(__accessor), _M_mapping(__mapping),
+ _M_handle(std::move(__handle))
+ { }
+
+ template<typename _OElementType, typename _OExtents, typename _OLayout,
+ typename _OAccessor>
+ requires is_constructible_v<mapping_type,
+ const typename _OLayout::template mapping<_OExtents>&>
+ && is_constructible_v<accessor_type, const _OAccessor&>
+ constexpr explicit(!is_convertible_v<
+ const typename _OLayout::template mapping<_OExtents>&, mapping_type>
+ || !is_convertible_v<const _OAccessor&, accessor_type>)
+ mdspan(const mdspan<_OElementType, _OExtents, _OLayout, _OAccessor>&
+ __other)
+ : _M_accessor(__other.accessor()), _M_mapping(__other.mapping()),
+ _M_handle(__other.data_handle())
+ {
+ static_assert(is_constructible_v<data_handle_type,
+ const typename _OAccessor::data_handle_type&>);
+ static_assert(is_constructible_v<extents_type, _OExtents>);
+ }
+
+ constexpr mdspan&
+ operator=(const mdspan& __other) = default;
+
+ constexpr mdspan&
+ operator=(mdspan&& __other) = default;
+
+ template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
+ requires (sizeof...(_OIndexTypes) == rank())
+ constexpr reference
+ operator[](_OIndexTypes... __indices) const
+ {
+ auto __checked_call = [this](auto... __idxs) -> index_type
+ {
+ if constexpr (sizeof...(__idxs) > 0)
+ __glibcxx_assert(__mdspan::__is_multi_index(extents(),
+ span<const index_type, sizeof...(__idxs)>({__idxs...})));
+ return _M_mapping(__idxs...);
+ };
+
+ auto __index = __checked_call(
+ static_cast<index_type>(std::move(__indices))...);
+ return _M_accessor.access(_M_handle, __index);
+ }
+
+ template<typename _OIndexType>
+ requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+ constexpr reference
+ operator[](span<_OIndexType, rank()> __indices) const
+ {
+ auto __call = [&]<size_t... _Counts>(index_sequence<_Counts...>)
+ -> reference
+ { return (*this)[index_type(as_const(__indices[_Counts]))...]; };
+ return __call(make_index_sequence<rank()>());
+ }
+
+ template<typename _OIndexType>
+ requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+ constexpr reference
+ operator[](const array<_OIndexType, rank()>& __indices) const
+ { return (*this)[span<const _OIndexType, rank()>(__indices)]; }
+
+ constexpr size_type
+ size() const noexcept
+ {
+ __glibcxx_assert(cmp_less_equal(_M_mapping.required_span_size(),
+ __gnu_cxx::__int_traits<size_t>
+ ::__max));
+ return size_type(__mdspan::__size(extents()));
+ }
+
+ [[nodiscard]]
+ constexpr bool
+ empty() const noexcept
+ { return __mdspan::__empty(extents()); }
+
+ friend constexpr void
+ swap(mdspan& __x, mdspan& __y) noexcept
+ {
+ using std::swap;
+ swap(__x._M_mapping, __y._M_mapping);
+ swap(__x._M_accessor, __y._M_accessor);
+ swap(__x._M_handle, __y._M_handle);
+ }
+
+ constexpr const extents_type&
+ extents() const noexcept { return _M_mapping.extents(); }
+
+ constexpr const data_handle_type&
+ data_handle() const noexcept { return _M_handle; }
+
+ constexpr const mapping_type&
+ mapping() const noexcept { return _M_mapping; }
+
+ constexpr const accessor_type&
+ accessor() const noexcept { return _M_accessor; }
+
+ // Strengthened noexcept for all `is_*` methods.
+
+ static constexpr bool
+ is_always_unique() noexcept(noexcept(mapping_type::is_always_unique()))
+ { return mapping_type::is_always_unique(); }
+
+ static constexpr bool
+ is_always_exhaustive()
+ noexcept(noexcept(mapping_type::is_always_exhaustive()))
+ { return mapping_type::is_always_exhaustive(); }
+
+ static constexpr bool
+ is_always_strided()
+ noexcept(noexcept(mapping_type::is_always_strided()))
+ { return mapping_type::is_always_strided(); }
+
+ constexpr bool
+ is_unique() const noexcept(noexcept(_M_mapping.is_unique()))
+ { return _M_mapping.is_unique(); }
+
+ constexpr bool
+ is_exhaustive() const noexcept(noexcept(_M_mapping.is_exhaustive()))
+ { return _M_mapping.is_exhaustive(); }
+
+ constexpr bool
+ is_strided() const noexcept(noexcept(_M_mapping.is_strided()))
+ { return _M_mapping.is_strided(); }
+
+ constexpr index_type
+ stride(rank_type __r) const { return _M_mapping.stride(__r); }
+
+ private:
+ [[no_unique_address]] accessor_type _M_accessor = accessor_type();
+ [[no_unique_address]] mapping_type _M_mapping = mapping_type();
+ [[no_unique_address]] data_handle_type _M_handle = data_handle_type();
+ };
+
+ template<typename _CArray>
+ requires is_array_v<_CArray> && (rank_v<_CArray> == 1)
+ mdspan(_CArray&)
+ -> mdspan<remove_all_extents_t<_CArray>,
+ extents<size_t, extent_v<_CArray, 0>>>;
+
+ template<typename _Pointer>
+ requires is_pointer_v<remove_reference_t<_Pointer>>
+ mdspan(_Pointer&&)
+ -> mdspan<remove_pointer_t<remove_reference_t<_Pointer>>, extents<size_t>>;
+
+ template<typename _ElementType, typename... _Integrals>
+ requires (is_convertible_v<_Integrals, size_t> && ...)
+ && (sizeof...(_Integrals) > 0)
+ explicit mdspan(_ElementType*, _Integrals...)
+ -> mdspan<_ElementType,
+ extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>;
+
+ template<typename _ElementType, typename _OIndexType, size_t _Nm>
+ mdspan(_ElementType*, span<_OIndexType, _Nm>)
+ -> mdspan<_ElementType, dextents<size_t, _Nm>>;
+
+ template<typename _ElementType, typename _OIndexType, size_t _Nm>
+ mdspan(_ElementType*, const array<_OIndexType, _Nm>&)
+ -> mdspan<_ElementType, dextents<size_t, _Nm>>;
+
+ template<typename _ElementType, typename _IndexType, size_t... _ExtentsPack>
+ mdspan(_ElementType*, const extents<_IndexType, _ExtentsPack...>&)
+ -> mdspan<_ElementType, extents<_IndexType, _ExtentsPack...>>;
+
+ template<typename _ElementType, typename _MappingType>
+ mdspan(_ElementType*, const _MappingType&)
+ -> mdspan<_ElementType, typename _MappingType::extents_type,
+ typename _MappingType::layout_type>;
+
+ template<typename _MappingType, typename _AccessorType>
+ mdspan(const typename _AccessorType::data_handle_type&, const _MappingType&,
+ const _AccessorType&)
+ -> mdspan<typename _AccessorType::element_type,
+ typename _MappingType::extents_type,
+ typename _MappingType::layout_type, _AccessorType>;
+
+#if __glibcxx_submdspan
+ namespace __mdspan
+ {
+ template<typename _IndexType, typename _Slice>
+ constexpr auto
+ __canonical_index(_Slice&& __slice)
+ {
+ if constexpr (__detail::__integral_constant_like<_Slice>)
+ {
+ static_assert(__is_representable_integer<_IndexType>(_Slice::value));
+ static_assert(_Slice::value >= 0);
+ return std::cw<_IndexType(_Slice::value)>;
+ }
+ else
+ return __mdspan::__index_type_cast<_IndexType>(std::move(__slice));
+ }
+
+ template<typename _IndexType, typename _Slice>
+ constexpr auto
+ __slice_cast(_Slice&& __slice)
+ {
+ using _SliceType = remove_cvref_t<_Slice>;
+ if constexpr (is_convertible_v<_SliceType, full_extent_t>)
+ return static_cast<full_extent_t>(std::move(__slice));
+ else if constexpr (is_convertible_v<_SliceType, _IndexType>)
+ return __mdspan::__canonical_index<_IndexType>(std::move(__slice));
+ else if constexpr (__is_strided_slice<_SliceType>)
+ {
+ auto __extent
+ = __mdspan::__canonical_index<_IndexType>(std::move(__slice.extent));
+ auto __offset
+ = __mdspan::__canonical_index<_IndexType>(std::move(__slice.offset));
+ if constexpr (is_same_v<decltype(__extent),
+ constant_wrapper<_IndexType(0)>>)
+ return strided_slice{
+ .offset = __offset,
+ .extent = __extent,
+ .stride = cw<_IndexType(1)>
+ };
+ else
+ return strided_slice{
+ .offset = __offset,
+ .extent = __extent,
+ .stride
+ = __mdspan::__canonical_index<_IndexType>(std::move(__slice.stride))
+ };
+ }
+ else
+ {
+ auto [__sbegin, __send] = std::move(__slice);
+ auto __offset
+ = __mdspan::__canonical_index<_IndexType>(std::move(__sbegin));
+ auto __end
+ = __mdspan::__canonical_index<_IndexType>(std::move(__send));
+ return strided_slice{
+ .offset = __offset,
+ .extent = __mdspan::__canonical_index<_IndexType>(__end - __offset),
+ .stride = cw<_IndexType(1)>
+ };
+ }
+ }
+
+ template<typename _IndexType, size_t _Extent, typename _OIndexType>
+ constexpr void
+ __check_valid_index(const extents<_IndexType, _Extent>& __ext,
+ const _OIndexType& __idx)
+ {
+ if constexpr (__is_constant_wrapper<_OIndexType>
+ && _Extent != dynamic_extent)
+ {
+ static_assert(_OIndexType::value >= 0);
+ static_assert(std::cmp_less_equal(_OIndexType::value, _Extent));
+ }
+ else
+ __glibcxx_assert(__idx <= __ext.extent(0));
+}
+
+ template<typename _IndexType, size_t _Extent, typename _Slice>
+ constexpr void
+ __check_valid_slice(const extents<_IndexType, _Extent>& __ext,
+ const _Slice& __slice)
+ {
+ if constexpr (__is_strided_slice<_Slice>)
+ {
+ // DEVIATION: For empty slices, P3663r3 does not allow us to check
+ // that this is less than or equal to the k-th extent (at runtime).
+ // We're only allowed to check if __slice.offset, __slice.extent
+ // are constant wrappers and __ext is a static extent.
+ __mdspan::__check_valid_index(__ext, __slice.offset);
+ __mdspan::__check_valid_index(__ext, __slice.extent);
+
+ if constexpr (__is_constant_wrapper<typename _Slice::extent_type>
+ && __is_constant_wrapper<typename _Slice::stride_type>)
+ static_assert(_Slice::stride_type::value > 0);
+ else
+ __glibcxx_assert(__slice.extent == 0 || __slice.stride > 0);
+
+ if constexpr (__is_constant_wrapper<typename _Slice::offset_type>
+ && __is_constant_wrapper<typename _Slice::extent_type>
+ && _Extent != dynamic_extent)
+ static_assert(std::cmp_greater_equal(
+ _Extent - _Slice::offset_type::value,
+ _Slice::extent_type::value));
+ else
+ __glibcxx_assert(__ext.extent(0) - __slice.offset
+ >= __slice.extent);
+ }
+ else if constexpr (__is_constant_wrapper<_Slice>
+ && _Extent != dynamic_extent)
+ static_assert(std::cmp_less(_Slice::value, _Extent));
+ else if constexpr (convertible_to<_Slice, _IndexType>)
+ __glibcxx_assert(__slice < __ext.extent(0));
+ }
+
+ template<typename _Extents, typename... _Slices>
+ constexpr void
+ __check_valid_slices(const _Extents& __exts, const _Slices&... __slices)
+ {
+ constexpr auto __rank = _Extents::rank();
+ auto __impl = [&]<size_t... _Is>(index_sequence<_Is...>)
+ {
+ ((__mdspan::__check_valid_slice(__extract_extent<_Is>(__exts),
+ __slices...[_Is])),...);
+ };
+ __impl(make_index_sequence<__rank>());
+ }
+
+ template<typename _Slice>
+ using __full_extent_t = std::full_extent_t;
+
+ // Enables ADL-only calls from submdspan.
+ void submdspan_mapping() = delete;
+
+ template<typename _Mapping, typename... _Slices>
+ concept __sliceable_mapping = requires(const _Mapping __m, _Slices... __slices)
+ {
+ { submdspan_mapping(__m, __slices...) } -> __submdspan_mapping_result;
+ };
+
+ template<typename _Mapping, typename... _Slices>
+ constexpr auto
+ __submapping(const _Mapping& __mapping, _Slices... __slices)
+ {
+ __mdspan::__check_valid_slices(__mapping.extents(), __slices...);
+ return submdspan_mapping(__mapping, __slices...);
+ }
+ }
+
+ template<typename _IndexType, size_t... _Extents, typename... _RawSlices>
+ requires (sizeof...(_RawSlices) == sizeof...(_Extents))
+ constexpr auto
+ submdspan_extents(const extents<_IndexType, _Extents...>& __exts,
+ _RawSlices... __raw_slices)
+ {
+ auto __impl = [&__exts](auto... __slices)
+ {
+ __mdspan::__check_valid_slices(__exts, __slices...);
+ return __mdspan::__subextents(__exts, __slices...);
+ };
+ return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
+ }
+
+ template<typename _IndexType, size_t... _Extents, typename... _RawSlices>
+ requires (sizeof...(_Extents) == sizeof...(_RawSlices))
+ constexpr auto
+ submdspan_canonicalize_slices(const extents<_IndexType, _Extents...>& __exts,
+ _RawSlices... __raw_slices)
+ {
+ auto __impl = [&__exts](auto... __slices)
+ {
+ __mdspan::__check_valid_slices(__exts, __slices...);
+ return std::make_tuple(__slices...);
+ };
+ return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
+ }
+
+ template<typename _ElementType, typename _Extents, typename _Layout,
+ typename _Accessor, typename... _RawSlices>
+ requires (sizeof...(_RawSlices) == _Extents::rank()
+ && __mdspan::__sliceable_mapping<typename _Layout::mapping<_Extents>,
+ __mdspan::__full_extent_t<_RawSlices>...>)
+ constexpr auto
+ submdspan(
+ const mdspan<_ElementType, _Extents, _Layout, _Accessor>& __md,
+ _RawSlices... __raw_slices)
+ {
+ using _IndexType = typename _Extents::index_type;
+ auto [__mapping, __offset] = __mdspan::__submapping(
+ __md.mapping(), __mdspan::__slice_cast<_IndexType>(__raw_slices)...);
+ return std::mdspan(
+ __md.accessor().offset(__md.data_handle(), __offset),
+ std::move(__mapping),
+ typename _Accessor::offset_policy(__md.accessor()));
+ }
+#endif // __glibcxx_submdspan
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+#endif
+#endif
diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory
index 99f542d..9763760 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,16 +109,21 @@
#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_is_sufficiently_aligned
#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
#define __glibcxx_want_shared_ptr_weak_type
#define __glibcxx_want_smart_ptr_for_overwrite
+#define __glibcxx_want_start_lifetime_as
#define __glibcxx_want_to_address
#define __glibcxx_want_transparent_operators
+#define __glibcxx_want_smart_ptr_owner_equality
#include <bits/version.h>
#if __cplusplus >= 201103L && __cplusplus <= 202002L && _GLIBCXX_HOSTED
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index b3f89c0..d4fc4c6 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -179,31 +179,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_try_lock_until(const chrono::time_point<chrono::system_clock,
_Duration>& __atime)
{
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
-
- __gthread_time_t __ts = {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
-
+ __gthread_time_t __ts = chrono::__to_timeout_gthread_time_t(__atime);
return static_cast<_Derived*>(this)->_M_timedlock(__ts);
}
-#ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
+#if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
template<typename _Duration>
bool
_M_try_lock_until(const chrono::time_point<chrono::steady_clock,
_Duration>& __atime)
{
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
-
- __gthread_time_t __ts = {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
-
+ __gthread_time_t __ts = chrono::__to_timeout_gthread_time_t(__atime);
return static_cast<_Derived*>(this)->_M_clocklock(CLOCK_MONOTONIC,
__ts);
}
@@ -377,7 +363,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_timedlock(const __gthread_time_t& __ts)
{ return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
-#ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
+#if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
bool
_M_clocklock(clockid_t __clockid, const __gthread_time_t& __ts)
{ return !pthread_mutex_clocklock(&_M_mutex, __clockid, &__ts); }
@@ -733,7 +719,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..8b9fa92 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)
{
@@ -771,6 +777,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
# define _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL 1
#endif
+ template<typename _Tp>
+ inline constexpr bool __is_valid_contained_type_for_optional =
+ (
+#if __cpp_lib_optional >= 202506L
+ is_lvalue_reference_v<_Tp> ||
+#endif
+ (is_object_v<_Tp> && is_destructible_v<_Tp> && !is_array_v<_Tp>)
+ )
+ && !is_same_v<remove_cv_t<remove_reference_t<_Tp>>, nullopt_t>
+ && !is_same_v<remove_cv_t<remove_reference_t<_Tp>>, in_place_t>;
+
/**
* @brief Class template for optional values.
*/
@@ -789,9 +806,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Unique tag type.
optional<_Tp>>
{
- static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>);
- static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>);
- static_assert(is_object_v<_Tp> && !is_array_v<_Tp>);
+ static_assert(__is_valid_contained_type_for_optional<_Tp>);
private:
using _Base = _Optional_base<_Tp>;
@@ -858,6 +873,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 { }
@@ -884,7 +903,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
{
if (__t)
- emplace(__t._M_get());
+ emplace(__t._M_fwd());
}
template<typename _Up>
@@ -896,7 +915,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept(is_nothrow_constructible_v<_Tp, _Up>)
{
if (__t)
- emplace(std::move(__t._M_get()));
+ emplace(std::move(__t)._M_fwd());
}
template<typename... _Args>
@@ -946,7 +965,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
{
if (__t)
- emplace(__t._M_get());
+ emplace(__t._M_fwd());
}
template<typename _Up,
@@ -959,7 +978,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
{
if (__t)
- emplace(__t._M_get());
+ emplace(__t._M_fwd());
}
template<typename _Up,
@@ -972,7 +991,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept(is_nothrow_constructible_v<_Tp, _Up>)
{
if (__t)
- emplace(std::move(__t._M_get()));
+ emplace(std::move(__t)._M_fwd());
}
template<typename _Up,
@@ -985,7 +1004,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept(is_nothrow_constructible_v<_Tp, _Up>)
{
if (__t)
- emplace(std::move(__t._M_get()));
+ emplace(std::move(__t)._M_fwd());
}
template<typename... _Args,
@@ -1064,9 +1083,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__u)
{
if (this->_M_is_engaged())
- this->_M_get() = __u._M_get();
+ this->_M_get() = __u._M_fwd();
else
- this->_M_construct(__u._M_get());
+ this->_M_construct(__u._M_fwd());
}
else
{
@@ -1098,9 +1117,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__u)
{
if (this->_M_is_engaged())
- this->_M_get() = std::move(__u._M_get());
+ this->_M_get() = std::move(__u)._M_fwd();
else
- this->_M_construct(std::move(__u._M_get()));
+ this->_M_construct(std::move(__u)._M_fwd());
}
else
{
@@ -1158,6 +1177,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
@@ -1239,30 +1285,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_bad_optional_access();
}
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4406. value_or return statement is inconsistent with Mandates
template<typename _Up = remove_cv_t<_Tp>>
- constexpr _Tp
+ constexpr remove_cv_t<_Tp>
value_or(_Up&& __u) const&
{
- static_assert(is_copy_constructible_v<_Tp>);
- static_assert(is_convertible_v<_Up&&, _Tp>);
+ using _Xp = remove_cv_t<_Tp>;
+ static_assert(is_convertible_v<const _Tp&, _Xp>);
+ static_assert(is_convertible_v<_Up, _Xp>);
if (this->_M_is_engaged())
return this->_M_get();
- else
- return static_cast<_Tp>(std::forward<_Up>(__u));
+ return std::forward<_Up>(__u);
}
template<typename _Up = remove_cv_t<_Tp>>
- constexpr _Tp
+ constexpr remove_cv_t<_Tp>
value_or(_Up&& __u) &&
{
- static_assert(is_move_constructible_v<_Tp>);
- static_assert(is_convertible_v<_Up&&, _Tp>);
+ using _Xp = remove_cv_t<_Tp>;
+ static_assert(is_convertible_v<_Tp, _Xp>);
+ static_assert(is_convertible_v<_Up, _Xp>);
if (this->_M_is_engaged())
return std::move(this->_M_get());
- else
- return static_cast<_Tp>(std::forward<_Up>(__u));
+ return std::forward<_Up>(__u);
}
#if __cpp_lib_optional >= 202110L // C++23
@@ -1273,7 +1321,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
and_then(_Fn&& __f) &
{
using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp&>>;
- static_assert(__is_optional_v<remove_cvref_t<_Up>>,
+ static_assert(__is_optional_v<_Up>,
"the function passed to std::optional<T>::and_then "
"must return a std::optional");
if (has_value())
@@ -1301,7 +1349,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
and_then(_Fn&& __f) &&
{
using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp>>;
- static_assert(__is_optional_v<remove_cvref_t<_Up>>,
+ static_assert(__is_optional_v<_Up>,
"the function passed to std::optional<T>::and_then "
"must return a std::optional");
if (has_value())
@@ -1315,7 +1363,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
and_then(_Fn&& __f) const &&
{
using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp>>;
- static_assert(__is_optional_v<remove_cvref_t<_Up>>,
+ static_assert(__is_optional_v<_Up>,
"the function passed to std::optional<T>::and_then "
"must return a std::optional");
if (has_value())
@@ -1404,6 +1452,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
using _Base::_M_get;
+ [[__gnu__::__always_inline__]]
+ constexpr _Tp&
+ _M_fwd() & noexcept
+ { return _M_get(); }
+
+ [[__gnu__::__always_inline__]]
+ constexpr _Tp&&
+ _M_fwd() && noexcept
+ { return std::move(_M_get()); }
+
+ [[__gnu__::__always_inline__]]
+ constexpr const _Tp&
+ _M_fwd() const& noexcept
+ { return _M_get(); }
+
+ [[__gnu__::__always_inline__]]
+ constexpr const _Tp&&
+ _M_fwd() const&& noexcept
+ { return std::move(_M_get()); }
+
template<typename _Up> friend class optional;
#if __cpp_lib_optional >= 202110L // C++23
@@ -1416,6 +1484,337 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
};
+#if __cpp_lib_optional >= 202506L // C++26
+ template<typename _Tp>
+ class optional<_Tp&>;
+
+ template<typename _Tp>
+ constexpr bool __is_optional_ref_v = false;
+
+ template<typename _Tp>
+ constexpr bool __is_optional_ref_v<optional<_Tp&>> = true;
+
+ template<typename _Tp>
+ struct __optional_ref_base
+ {};
+
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ template<typename _Tp>
+ struct __optional_ref_base<_Tp[]>
+ {};
+
+ template<typename _Tp>
+ requires is_object_v<_Tp>
+ struct __optional_ref_base<_Tp>
+ {
+ using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional<_Tp&>>;
+ };
+#endif // __cpp_lib_optional_range_support
+
+ template<typename _Tp>
+ class optional<_Tp&> : public __optional_ref_base<_Tp>
+ {
+ static_assert(__is_valid_contained_type_for_optional<_Tp&>);
+
+ public:
+ using value_type = _Tp;
+
+ // Constructors.
+ constexpr optional() noexcept = default;
+ constexpr optional(nullopt_t) noexcept : optional() {}
+ constexpr optional(const optional&) noexcept = default;
+
+ template<typename _Arg>
+ requires is_constructible_v<_Tp&, _Arg>
+ && (!reference_constructs_from_temporary_v<_Tp&, _Arg>)
+ explicit constexpr
+ optional(in_place_t, _Arg&& __arg)
+ {
+ __convert_ref_init_val(std::forward<_Arg>(__arg));
+ }
+
+ template<typename _Up>
+ requires (!is_same_v<remove_cvref_t<_Up>, optional>)
+ && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
+ && is_constructible_v<_Tp&, _Up>
+ && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
+ explicit(!is_convertible_v<_Up, _Tp&>)
+ constexpr
+ optional(_Up&& __u)
+ noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
+ {
+ __convert_ref_init_val(std::forward<_Up>(__u));
+ }
+
+ template<typename _Up>
+ requires (!is_same_v<remove_cvref_t<_Up>, optional>)
+ && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
+ && is_constructible_v<_Tp&, _Up>
+ && reference_constructs_from_temporary_v<_Tp&, _Up>
+ explicit(!is_convertible_v<_Up, _Tp&>)
+ constexpr
+ optional(_Up&& __u) = delete;
+
+ // optional<U> &
+ template<typename _Up>
+ requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
+ && (!is_same_v<_Tp&, _Up>)
+ && is_constructible_v<_Tp&, _Up&>
+ && (!reference_constructs_from_temporary_v<_Tp&, _Up&>)
+ explicit(!is_convertible_v<_Up&, _Tp&>)
+ constexpr
+ optional(optional<_Up>& __rhs)
+ noexcept(is_nothrow_constructible_v<_Tp&, _Up&>)
+ {
+ if (__rhs)
+ __convert_ref_init_val(__rhs._M_fwd());
+ }
+
+ template<typename _Up>
+ requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
+ && (!is_same_v<_Tp&, _Up>)
+ && is_constructible_v<_Tp&, _Up&>
+ && reference_constructs_from_temporary_v<_Tp&, _Up&>
+ explicit(!is_convertible_v<_Up&, _Tp&>)
+ constexpr
+ optional(optional<_Up>& __rhs) = delete;
+
+ // const optional<U>&
+ template<typename _Up>
+ requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
+ && (!is_same_v<_Tp&, _Up>)
+ && is_constructible_v<_Tp&, const _Up&>
+ && (!reference_constructs_from_temporary_v<_Tp&, const _Up&>)
+ explicit(!is_convertible_v<const _Up&, _Tp&>)
+ constexpr
+ optional(const optional<_Up>& __rhs)
+ noexcept(is_nothrow_constructible_v<_Tp&, _Up&>)
+ {
+ if (__rhs)
+ __convert_ref_init_val(__rhs._M_fwd());
+ }
+
+ template<typename _Up>
+ requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
+ && (!is_same_v<_Tp&, _Up>)
+ && is_constructible_v<_Tp&, const _Up&>
+ && reference_constructs_from_temporary_v<_Tp&, const _Up&>
+ explicit(!is_convertible_v<const _Up&, _Tp&>)
+ constexpr
+ optional(const optional<_Up>& __rhs) = delete;
+
+ // optional<U>&&
+ template<typename _Up>
+ requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
+ && (!is_same_v<_Tp&, _Up>)
+ && is_constructible_v<_Tp&, _Up>
+ && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
+ explicit(!is_convertible_v<_Up, _Tp&>)
+ constexpr
+ optional(optional<_Up>&& __rhs)
+ noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
+ {
+ if (__rhs)
+ __convert_ref_init_val(std::move(__rhs)._M_fwd());
+ }
+
+ template<typename _Up>
+ requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
+ && (!is_same_v<_Tp&, _Up>)
+ && is_constructible_v<_Tp&, _Up>
+ && reference_constructs_from_temporary_v<_Tp&, _Up>
+ explicit(!is_convertible_v<_Up, _Tp&>)
+ constexpr
+ optional(optional<_Up>&& __rhs) = delete;
+
+ // const optional<U>&&
+ template<typename _Up>
+ requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
+ && (!is_same_v<_Tp&, _Up>)
+ && is_constructible_v<_Tp&, const _Up>
+ && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
+ explicit(!is_convertible_v<const _Up, _Tp&>)
+ constexpr
+ optional(const optional<_Up>&& __rhs)
+ noexcept(is_nothrow_constructible_v<_Tp&, const _Up>)
+ {
+ if (__rhs)
+ __convert_ref_init_val(std::move(__rhs)._M_fwd());
+ }
+
+ template<typename _Up>
+ requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
+ && (!is_same_v<_Tp&, _Up>)
+ && is_constructible_v<_Tp&, const _Up>
+ && reference_constructs_from_temporary_v<_Tp&, const _Up>
+ explicit(!is_convertible_v<const _Up, _Tp&>)
+ constexpr
+ optional(const optional<_Up>&& __rhs) = delete;
+
+ constexpr ~optional() = default;
+
+ // Assignment.
+ constexpr optional& operator=(nullopt_t) noexcept
+ {
+ _M_val = nullptr;
+ return *this;
+ }
+
+ constexpr optional& operator=(const optional&) noexcept = default;
+
+ template<typename _Up>
+ requires is_constructible_v<_Tp&, _Up>
+ && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
+ constexpr _Tp&
+ emplace(_Up&& __u)
+ noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
+ {
+ __convert_ref_init_val(std::forward<_Up>(__u));
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4300. Missing Returns: element in optional<T&>::emplace
+ return *_M_val;
+ }
+
+ // Swap.
+ constexpr void swap(optional& __rhs) noexcept
+ { std::swap(_M_val, __rhs._M_val); }
+
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ // Iterator support.
+ constexpr auto begin() const noexcept
+ requires is_object_v<_Tp> && (!is_unbounded_array_v<_Tp>)
+ { return __gnu_cxx::__normal_iterator<_Tp*, optional>(_M_val); }
+
+ constexpr auto end() const noexcept
+ requires is_object_v<_Tp> && (!is_unbounded_array_v<_Tp>)
+ { return begin() + has_value(); }
+#endif // __cpp_lib_optional_range_support
+
+ // Observers.
+ constexpr _Tp* operator->() const noexcept
+ {
+ __glibcxx_assert(_M_val); // hardened precondition
+ return _M_val;
+ }
+
+ constexpr _Tp& operator*() const noexcept
+ {
+ __glibcxx_assert(_M_val); // hardened precondition
+ return *_M_val;
+ }
+
+ constexpr explicit operator bool() const noexcept
+ {
+ return _M_val;
+ }
+
+ constexpr bool has_value() const noexcept
+ {
+ return _M_val;
+ }
+
+ constexpr _Tp& value() const
+ {
+ if (_M_val)
+ return *_M_val;
+ __throw_bad_optional_access();
+ }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4304. std::optional<NonReturnable&> is ill-formed due to value_or
+ template<typename _Up = remove_cv_t<_Tp>>
+ requires is_object_v<_Tp> && (!is_array_v<_Tp>)
+ constexpr decay_t<_Tp>
+ value_or(_Up&& __u) const
+ {
+ using _Xp = remove_cv_t<_Tp>;
+ static_assert(is_convertible_v<_Tp&, _Xp>);
+ static_assert(is_convertible_v<_Up, _Xp>);
+ if (_M_val)
+ return *_M_val;
+ return std::forward<_Up>(__u);
+ }
+
+ // Monadic operations.
+ template<typename _Fn>
+ constexpr auto
+ and_then(_Fn&& __f) const
+ {
+ using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp&>>;
+ static_assert(__is_optional_v<_Up>,
+ "the function passed to std::optional<T&>::and_then "
+ "must return a std::optional");
+ if (has_value())
+ return std::__invoke(std::forward<_Fn>(__f), *_M_val);
+ else
+ return _Up();
+ }
+
+ template<typename _Fn>
+ constexpr
+ optional<remove_cv_t<invoke_result_t<_Fn, _Tp&>>>
+ transform(_Fn&& __f) const
+ {
+ using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp&>>;
+ if (has_value())
+ return optional<_Up>(_Optional_func<_Fn>{__f}, *_M_val);
+ else
+ return optional<_Up>();
+ }
+
+ template<typename _Fn>
+ requires invocable<_Fn>
+ constexpr
+ optional
+ or_else(_Fn&& __f) const
+ {
+ static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Fn>>, optional>,
+ "the function passed to std::optional<T&>::or_else "
+ "must return a std::optional<T&>");
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4367. Improve optional<T&>::or_else
+ if (has_value())
+ return *this;
+ else
+ return std::forward<_Fn>(__f)();
+ }
+
+ // Modifiers.
+ constexpr void reset() noexcept
+ {
+ _M_val = nullptr;
+ }
+
+ private:
+ _Tp *_M_val = nullptr;
+
+ [[__gnu__::__always_inline__]]
+ constexpr _Tp&
+ _M_fwd() const noexcept
+ { return *_M_val; }
+
+ template<typename _Up> friend class optional;
+
+ template<typename _Up>
+ constexpr
+ void
+ __convert_ref_init_val(_Up&& __u)
+ noexcept
+ {
+ _Tp& __r(std::forward<_Up>(__u));
+ _M_val = std::addressof(__r);
+ }
+
+ template<typename _Fn, typename _Value>
+ explicit constexpr
+ optional(_Optional_func<_Fn> __f, _Value&& __v)
+ {
+ _Tp& __r = std::__invoke(std::forward<_Fn>(__f._M_f), std::forward<_Value>(__v));
+ _M_val = std::addressof(__r);
+ }
+ };
+#endif // __cpp_lib_optional >= 202506L
+
template<typename _Tp>
using __optional_relop_t =
enable_if_t<is_convertible_v<_Tp, bool>, bool>;
@@ -1456,8 +1855,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
-> __optional_eq_t<_Tp, _Up>
{
- return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
- && (!__lhs || *__lhs == *__rhs);
+ if (__lhs.has_value() != __rhs.has_value())
+ return false;
+ if (!__lhs.has_value())
+ return true;
+ return *__lhs == *__rhs;
}
template<typename _Tp, typename _Up>
@@ -1465,8 +1867,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
-> __optional_ne_t<_Tp, _Up>
{
- return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
- || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
+ if (__lhs.has_value() != __rhs.has_value())
+ return true;
+ if (!__lhs.has_value())
+ return false;
+ return *__lhs != *__rhs;
}
template<typename _Tp, typename _Up>
@@ -1474,7 +1879,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
-> __optional_lt_t<_Tp, _Up>
{
- return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
+ if (!__rhs.has_value())
+ return false;
+ if (!__lhs.has_value())
+ return true;
+ return *__lhs < *__rhs;
}
template<typename _Tp, typename _Up>
@@ -1482,7 +1891,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
-> __optional_gt_t<_Tp, _Up>
{
- return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
+ if (!__lhs.has_value())
+ return false;
+ if (!__rhs.has_value())
+ return true;
+ return *__lhs > *__rhs;
}
template<typename _Tp, typename _Up>
@@ -1490,7 +1903,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
-> __optional_le_t<_Tp, _Up>
{
- return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
+ if (!__lhs.has_value())
+ return true;
+ if (!__rhs.has_value())
+ return false;
+ return *__lhs <= *__rhs;
}
template<typename _Tp, typename _Up>
@@ -1498,7 +1915,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
-> __optional_ge_t<_Tp, _Up>
{
- return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
+ if (!__rhs.has_value())
+ return true;
+ if (!__lhs.has_value())
+ return false;
+ return *__lhs >= *__rhs;
}
#ifdef __cpp_lib_three_way_comparison
@@ -1595,84 +2016,132 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr auto
operator== [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
-> __optional_eq_t<_Tp, _Up>
- { return __lhs && *__lhs == __rhs; }
+ {
+ if (__lhs.has_value())
+ return *__lhs == __rhs;
+ return false;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Tp)
constexpr auto
operator== [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
-> __optional_eq_t<_Tp, _Up>
- { return __rhs && __lhs == *__rhs; }
+ {
+ if (__rhs.has_value())
+ return __lhs == *__rhs;
+ return false;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Up)
constexpr auto
operator!= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
-> __optional_ne_t<_Tp, _Up>
- { return !__lhs || *__lhs != __rhs; }
+ {
+ if (__lhs.has_value())
+ return *__lhs != __rhs;
+ return true;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Tp)
constexpr auto
operator!= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
-> __optional_ne_t<_Tp, _Up>
- { return !__rhs || __lhs != *__rhs; }
+ {
+ if (__rhs.has_value())
+ return __lhs != *__rhs;
+ return true;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Up)
constexpr auto
operator< [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
-> __optional_lt_t<_Tp, _Up>
- { return !__lhs || *__lhs < __rhs; }
+ {
+ if (__lhs.has_value())
+ return *__lhs < __rhs;
+ return true;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Tp)
constexpr auto
operator< [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
-> __optional_lt_t<_Tp, _Up>
- { return __rhs && __lhs < *__rhs; }
+ {
+ if (__rhs.has_value())
+ return __lhs < *__rhs;
+ return false;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Up)
constexpr auto
operator> [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
-> __optional_gt_t<_Tp, _Up>
- { return __lhs && *__lhs > __rhs; }
+ {
+ if (__lhs.has_value())
+ return *__lhs > __rhs;
+ return false;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Tp)
constexpr auto
operator> [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
-> __optional_gt_t<_Tp, _Up>
- { return !__rhs || __lhs > *__rhs; }
+ {
+ if (__rhs.has_value())
+ return __lhs > *__rhs;
+ return true;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Up)
constexpr auto
operator<= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
-> __optional_le_t<_Tp, _Up>
- { return !__lhs || *__lhs <= __rhs; }
+ {
+ if (__lhs.has_value())
+ return *__lhs <= __rhs;
+ return true;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Tp)
constexpr auto
operator<= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
-> __optional_le_t<_Tp, _Up>
- { return __rhs && __lhs <= *__rhs; }
+ {
+ if (__rhs.has_value())
+ return __lhs <= *__rhs;
+ return false;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Up)
constexpr auto
operator>= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
-> __optional_ge_t<_Tp, _Up>
- { return __lhs && *__lhs >= __rhs; }
+ {
+ if (__lhs.has_value())
+ return *__lhs >= __rhs;
+ return false;
+ }
template<typename _Tp, typename _Up>
_REQUIRES_NOT_OPTIONAL(_Tp)
constexpr auto
operator>= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
-> __optional_ge_t<_Tp, _Up>
- { return !__rhs || __lhs >= *__rhs; }
+ {
+ if (__rhs.has_value())
+ return __lhs >= *__rhs;
+ return true;
+ }
#ifdef __cpp_lib_three_way_comparison
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -1703,17 +2172,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept(noexcept(__lhs.swap(__rhs)))
{ __lhs.swap(__rhs); }
+#if __cpp_lib_optional >= 202506L
+ // We deviate from standard, that do not declared separate swap overload
+ // from optional<T&>.
+ template<typename _Tp>
+ constexpr void
+ swap(optional<_Tp&>& __lhs, optional<_Tp&>& __rhs) noexcept
+ { __lhs.swap(__rhs); }
+#endif
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2766. Swapping non-swappable types
template<typename _Tp>
enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
swap(optional<_Tp>&, optional<_Tp>&) = delete;
+#if __cpp_lib_optional >= 202506L
+ template<int = 0, typename _Tp>
+#else
template<typename _Tp>
+#endif
constexpr
enable_if_t<is_constructible_v<decay_t<_Tp>, _Tp>,
optional<decay_t<_Tp>>>
make_optional(_Tp&& __t)
noexcept(is_nothrow_constructible_v<optional<decay_t<_Tp>>, _Tp>)
- { return optional<decay_t<_Tp>>{ std::forward<_Tp>(__t) }; }
+ { return optional<decay_t<_Tp>>( std::forward<_Tp>(__t) ); }
template<typename _Tp, typename... _Args>
constexpr
@@ -1721,7 +2205,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
optional<_Tp>>
make_optional(_Args&&... __args)
noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
- { return optional<_Tp>{ in_place, std::forward<_Args>(__args)... }; }
+ { return optional<_Tp>( in_place, std::forward<_Args>(__args)... ); }
template<typename _Tp, typename _Up, typename... _Args>
constexpr
@@ -1729,7 +2213,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
optional<_Tp>>
make_optional(initializer_list<_Up> __il, _Args&&... __args)
noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>)
- { return optional<_Tp>{ in_place, __il, std::forward<_Args>(__args)... }; }
+ { return optional<_Tp>( in_place, __il, std::forward<_Args>(__args)... ); }
// Hash.
@@ -1757,6 +2241,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
struct hash<optional<_Tp>>
+ // hash for optional<T&> is disabled because is_hash_enabled_for<T&> is false
: public __conditional_t<__is_hash_enabled_for<remove_const_t<_Tp>>,
__optional_hash<_Tp>,
__hash_not_enabled<_Tp>>
@@ -1772,6 +2257,22 @@ _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;
+
+#if __cpp_lib_optional >= 202506L // C++26
+ template<typename _Tp>
+ constexpr bool
+ ranges::enable_borrowed_range<optional<_Tp&>> = true;
+#endif
+
+ 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..3387296 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>);
@@ -259,9 +259,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
print(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args)
{
auto __fmtargs = std::make_format_args(__args...);
+#if defined(_WIN32) && !defined(__CYGWIN__)
if constexpr (__unicode::__literal_encoding_is_utf8())
std::vprint_unicode(__os, __fmt.get(), __fmtargs);
else
+#endif
std::vprint_nonunicode(__os, __fmt.get(), __fmtargs);
}
@@ -269,10 +271,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline void
println(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args)
{
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 4088. println ignores the locale imbued in std::ostream
- std::print(__os, "{}\n", std::format(__os.getloc(), __fmt,
- std::forward<_Args>(__args)...));
+ auto __fmtargs = std::make_format_args(__args...);
+ std::string __fmtn;
+ __fmtn.reserve(__fmt.get().size() + 1);
+ __fmtn = __fmt.get();
+ __fmtn += '\n';
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if constexpr (__unicode::__literal_encoding_is_utf8())
+ std::vprint_unicode(__os, __fmtn, __fmtargs);
+ else
+#endif
+ std::vprint_nonunicode(__os, __fmtn, __fmtargs);
}
// Defined for C++26, supported as an extension to C++23.
diff --git a/libstdc++-v3/include/std/print b/libstdc++-v3/include/std/print
index ea1aaac..6ffd9a4 100644
--- a/libstdc++-v3/include/std/print
+++ b/libstdc++-v3/include/std/print
@@ -53,9 +53,214 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __format
+{
+#if _GLIBCXX_USE_STDIO_LOCKING && _GLIBCXX_USE_GLIBC_STDIO_EXT
+ // These are defined in <stdio_ext.h> but we don't want to include that.
+ extern "C" int __fwritable(FILE*) noexcept;
+ extern "C" int __flbf(FILE*) noexcept;
+ extern "C" size_t __fbufsize(FILE*) noexcept;
+
+ // A format sink that writes directly to a Glibc FILE.
+ // The file is locked on construction and its buffer is accessed directly.
+ class _File_sink final : _Buf_sink<char>
+ {
+ struct _File
+ {
+ explicit
+ _File(FILE* __f) : _M_file(__f)
+ {
+ ::flockfile(__f);
+ // Ensure stream is in write mode
+ if (!__fwritable(__f))
+ {
+ ::funlockfile(__f);
+ __throw_system_error(EACCES);
+ }
+ // Allocate buffer if needed:
+ if (_M_write_buf().empty())
+ if (::__overflow(__f, EOF) == EOF)
+ {
+ const int __err = errno;
+ ::funlockfile(__f);
+ __throw_system_error(__err);
+ }
+ }
+
+ ~_File() { ::funlockfile(_M_file); }
+
+ _File(_File&&) = delete;
+
+ // A span viewing the unused portion of the stream's output buffer.
+ std::span<char>
+ _M_write_buf() noexcept
+ {
+ return {_M_file->_IO_write_ptr,
+ size_t(_M_file->_IO_buf_end - _M_file->_IO_write_ptr)};
+ }
+
+ // Flush the output buffer to the file so we can write to it again.
+ void
+ _M_flush()
+ {
+ if (::fflush_unlocked(_M_file))
+ __throw_system_error(errno);
+ }
+
+ // Update the current position in the output buffer.
+ void
+ _M_bump(size_t __n) noexcept
+ { _M_file->_IO_write_ptr += __n; }
+
+ bool
+ _M_line_buffered() const noexcept
+ { return __flbf(_M_file); } // Or: _M_file->_flags & 0x200
+
+ bool
+ _M_unbuffered() const noexcept
+ { return __fbufsize(_M_file) == 1; } // Or: _M_file->_flags & 0x2
+
+ FILE* _M_file;
+ } _M_file;
+
+ bool _M_add_newline; // True for std::println, false for std::print.
+
+ // Flush the stream's put area so it can be refilled.
+ void
+ _M_overflow() override
+ {
+ auto __s = this->_M_used();
+ if (__s.data() == this->_M_buf)
+ {
+ // Characters in internal buffer need to be transferred to the FILE.
+ auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(),
+ _M_file._M_file);
+ if (__n != __s.size())
+ __throw_system_error(errno);
+ this->_M_reset(this->_M_buf);
+ }
+ else
+ {
+ // Characters were written directly to the FILE's output buffer.
+ _M_file._M_bump(__s.size());
+ _M_file._M_flush();
+ this->_M_reset(_M_file._M_write_buf());
+ }
+ }
+
+ public:
+ _File_sink(FILE* __f, bool __add_newline)
+ : _M_file(__f), _M_add_newline(__add_newline)
+ {
+ if (!_M_file._M_unbuffered())
+ // Write directly to the FILE's output buffer.
+ this->_M_reset(_M_file._M_write_buf());
+ }
+
+ ~_File_sink() noexcept(false)
+ {
+ auto __s = this->_M_used();
+ if (__s.data() == this->_M_buf) // Unbuffered stream
+ {
+ _File_sink::_M_overflow();
+ if (_M_add_newline)
+ ::putc_unlocked('\n', _M_file._M_file);
+ }
+ else
+ {
+ _M_file._M_bump(__s.size());
+ if (_M_add_newline)
+ ::putc_unlocked('\n', _M_file._M_file);
+ else if (_M_file._M_line_buffered() && __s.size()
+ && (__s.back() == '\n'
+ || __builtin_memchr(__s.data(), '\n', __s.size())))
+ _M_file._M_flush();
+ }
+ }
+
+ using _Sink<char>::out;
+ };
+#elif _GLIBCXX_USE_STDIO_LOCKING
+ // A format sink that buffers output and then copies it to a stdio FILE.
+ // The file is locked on construction and written to using fwrite_unlocked.
+ class _File_sink final : _Buf_sink<char>
+ {
+ FILE* _M_file;
+ bool _M_add_newline;
+
+ // Transfer buffer contents to the FILE, so buffer can be refilled.
+ void
+ _M_overflow() override
+ {
+ auto __s = this->_M_used();
+#if _GLIBCXX_HAVE_FWRITE_UNLOCKED
+ auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(), _M_file);
+ if (__n != __s.size())
+ __throw_system_error(errno);
+#else
+ for (char __c : __s)
+ ::putc_unlocked(__c, _M_file);
+ if (::ferror(_M_file))
+ __throw_system_error(errno);
+#endif
+ this->_M_reset(this->_M_buf);
+ }
+
+ public:
+ _File_sink(FILE* __f, bool __add_newline) noexcept
+ : _Buf_sink<char>(), _M_file(__f), _M_add_newline(__add_newline)
+ { ::flockfile(__f); }
+
+ ~_File_sink() noexcept(false)
+ {
+ _File_sink::_M_overflow();
+ if (_M_add_newline)
+ ::putc_unlocked('\n', _M_file);
+ ::funlockfile(_M_file);
+ }
+
+ using _Sink<char>::out;
+ };
+#else
+ // A wrapper around a format sink that copies the output to a stdio FILE.
+ // This is not actually a _Sink itself, but it creates one to hold the
+ // formatted characters and then copies them to the file when finished.
+ class _File_sink final
+ {
+ FILE* _M_file;
+ _Str_sink<char> _M_sink;
+ bool _M_add_newline;
+
+ public:
+ _File_sink(FILE* __f, bool __add_newline) noexcept
+ : _M_file(__f), _M_add_newline(__add_newline)
+ { }
+
+ ~_File_sink() noexcept(false)
+ {
+ string __s = std::move(_M_sink).get();
+ if (_M_add_newline)
+ __s += '\n';
+ auto __n = std::fwrite(__s.data(), 1, __s.size(), _M_file);
+ if (__n < __s.size())
+ __throw_system_error(EIO);
+ }
+
+ auto out() { return _M_sink.out(); }
+ };
+#endif
+} // namespace __format
+
inline void
vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args)
{
+ std::vformat_to(__format::_File_sink(__stream, false).out(), __fmt, __args);
+ }
+
+ inline void
+ vprint_nonunicode_buffered(FILE* __stream, string_view __fmt,
+ format_args __args)
+ {
__format::_Str_sink<char> __buf;
std::vformat_to(__buf.out(), __fmt, __args);
auto __out = __buf.view();
@@ -73,14 +278,13 @@ _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>);
// If stream refers to a terminal, write a native Unicode string to it.
if (auto __term = __open_terminal(__stream))
{
- string __out = std::vformat(__fmt, __args);
error_code __e;
if (!std::fflush(__stream))
{
@@ -95,21 +299,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_THROW_OR_ABORT(system_error(__e, "std::vprint_unicode"));
}
- // Otherwise just write the string to the file as vprint_nonunicode does.
+ // Otherwise just write the string to the file.
if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())
__throw_system_error(EIO);
#endif
}
+ inline void
+ vprint_unicode_buffered(FILE* __stream, string_view __fmt, format_args __args)
+ {
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ // For most targets we don't need to do anything special to write
+ // Unicode to a terminal. Just use the nonunicode function.
+ std::vprint_nonunicode_buffered(__stream, __fmt, __args);
+#else
+ // For Windows the locking function formats everything first anyway,
+ // so no formatting happens while a lock is taken. Just use that.
+ std::vprint_unicode(__stream, __fmt, __args);
+#endif
+ }
+
template<typename... _Args>
inline void
print(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args)
{
+ constexpr bool __locksafe =
+ (enable_nonlocking_formatter_optimization<remove_cvref_t<_Args>> && ...);
+
auto __fmtargs = std::make_format_args(__args...);
+#if defined(_WIN32) && !defined(__CYGWIN__)
if constexpr (__unicode::__literal_encoding_is_utf8())
- std::vprint_unicode(__stream, __fmt.get(), __fmtargs);
+ std::vprint_unicode_buffered(__stream, __fmt.get(), __fmtargs);
else
+#endif
+
+ if constexpr (__locksafe)
std::vprint_nonunicode(__stream, __fmt.get(), __fmtargs);
+ else
+ std::vprint_nonunicode_buffered(__stream, __fmt.get(), __fmtargs);
}
template<typename... _Args>
@@ -121,8 +348,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline void
println(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args)
{
- std::print(__stream, "{}\n",
- std::format(__fmt, std::forward<_Args>(__args)...));
+ constexpr bool __locksafe =
+ (enable_nonlocking_formatter_optimization<remove_cvref_t<_Args>> && ...);
+
+ // The standard wants us to call
+ // print(stream, runtime_format(string(fmt.get()) + '\n'), args...)
+ // here, but we can avoid that string concatenation in most cases,
+ // and we know what that would call, so we can call that directly.
+
+ auto __fmtargs = std::make_format_args(__args...);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if constexpr (__unicode::__literal_encoding_is_utf8())
+ {
+ // We can't avoid the string concatenation here, but we can call
+ // vprint_unicode_buffered directly, since that's what print would do.
+ string __fmtn;
+ __fmtn.reserve(__fmt.get().size() + 1);
+ __fmtn = __fmt.get();
+ __fmtn += '\n';
+ std::vprint_unicode_buffered(__stream, __fmtn, __fmtargs);
+ }
+ else
+#endif
+
+ // For non-Windows and for non-Unicode on Windows, we know that print
+ // would call vprint_nonunicode or vprint_nonunicode_buffered with a
+ // newline appended to the format-string. Use a _File_sink that adds
+ // the newline automatically and write to it directly.
+ if constexpr (__locksafe)
+ std::vformat_to(__format::_File_sink(__stream, true).out(),
+ __fmt.get(), __fmtargs);
+ else
+ {
+ // Format to a string buffer first, then write the result to a
+ // _File_sink that adds a newline.
+ __format::_Str_sink<char> __buf;
+ std::vformat_to(__buf.out(), __fmt.get(), __fmtargs);
+ string_view __s(__buf.view());
+ __format::_File_sink(__stream, true).out() = __s;
+ }
}
template<typename... _Args>
@@ -131,19 +395,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ std::println(stdout, __fmt, std::forward<_Args>(__args)...); }
inline void
- vprint_unicode(string_view __fmt, format_args __args)
- { std::vprint_unicode(stdout, __fmt, __args); }
+ vprint_unicode_buffered(string_view __fmt, format_args __args)
+ { std::vprint_unicode_buffered(stdout, __fmt, __args); }
inline void
- vprint_nonunicode(string_view __fmt, format_args __args)
- { std::vprint_nonunicode(stdout, __fmt, __args); }
+ vprint_nonunicode_buffered(string_view __fmt, format_args __args)
+ { std::vprint_nonunicode_buffered(stdout, __fmt, __args); }
// Defined for C++26, supported as an extension to C++23.
inline void println(FILE* __stream)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
if constexpr (__unicode::__literal_encoding_is_utf8())
- std::vprint_unicode(__stream, "\n", std::make_format_args());
+ std::vprint_unicode_buffered(__stream, "\n", std::make_format_args());
else
#endif
if (std::putc('\n', __stream) == EOF)
diff --git a/libstdc++-v3/include/std/queue b/libstdc++-v3/include/std/queue
index 74b6c07..bf2b344 100644
--- a/libstdc++-v3/include/std/queue
+++ b/libstdc++-v3/include/std/queue
@@ -61,14 +61,111 @@
#include <bits/requires_hosted.h> // containers
+#define __glibcxx_want_adaptor_iterator_pair_constructor
+#define __glibcxx_want_containers_ranges
+#include <bits/version.h>
+
#include <deque>
#include <vector>
#include <bits/stl_heap.h>
#include <bits/stl_function.h>
#include <bits/stl_queue.h>
-#define __glibcxx_want_adaptor_iterator_pair_constructor
-#define __glibcxx_want_containers_ranges
-#include <bits/version.h>
+#ifdef __glibcxx_format_ranges // C++ >= 23 && HOSTED
+#include <bits/formatfwd.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ // Standard does not constrain accepted _CharT, we do so we can
+ // befriend specializations.
+ template<__format::__char _CharT, typename _Tp,
+ formattable<_CharT> _Container>
+ struct formatter<queue<_Tp, _Container>, _CharT>
+ {
+ private:
+ using __maybe_const_adaptor
+ = __conditional_t<
+ __format::__const_formattable_range<_Container, _CharT>,
+ const queue<_Tp, _Container>, queue<_Tp, _Container>>;
+
+ public:
+ // Standard declares this as template accepting unconstrained
+ // ParseContext type.
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ { return _M_f.parse(__pc); }
+
+ // Standard declares this as template accepting unconstrained
+ // FormatContext type.
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(__maybe_const_adaptor& __a,
+ basic_format_context<_Out, _CharT>& __fc) const
+ { return _M_f.format(__a.c, __fc); }
+
+ private:
+ // Standard uses formatter<ref_view<_Container>, _CharT>, but range_formatter
+ // provides same behavior.
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3881. Incorrect formatting of container adapters backed by std::string
+ range_formatter<_Tp, _CharT> _M_f;
+ };
+
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4398. enable_nonlocking_formatter_optimization should be disabled for container adaptors
+ template<typename _Tp, typename _Container>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<queue<_Tp, _Container>> = false;
+#endif
+
+ 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>, but range_formatter
+ // provides same behavior.
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3881. Incorrect formatting of container adapters backed by std::string
+ range_formatter<_Tp, _CharT> _M_f;
+ };
+
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4398. enable_nonlocking_formatter_optimization should be disabled for container adaptors
+ template<typename _Tp, typename _Container, typename _Comparator>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<
+ priority_queue<_Tp, _Container, _Comparator>> = false;
+#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // __glibcxx_format_ranges
+
#endif /* _GLIBCXX_QUEUE */
diff --git a/libstdc++-v3/include/std/random b/libstdc++-v3/include/std/random
index 0e058a0..8a02ade 100644
--- a/libstdc++-v3/include/std/random
+++ b/libstdc++-v3/include/std/random
@@ -39,6 +39,9 @@
# include <bits/c++0x_warning.h>
#else
+#define __glibcxx_want_philox_engine
+#include <bits/version.h>
+
#include <cmath>
#include <cstdint> // For uint_fast32_t, uint_fast64_t, uint_least32_t
#include <cstdlib>
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 7a339c5..b81ee78 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -51,6 +51,7 @@
#include <utility>
#include <variant>
#endif
+#include <bits/binders.h>
#include <bits/ranges_util.h>
#include <bits/refwrap.h>
@@ -64,7 +65,7 @@
#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_indices
#define __glibcxx_want_ranges_join_with
#define __glibcxx_want_ranges_repeat
#define __glibcxx_want_ranges_slide
@@ -285,6 +286,190 @@ namespace ranges
operator->() const noexcept
{ return std::__addressof(_M_value); }
};
+
+ template<template<typename> class>
+ constexpr bool __is_std_op_template = false;
+
+ template<>
+ inline constexpr bool __is_std_op_template<std::equal_to> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::not_equal_to> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::greater> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::less> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::greater_equal> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::less_equal> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::plus> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::minus> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::multiplies> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::divides> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::modulus> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::negate> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::logical_and> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::logical_or> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::logical_not> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::bit_and> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::bit_or> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::bit_xor> = true;
+ template<>
+ inline constexpr bool __is_std_op_template<std::bit_not> = true;
+
+
+ template<typename _Fn>
+ constexpr bool __is_std_op_wrapper = false;
+
+ template<template<typename> class _Ft, typename _Tp>
+ constexpr bool __is_std_op_wrapper<_Ft<_Tp>>
+ = __is_std_op_template<_Ft>;
+
+ namespace __func_handle
+ {
+ template<typename _Fn>
+ struct _Inplace
+ {
+ _Inplace() = default;
+
+ constexpr explicit
+ _Inplace(_Fn __func) noexcept
+ : _M_fn(__func)
+ { }
+
+ template<typename... _Iters>
+ constexpr decltype(auto)
+ _M_call_deref(const _Iters&... __iters) const
+ noexcept(noexcept(_M_fn(*__iters...)))
+ { return _M_fn(*__iters...); }
+
+ template<typename _DistType, typename... _Iters>
+ constexpr decltype(auto)
+ _M_call_subscript(const _DistType __n, const _Iters&... __iters) const
+ noexcept(noexcept(_M_fn(__iters[iter_difference_t<_Iters>(__n)]...)))
+ { return _M_fn(__iters[iter_difference_t<_Iters>(__n)]...); }
+
+ private:
+ [[no_unique_address]] _Fn _M_fn = _Fn();
+ };
+
+ template<typename _Fn>
+ struct _InplaceMemPtr
+ {
+ _InplaceMemPtr() = default;
+
+ constexpr explicit
+ _InplaceMemPtr(_Fn __func) noexcept
+ : _M_ptr(__func)
+ {}
+
+ template<typename... _Iters>
+ constexpr decltype(auto)
+ _M_call_deref(const _Iters&... __iters) const
+ noexcept(noexcept(std::__invoke(_M_ptr, *__iters...)))
+ { return std::__invoke(_M_ptr, *__iters...); }
+
+ template<typename _DistType, typename... _Iters>
+ constexpr decltype(auto)
+ _M_call_subscript(const _DistType __n, const _Iters&... __iters) const
+ noexcept(noexcept(std::__invoke(_M_ptr, __iters[iter_difference_t<_Iters>(__n)]...)))
+ { return std::__invoke(_M_ptr, __iters[iter_difference_t<_Iters>(__n)]...); }
+
+ private:
+ _Fn _M_ptr = nullptr;
+ };
+
+ template<typename _Fn>
+ struct _ViaPointer
+ {
+ _ViaPointer() = default;
+
+ constexpr explicit
+ _ViaPointer(_Fn& __func) noexcept
+ : _M_ptr(std::addressof(__func))
+ { }
+
+ template<typename _Un>
+ requires (!is_const_v<_Un>) && is_same_v<const _Un, _Fn>
+ constexpr
+ _ViaPointer(_ViaPointer<_Un> __other) noexcept
+ : _M_ptr(__other._M_ptr)
+ { }
+
+ template<typename... _Iters>
+ constexpr decltype(auto)
+ _M_call_deref(const _Iters&... __iters) const
+ noexcept(noexcept((*_M_ptr)(*__iters...)))
+ { return (*_M_ptr)(*__iters...); }
+
+ template<typename _DistType, typename... _Iters>
+ constexpr decltype(auto)
+ _M_call_subscript(const _DistType __n, const _Iters&... __iters) const
+ noexcept(noexcept((*_M_ptr)(__iters[iter_difference_t<_Iters>(__n)]...)))
+ { return (*_M_ptr)(__iters[iter_difference_t<_Iters>(__n)]...); }
+
+ private:
+ _Fn* _M_ptr = nullptr;
+
+ template<typename>
+ friend struct _ViaPointer;
+ };
+
+ template<typename _Fn>
+ struct _StaticCall
+ {
+ _StaticCall() = default;
+
+ constexpr explicit
+ _StaticCall(const _Fn&) noexcept
+ {}
+
+ template<typename... _Iters>
+ static constexpr decltype(auto)
+ _M_call_deref(const _Iters&... __iters)
+ noexcept(noexcept(_Fn::operator()(*__iters...)))
+ { return _Fn::operator()(*__iters...); }
+
+ template<typename _DistType, typename... _Iters>
+ static constexpr decltype(auto)
+ _M_call_subscript(_DistType __n, const _Iters&... __iters)
+ noexcept(noexcept(_Fn::operator()(__iters[iter_difference_t<_Iters>(__n)]...)))
+ { return _Fn::operator()(__iters[iter_difference_t<_Iters>(__n)]...); }
+ };
+
+ template<typename _Fn, typename... _Iters>
+ consteval auto
+ __select()
+ {
+ using _Fd = remove_cv_t<_Fn>;
+ if constexpr (is_member_pointer_v<_Fd>)
+ return __func_handle::_InplaceMemPtr<_Fd>();
+ else if constexpr (is_function_v<remove_pointer_t<_Fd>>)
+ return __func_handle::_Inplace<_Fd>();
+ else if constexpr (__is_std_op_wrapper<_Fd>)
+ return __func_handle::_Inplace<_Fd>();
+ else if constexpr (requires (const _Iters&... __iters)
+ { _Fd::operator()(*__iters...); })
+ return __func_handle::_StaticCall<_Fd>();
+ else
+ return __func_handle::_ViaPointer<_Fn>();
+ };
+ } // __func_handle
+
+ template<typename _Fn, typename... _Iters>
+ using __func_handle_t = decltype(__func_handle::__select<_Fn, _Iters...>());
} // namespace __detail
/// A view that contains exactly one element.
@@ -661,7 +846,7 @@ namespace ranges
: _M_value(__value)
{ }
- constexpr
+ constexpr explicit
iota_view(type_identity_t<_Winc> __value,
type_identity_t<_Bound> __bound)
: _M_value(__value), _M_bound(__bound)
@@ -670,19 +855,19 @@ namespace ranges
__glibcxx_assert( bool(__value <= __bound) );
}
- constexpr
+ constexpr explicit
iota_view(_Iterator __first, _Iterator __last)
requires same_as<_Winc, _Bound>
: iota_view(__first._M_value, __last._M_value)
{ }
- constexpr
+ constexpr explicit
iota_view(_Iterator __first, unreachable_sentinel_t __last)
requires same_as<_Bound, unreachable_sentinel_t>
: iota_view(__first._M_value, __last)
{ }
- constexpr
+ constexpr explicit
iota_view(_Iterator __first, _Sentinel __last)
requires (!same_as<_Winc, _Bound>) && (!same_as<_Bound, unreachable_sentinel_t>)
: iota_view(__first._M_value, __last._M_bound)
@@ -785,6 +970,19 @@ namespace views
};
inline constexpr _Iota iota{};
+
+#ifdef __cpp_lib_ranges_indices // C++ >= 26
+ struct _Indices
+ {
+ template<ranges::__detail::__is_integer_like _Tp>
+ requires __detail::__can_iota_view<_Tp>
+ [[nodiscard]] constexpr auto
+ operator() (_Tp __e) const noexcept
+ { return iota(_Tp{}, __e); }
+ };
+
+ inline constexpr _Indices indices{};
+#endif // __cpp_lib_ranges_indices
} // namespace views
#if _GLIBCXX_HOSTED
@@ -1048,93 +1246,43 @@ namespace views::__adaptor
template<typename _Adaptor, typename... _Args>
struct _Partial : _RangeAdaptorClosure<_Partial<_Adaptor, _Args...>>
{
- tuple<_Args...> _M_args;
+ using _Binder = _Bind_back_t<_Adaptor, _Args...>;
+ [[no_unique_address]] _Binder _M_binder;
// First parameter is to ensure this constructor is never used
// instead of the copy/move constructor.
template<typename... _Ts>
constexpr
_Partial(int, _Ts&&... __args)
- : _M_args(std::forward<_Ts>(__args)...)
+ : _M_binder(0, _Adaptor(), std::forward<_Ts>(__args)...)
{ }
// Invoke _Adaptor with arguments __r, _M_args... according to the
// value category of this _Partial object.
-#if __cpp_explicit_this_parameter
+#if _GLIBCXX_EXPLICIT_THIS_PARAMETER
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this
template<typename _Self, typename _Range>
requires __adaptor_invocable<_Adaptor, _Range, __like_t<_Self, _Args>...>
constexpr auto
operator()(this _Self&& __self, _Range&& __r)
{
- auto __forwarder = [&__r] (auto&&... __args) {
- return _Adaptor{}(std::forward<_Range>(__r),
- std::forward<decltype(__args)>(__args)...);
- };
- return std::apply(__forwarder, __like_t<_Self, _Partial>(__self)._M_args);
+ return _Binder::_S_call(__like_t<_Self, _Partial>(__self)._M_binder,
+ std::forward<_Range>(__r));
}
+# pragma GCC diagnostic pop
#else
template<typename _Range>
requires __adaptor_invocable<_Adaptor, _Range, const _Args&...>
constexpr auto
operator()(_Range&& __r) const &
- {
- auto __forwarder = [&__r] (const auto&... __args) {
- return _Adaptor{}(std::forward<_Range>(__r), __args...);
- };
- return std::apply(__forwarder, _M_args);
- }
+ { return _Binder::_S_call(_M_binder, std::forward<_Range>(__r)); }
template<typename _Range>
requires __adaptor_invocable<_Adaptor, _Range, _Args...>
constexpr auto
operator()(_Range&& __r) &&
- {
- auto __forwarder = [&__r] (auto&... __args) {
- return _Adaptor{}(std::forward<_Range>(__r), std::move(__args)...);
- };
- return std::apply(__forwarder, _M_args);
- }
-
- template<typename _Range>
- constexpr auto
- operator()(_Range&& __r) const && = delete;
-#endif
- };
-
- // A lightweight specialization of the above primary template for
- // the common case where _Adaptor accepts a single extra argument.
- template<typename _Adaptor, typename _Arg>
- struct _Partial<_Adaptor, _Arg> : _RangeAdaptorClosure<_Partial<_Adaptor, _Arg>>
- {
- _Arg _M_arg;
-
- template<typename _Tp>
- constexpr
- _Partial(int, _Tp&& __arg)
- : _M_arg(std::forward<_Tp>(__arg))
- { }
-
-#if __cpp_explicit_this_parameter
- template<typename _Self, typename _Range>
- requires __adaptor_invocable<_Adaptor, _Range, __like_t<_Self, _Arg>>
- constexpr auto
- operator()(this _Self&& __self, _Range&& __r)
- {
- return _Adaptor{}(std::forward<_Range>(__r),
- __like_t<_Self, _Partial>(__self)._M_arg);
- }
-#else
- template<typename _Range>
- requires __adaptor_invocable<_Adaptor, _Range, const _Arg&>
- constexpr auto
- operator()(_Range&& __r) const &
- { return _Adaptor{}(std::forward<_Range>(__r), _M_arg); }
-
- template<typename _Range>
- requires __adaptor_invocable<_Adaptor, _Range, _Arg>
- constexpr auto
- operator()(_Range&& __r) &&
- { return _Adaptor{}(std::forward<_Range>(__r), std::move(_M_arg)); }
+ { return _Binder::_S_call(std::move(_M_binder), std::forward<_Range>(__r)); }
template<typename _Range>
constexpr auto
@@ -1151,12 +1299,13 @@ namespace views::__adaptor
&& (is_trivially_copy_constructible_v<_Args> && ...)
struct _Partial<_Adaptor, _Args...> : _RangeAdaptorClosure<_Partial<_Adaptor, _Args...>>
{
- tuple<_Args...> _M_args;
+ using _Binder = _Bind_back_t<_Adaptor, _Args...>;
+ [[no_unique_address]] _Binder _M_binder;
template<typename... _Ts>
constexpr
_Partial(int, _Ts&&... __args)
- : _M_args(std::forward<_Ts>(__args)...)
+ : _M_binder(0, _Adaptor(), std::forward<_Ts>(__args)...)
{ }
// Invoke _Adaptor with arguments __r, const _M_args&... regardless
@@ -1165,36 +1314,7 @@ namespace views::__adaptor
requires __adaptor_invocable<_Adaptor, _Range, const _Args&...>
constexpr auto
operator()(_Range&& __r) const
- {
- auto __forwarder = [&__r] (const auto&... __args) {
- return _Adaptor{}(std::forward<_Range>(__r), __args...);
- };
- return std::apply(__forwarder, _M_args);
- }
-
- static constexpr bool _S_has_simple_call_op = true;
- };
-
- // A lightweight specialization of the above template for the common case
- // where _Adaptor accepts a single extra argument.
- template<typename _Adaptor, typename _Arg>
- requires __adaptor_has_simple_extra_args<_Adaptor, _Arg>
- && is_trivially_copy_constructible_v<_Arg>
- struct _Partial<_Adaptor, _Arg> : _RangeAdaptorClosure<_Partial<_Adaptor, _Arg>>
- {
- _Arg _M_arg;
-
- template<typename _Tp>
- constexpr
- _Partial(int, _Tp&& __arg)
- : _M_arg(std::forward<_Tp>(__arg))
- { }
-
- template<typename _Range>
- requires __adaptor_invocable<_Adaptor, _Range, const _Arg&>
- constexpr auto
- operator()(_Range&& __r) const
- { return _Adaptor{}(std::forward<_Range>(__r), _M_arg); }
+ { return _Binder::_S_call(_M_binder, std::forward<_Range>(__r)); }
static constexpr bool _S_has_simple_call_op = true;
};
@@ -1219,7 +1339,9 @@ namespace views::__adaptor
// Invoke _M_rhs(_M_lhs(__r)) according to the value category of this
// range adaptor closure object.
-#if __cpp_explicit_this_parameter
+#if _GLIBCXX_EXPLICIT_THIS_PARAMETER
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this
template<typename _Self, typename _Range>
requires __pipe_invocable<__like_t<_Self, _Lhs>, __like_t<_Self, _Rhs>, _Range>
constexpr auto
@@ -1229,6 +1351,7 @@ namespace views::__adaptor
(__like_t<_Self, _Pipe>(__self)._M_lhs
(std::forward<_Range>(__r))));
}
+# pragma GCC diagnostic pop
#else
template<typename _Range>
requires __pipe_invocable<const _Lhs&, const _Rhs&, _Range>
@@ -1586,8 +1709,6 @@ namespace views::__adaptor
};
template<random_access_range _Range>
- requires (sizeof(range_difference_t<_Range>)
- <= sizeof(iterator_t<_Range>))
struct _CachedPosition<_Range>
{
private:
@@ -1812,7 +1933,7 @@ namespace views::__adaptor
&& default_initializable<_Pred>)
= default;
- constexpr
+ constexpr explicit
filter_view(_Vp __base, _Pred __pred)
: _M_base(std::move(__base)), _M_pred(std::move(__pred))
{ }
@@ -1943,6 +2064,10 @@ namespace views::__adaptor
private:
using _Parent = __detail::__maybe_const_t<_Const, transform_view>;
using _Base = transform_view::_Base<_Const>;
+ using _Base_iter = iterator_t<_Base>;
+ using _Func_handle = __detail::__func_handle_t<
+ __detail::__maybe_const_t<_Const, _Fp>,
+ _Base_iter>;
static auto
_S_iter_concept()
@@ -1957,10 +2082,8 @@ namespace views::__adaptor
return input_iterator_tag{};
}
- using _Base_iter = iterator_t<_Base>;
-
_Base_iter _M_current = _Base_iter();
- _Parent* _M_parent = nullptr;
+ [[no_unique_address]] _Func_handle _M_fun;
public:
using iterator_concept = decltype(_S_iter_concept());
@@ -1973,16 +2096,20 @@ namespace views::__adaptor
_Iterator() requires default_initializable<_Base_iter> = default;
constexpr
- _Iterator(_Parent* __parent, _Base_iter __current)
- : _M_current(std::move(__current)),
- _M_parent(__parent)
+ _Iterator(_Func_handle __fun, _Base_iter __current)
+ : _M_current(std::move(__current)), _M_fun(__fun)
{ }
constexpr
+ _Iterator(_Parent* __parent, _Base_iter __current)
+ : _M_current(std::move(__current)), _M_fun(*__parent->_M_fun)
+ {}
+
+ constexpr
_Iterator(_Iterator<!_Const> __i)
requires _Const
&& convertible_to<iterator_t<_Vp>, _Base_iter>
- : _M_current(std::move(__i._M_current)), _M_parent(__i._M_parent)
+ : _M_current(std::move(__i._M_current)), _M_fun(__i._M_fun)
{ }
constexpr const _Base_iter&
@@ -1995,8 +2122,8 @@ namespace views::__adaptor
constexpr decltype(auto)
operator*() const
- noexcept(noexcept(std::__invoke(*_M_parent->_M_fun, *_M_current)))
- { return std::__invoke(*_M_parent->_M_fun, *_M_current); }
+ noexcept(noexcept(_M_fun._M_call_deref(_M_current)))
+ { return _M_fun._M_call_deref(_M_current); }
constexpr _Iterator&
operator++()
@@ -2049,7 +2176,7 @@ namespace views::__adaptor
constexpr decltype(auto)
operator[](difference_type __n) const
requires random_access_range<_Base>
- { return std::__invoke(*_M_parent->_M_fun, _M_current[__n]); }
+ { return _M_fun._M_call_subscript(__n, _M_current); }
friend constexpr bool
operator==(const _Iterator& __x, const _Iterator& __y)
@@ -2087,17 +2214,17 @@ namespace views::__adaptor
friend constexpr _Iterator
operator+(_Iterator __i, difference_type __n)
requires random_access_range<_Base>
- { return {__i._M_parent, __i._M_current + __n}; }
+ { return {__i._M_fun, __i._M_current + __n}; }
friend constexpr _Iterator
operator+(difference_type __n, _Iterator __i)
requires random_access_range<_Base>
- { return {__i._M_parent, __i._M_current + __n}; }
+ { return {__i._M_fun, __i._M_current + __n}; }
friend constexpr _Iterator
operator-(_Iterator __i, difference_type __n)
requires random_access_range<_Base>
- { return {__i._M_parent, __i._M_current - __n}; }
+ { return {__i._M_fun, __i._M_current - __n}; }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3483. transform_view::iterator's difference is overconstrained
@@ -2189,7 +2316,7 @@ namespace views::__adaptor
&& default_initializable<_Fp>)
= default;
- constexpr
+ constexpr explicit
transform_view(_Vp __base, _Fp __fun)
: _M_base(std::move(__base)), _M_fun(std::move(__fun))
{ }
@@ -2324,7 +2451,7 @@ namespace views::__adaptor
public:
take_view() requires default_initializable<_Vp> = default;
- constexpr
+ constexpr explicit
take_view(_Vp __base, range_difference_t<_Vp> __count)
: _M_base(std::move(__base)), _M_count(std::move(__count))
{ }
@@ -2472,6 +2599,10 @@ namespace views::__adaptor
using _Tp = remove_cvref_t<_Range>;
if constexpr (__detail::__is_empty_view<_Tp>)
return _Tp();
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ else if constexpr (__is_optional_v<_Tp> && view<_Tp>)
+ return __n ? std::forward<_Range>(__r) : _Tp();
+#endif
else if constexpr (random_access_range<_Tp>
&& sized_range<_Tp>
&& (std::__detail::__is_span<_Tp>
@@ -2563,7 +2694,7 @@ namespace views::__adaptor
&& default_initializable<_Pred>)
= default;
- constexpr
+ constexpr explicit
take_while_view(_Vp __base, _Pred __pred)
: _M_base(std::move(__base)), _M_pred(std::move(__pred))
{ }
@@ -2651,7 +2782,7 @@ namespace views::__adaptor
public:
drop_view() requires default_initializable<_Vp> = default;
- constexpr
+ constexpr explicit
drop_view(_Vp __base, range_difference_t<_Vp> __count)
: _M_base(std::move(__base)), _M_count(__count)
{ __glibcxx_assert(__count >= 0); }
@@ -2748,6 +2879,10 @@ namespace views::__adaptor
using _Tp = remove_cvref_t<_Range>;
if constexpr (__detail::__is_empty_view<_Tp>)
return _Tp();
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ else if constexpr (__is_optional_v<_Tp> && view<_Tp>)
+ return __n ? _Tp() : std::forward<_Range>(__r);
+#endif
else if constexpr (random_access_range<_Tp>
&& sized_range<_Tp>
&& (std::__detail::__is_span<_Tp>
@@ -2805,7 +2940,7 @@ namespace views::__adaptor
&& default_initializable<_Pred>)
= default;
- constexpr
+ constexpr explicit
drop_while_view(_Vp __base, _Pred __pred)
: _M_base(std::move(__base)), _M_pred(std::move(__pred))
{ }
@@ -2972,7 +3107,12 @@ namespace views::__adaptor
}
if constexpr (_S_ref_is_glvalue)
- _M_inner.reset();
+ {
+ if constexpr (forward_iterator<_Inner_iter>)
+ _M_inner = _Inner_iter();
+ else
+ _M_inner.reset();
+ }
}
static constexpr auto
@@ -3012,6 +3152,24 @@ namespace views::__adaptor
return *_M_parent->_M_outer;
}
+ constexpr _Inner_iter&
+ _M_get_inner() noexcept
+ {
+ if constexpr (forward_iterator<_Inner_iter>)
+ return _M_inner;
+ else
+ return *_M_inner;
+ }
+
+ constexpr const _Inner_iter&
+ _M_get_inner() const noexcept
+ {
+ if constexpr (forward_iterator<_Inner_iter>)
+ return _M_inner;
+ else
+ return *_M_inner;
+ }
+
constexpr
_Iterator(_Parent* __parent, _Outer_iter __outer) requires forward_range<_Base>
: _M_outer(std::move(__outer)), _M_parent(__parent)
@@ -3023,8 +3181,11 @@ namespace views::__adaptor
{ _M_satisfy(); }
[[no_unique_address]]
- __detail::__maybe_present_t<forward_range<_Base>, _Outer_iter> _M_outer;
- optional<_Inner_iter> _M_inner;
+ __detail::__maybe_present_t<forward_range<_Base>, _Outer_iter> _M_outer
+ = decltype(_M_outer)();
+ __conditional_t<forward_iterator<_Inner_iter>,
+ _Inner_iter, optional<_Inner_iter>> _M_inner
+ = decltype(_M_inner)();
_Parent* _M_parent = nullptr;
public:
@@ -3048,7 +3209,7 @@ namespace views::__adaptor
constexpr decltype(auto)
operator*() const
- { return **_M_inner; }
+ { return *_M_get_inner(); }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3500. join_view::iterator::operator->() is bogus
@@ -3056,7 +3217,7 @@ namespace views::__adaptor
operator->() const
requires __detail::__has_arrow<_Inner_iter>
&& copyable<_Inner_iter>
- { return *_M_inner; }
+ { return _M_get_inner(); }
constexpr _Iterator&
operator++()
@@ -3067,7 +3228,7 @@ namespace views::__adaptor
else
return *_M_parent->_M_inner;
}();
- if (++*_M_inner == ranges::end(__inner_range))
+ if (++_M_get_inner() == ranges::end(__inner_range))
{
++_M_get_outer();
_M_satisfy();
@@ -3097,9 +3258,9 @@ namespace views::__adaptor
{
if (_M_outer == ranges::end(_M_parent->_M_base))
_M_inner = ranges::end(__detail::__as_lvalue(*--_M_outer));
- while (*_M_inner == ranges::begin(__detail::__as_lvalue(*_M_outer)))
- *_M_inner = ranges::end(__detail::__as_lvalue(*--_M_outer));
- --*_M_inner;
+ while (_M_get_inner() == ranges::begin(__detail::__as_lvalue(*_M_outer)))
+ _M_get_inner() = ranges::end(__detail::__as_lvalue(*--_M_outer));
+ --_M_get_inner();
return *this;
}
@@ -3126,14 +3287,14 @@ namespace views::__adaptor
friend constexpr decltype(auto)
iter_move(const _Iterator& __i)
- noexcept(noexcept(ranges::iter_move(*__i._M_inner)))
- { return ranges::iter_move(*__i._M_inner); }
+ noexcept(noexcept(ranges::iter_move(__i._M_get_inner())))
+ { return ranges::iter_move(__i._M_get_inner()); }
friend constexpr void
iter_swap(const _Iterator& __x, const _Iterator& __y)
- noexcept(noexcept(ranges::iter_swap(*__x._M_inner, *__y._M_inner)))
+ noexcept(noexcept(ranges::iter_swap(__x._M_get_inner(), __y._M_get_inner())))
requires indirectly_swappable<_Inner_iter>
- { return ranges::iter_swap(*__x._M_inner, *__y._M_inner); }
+ { return ranges::iter_swap(__x._M_get_inner(), __y._M_get_inner()); }
friend _Iterator<!_Const>;
template<bool> friend struct _Sentinel;
@@ -3377,7 +3538,8 @@ namespace views::__adaptor
[[no_unique_address]]
__detail::__maybe_present_t<forward_range<_Vp>,
- iterator_t<_Base>> _M_current;
+ iterator_t<_Base>> _M_current
+ = decltype(_M_current)();
bool _M_trailing_empty = false;
public:
@@ -3642,7 +3804,7 @@ namespace views::__adaptor
&& default_initializable<_Pattern>)
= default;
- constexpr
+ constexpr explicit
lazy_split_view(_Vp __base, _Pattern __pattern)
: _M_base(std::move(__base)), _M_pattern(std::move(__pattern))
{ }
@@ -3650,7 +3812,7 @@ namespace views::__adaptor
template<input_range _Range>
requires constructible_from<_Vp, views::all_t<_Range>>
&& constructible_from<_Pattern, single_view<range_value_t<_Range>>>
- constexpr
+ constexpr explicit
lazy_split_view(_Range&& __r, range_value_t<_Range> __e)
: _M_base(views::all(std::forward<_Range>(__r))),
_M_pattern(views::single(std::move(__e)))
@@ -3767,7 +3929,7 @@ namespace views::__adaptor
&& default_initializable<_Pattern>)
= default;
- constexpr
+ constexpr explicit
split_view(_Vp __base, _Pattern __pattern)
: _M_base(std::move(__base)), _M_pattern(std::move(__pattern))
{ }
@@ -3775,7 +3937,7 @@ namespace views::__adaptor
template<forward_range _Range>
requires constructible_from<_Vp, views::all_t<_Range>>
&& constructible_from<_Pattern, single_view<range_value_t<_Range>>>
- constexpr
+ constexpr explicit
split_view(_Range&& __r, range_value_t<_Range> __e)
: _M_base(views::all(std::forward<_Range>(__r))),
_M_pattern(views::single(std::move(__e)))
@@ -4198,6 +4360,10 @@ namespace views::__adaptor
using _Tp = remove_cvref_t<_Range>;
if constexpr (__detail::__is_reverse_view<_Tp>)
return std::forward<_Range>(__r).base();
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ else if constexpr (__is_optional_v<_Tp> && view<_Tp>)
+ return std::forward<_Range>(__r);
+#endif
else if constexpr (__detail::__is_reversible_subrange<_Tp>)
{
using _Iter = decltype(ranges::begin(__r).base());
@@ -5156,13 +5322,21 @@ namespace views::__adaptor
class zip_transform_view<_Fp, _Vs...>::_Iterator : public __iter_cat<_Const>
{
using _Parent = __detail::__maybe_const_t<_Const, zip_transform_view>;
+ using _Fun_handle = __detail::__func_handle_t<
+ __detail::__maybe_const_t<_Const, _Fp>,
+ iterator_t<__detail::__maybe_const_t<_Const, _Vs>>...>;
- _Parent* _M_parent = nullptr;
+ [[no_unique_address]] _Fun_handle _M_fun;
__ziperator<_Const> _M_inner;
constexpr
+ _Iterator(_Fun_handle __fun, __ziperator<_Const> __inner)
+ : _M_fun(__fun), _M_inner(std::move(__inner))
+ { }
+
+ constexpr
_Iterator(_Parent& __parent, __ziperator<_Const> __inner)
- : _M_parent(std::__addressof(__parent)), _M_inner(std::move(__inner))
+ : _M_fun(*__parent._M_fun), _M_inner(std::move(__inner))
{ }
friend class zip_transform_view;
@@ -5180,14 +5354,14 @@ namespace views::__adaptor
constexpr
_Iterator(_Iterator<!_Const> __i)
requires _Const && convertible_to<__ziperator<false>, __ziperator<_Const>>
- : _M_parent(__i._M_parent), _M_inner(std::move(__i._M_inner))
+ : _M_fun(__i._M_fun), _M_inner(std::move(__i._M_inner))
{ }
constexpr decltype(auto)
operator*() const
{
return std::apply([&](const auto&... __iters) -> decltype(auto) {
- return std::__invoke(*_M_parent->_M_fun, *__iters...);
+ return _M_fun._M_call_deref(__iters...);
}, _M_inner._M_current);
}
@@ -5243,7 +5417,7 @@ namespace views::__adaptor
operator[](difference_type __n) const requires random_access_range<_Base<_Const>>
{
return std::apply([&]<typename... _Is>(const _Is&... __iters) -> decltype(auto) {
- return std::__invoke(*_M_parent->_M_fun, __iters[iter_difference_t<_Is>(__n)]...);
+ return _M_fun._M_call_subscript(__n, __iters...);
}, _M_inner._M_current);
}
@@ -5260,17 +5434,17 @@ namespace views::__adaptor
friend constexpr _Iterator
operator+(const _Iterator& __i, difference_type __n)
requires random_access_range<_Base<_Const>>
- { return _Iterator(*__i._M_parent, __i._M_inner + __n); }
+ { return _Iterator(__i._M_fun, __i._M_inner + __n); }
friend constexpr _Iterator
operator+(difference_type __n, const _Iterator& __i)
requires random_access_range<_Base<_Const>>
- { return _Iterator(*__i._M_parent, __i._M_inner + __n); }
+ { return _Iterator(__i._M_fun, __i._M_inner + __n); }
friend constexpr _Iterator
operator-(const _Iterator& __i, difference_type __n)
requires random_access_range<_Base<_Const>>
- { return _Iterator(*__i._M_parent, __i._M_inner - __n); }
+ { return _Iterator(__i._M_fun, __i._M_inner - __n); }
friend constexpr difference_type
operator-(const _Iterator& __x, const _Iterator& __y)
@@ -5337,7 +5511,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>&>>>;
}
@@ -5439,7 +5613,7 @@ namespace views::__adaptor
{
// Yields tuple<_Tp, ..., _Tp> with _Nm elements.
template<typename _Tp, size_t _Nm>
- using __repeated_tuple = decltype(std::tuple_cat(std::declval<array<_Tp, _Nm>>()));
+ using __repeated_tuple = typename __make_tuple<array<_Tp, _Nm>>::__type;
// For a functor F that is callable with N arguments, the expression
// declval<__unarize<F, N>>(x) is equivalent to declval<F>(x, ..., x).
@@ -5516,9 +5690,7 @@ namespace views::__adaptor
public:
using iterator_category = input_iterator_tag;
using iterator_concept = decltype(_S_iter_concept());
- using value_type = conditional_t<_Nm == 2,
- pair<range_value_t<_Base>, range_value_t<_Base>>,
- __detail::__repeated_tuple<range_value_t<_Base>, _Nm>>;
+ using value_type = __detail::__repeated_tuple<range_value_t<_Base>, _Nm>;
using difference_type = range_difference_t<_Base>;
_Iterator() = default;
@@ -5839,13 +6011,23 @@ namespace views::__adaptor
{
using _Parent = __detail::__maybe_const_t<_Const, adjacent_transform_view>;
using _Base = __detail::__maybe_const_t<_Const, _Vp>;
+ using _Fun_handle = decltype([]<size_t... _Ids>(std::index_sequence<_Ids...>) {
+ return __detail::__func_handle_t<
+ __detail::__maybe_const_t<_Const, _Fp>,
+ iterator_t<__detail::__maybe_const_t<(_Ids, _Const), _Vp>>...>();
+ }(make_index_sequence<_Nm>()));
- _Parent* _M_parent = nullptr;
+ [[no_unique_address]] _Fun_handle _M_fun;
_InnerIter<_Const> _M_inner;
constexpr
+ _Iterator(_Fun_handle __fun, _InnerIter<_Const> __inner)
+ : _M_fun(__fun), _M_inner(std::move(__inner))
+ { }
+
+ constexpr
_Iterator(_Parent& __parent, _InnerIter<_Const> __inner)
- : _M_parent(std::__addressof(__parent)), _M_inner(std::move(__inner))
+ : _M_fun(*__parent._M_fun), _M_inner(std::move(__inner))
{ }
static auto
@@ -5886,14 +6068,14 @@ namespace views::__adaptor
constexpr
_Iterator(_Iterator<!_Const> __i)
requires _Const && convertible_to<_InnerIter<false>, _InnerIter<_Const>>
- : _M_parent(__i._M_parent), _M_inner(std::move(__i._M_inner))
+ : _M_fun(__i._M_fun), _M_inner(std::move(__i._M_inner))
{ }
constexpr decltype(auto)
operator*() const
{
return std::apply([&](const auto&... __iters) -> decltype(auto) {
- return std::__invoke(*_M_parent->_M_fun, *__iters...);
+ return _M_fun._M_call_deref(__iters...);
}, _M_inner._M_current);
}
@@ -5945,7 +6127,7 @@ namespace views::__adaptor
operator[](difference_type __n) const requires random_access_range<_Base>
{
return std::apply([&](const auto&... __iters) -> decltype(auto) {
- return std::__invoke(*_M_parent->_M_fun, __iters[__n]...);
+ return _M_fun._M_call_subscript(__n, __iters...);
}, _M_inner._M_current);
}
@@ -5982,17 +6164,17 @@ namespace views::__adaptor
friend constexpr _Iterator
operator+(const _Iterator& __i, difference_type __n)
requires random_access_range<_Base>
- { return _Iterator(*__i._M_parent, __i._M_inner + __n); }
+ { return _Iterator(__i._M_fun, __i._M_inner + __n); }
friend constexpr _Iterator
operator+(difference_type __n, const _Iterator& __i)
requires random_access_range<_Base>
- { return _Iterator(*__i._M_parent, __i._M_inner + __n); }
+ { return _Iterator(__i._M_fun, __i._M_inner + __n); }
friend constexpr _Iterator
operator-(const _Iterator& __i, difference_type __n)
requires random_access_range<_Base>
- { return _Iterator(*__i._M_parent, __i._M_inner - __n); }
+ { return _Iterator(__i._M_fun, __i._M_inner - __n); }
friend constexpr difference_type
operator-(const _Iterator& __x, const _Iterator& __y)
@@ -6599,7 +6781,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,15 +7470,15 @@ 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>
&& default_initializable<_Pattern>)
= default;
- constexpr
+ constexpr explicit
join_with_view(_Vp __base, _Pattern __pattern)
: _M_base(std::move(__base)), _M_pattern(std::move(__pattern))
{ }
@@ -7304,7 +7486,7 @@ namespace views::__adaptor
template<input_range _Range>
requires constructible_from<_Vp, views::all_t<_Range>>
&& constructible_from<_Pattern, single_view<range_value_t<_InnerRange>>>
- constexpr
+ constexpr explicit
join_with_view(_Range&& __r, range_value_t<_InnerRange> __e)
: _M_base(views::all(std::forward<_Range>(__r))),
_M_pattern(views::single(std::move(__e)))
@@ -7401,7 +7583,8 @@ namespace views::__adaptor
_Parent* _M_parent = nullptr;
[[no_unique_address]]
- __detail::__maybe_present_t<forward_range<_Base>, _OuterIter> _M_outer_it;
+ __detail::__maybe_present_t<forward_range<_Base>, _OuterIter> _M_outer_it
+ = decltype(_M_outer_it)();
variant<_PatternIter, _InnerIter> _M_inner_it;
constexpr _OuterIter&
@@ -7744,7 +7927,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 +8487,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); }
@@ -9355,6 +9538,10 @@ namespace views::__adaptor
return views::all(std::forward<_Range>(__r));
else if constexpr (__detail::__is_empty_view<_Tp>)
return views::empty<const element_type>;
+#if __cpp_lib_optional >= 202506L && __cpp_lib_optional_range_support // >= C++26
+ else if constexpr (__is_optional_ref_v<_Tp>)
+ return optional<const typename _Tp::value_type&>(__r);
+#endif
else if constexpr (std::__detail::__is_span<_Tp>)
return span<const element_type, _Tp::extent>(std::forward<_Range>(__r));
else if constexpr (__detail::__is_constable_ref_view<_Tp>)
@@ -9736,7 +9923,7 @@ namespace ranges
end() requires (!(__detail::__simple_view<_Vs> && ...))
{
constexpr auto __n = sizeof...(_Vs);
- if constexpr ((semiregular<iterator_t<_Vs>> && ...)
+ if constexpr (__detail::__all_forward<false, _Vs...>
&& common_range<_Vs...[__n - 1]>)
return _Iterator<false>(this, in_place_index<__n - 1>,
ranges::end(std::get<__n - 1>(_M_views)));
@@ -9748,7 +9935,7 @@ namespace ranges
end() const requires (range<const _Vs> && ...) && __detail::__concatable<const _Vs...>
{
constexpr auto __n = sizeof...(_Vs);
- if constexpr ((semiregular<iterator_t<const _Vs>> && ...)
+ if constexpr (__detail::__all_forward<true, _Vs...>
&& common_range<const _Vs...[__n - 1]>)
return _Iterator<true>(this, in_place_index<__n - 1>,
ranges::end(std::get<__n - 1>(_M_views)));
diff --git a/libstdc++-v3/include/std/regex b/libstdc++-v3/include/std/regex
index 0223066..9121d26 100644
--- a/libstdc++-v3/include/std/regex
+++ b/libstdc++-v3/include/std/regex
@@ -41,7 +41,6 @@
#include <bitset>
#include <locale>
-#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
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/shared_mutex b/libstdc++-v3/include/std/shared_mutex
index 94c8532..92f6227 100644
--- a/libstdc++-v3/include/std/shared_mutex
+++ b/libstdc++-v3/include/std/shared_mutex
@@ -208,10 +208,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
try_lock()
{
int __ret = __glibcxx_rwlock_trywrlock(&_M_rwlock);
- if (__ret == EBUSY) return false;
- // Errors not handled: EINVAL
+ if (__ret == 0)
+ return true;
+ if (__ret == EBUSY)
+ return false;
+ // Errors not handled: EINVAL, EDEADLK
__glibcxx_assert(__ret == 0);
- return true;
+ // try_lock() is not permitted to throw
+ return false;
}
void
@@ -520,23 +524,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
try_lock_until(const chrono::time_point<chrono::system_clock,
_Duration>& __atime)
{
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
-
- __gthread_time_t __ts =
- {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
-
+ struct timespec __ts = chrono::__to_timeout_timespec(__atime);
int __ret = __glibcxx_rwlock_timedwrlock(&_M_rwlock, &__ts);
- // On self-deadlock, we just fail to acquire the lock. Technically,
- // the program violated the precondition.
- if (__ret == ETIMEDOUT || __ret == EDEADLK)
+ if (__ret == 0)
+ return true;
+ if (__ret == ETIMEDOUT)
return false;
- // Errors not handled: EINVAL
+ // Errors not handled: EINVAL, EDEADLK
__glibcxx_assert(__ret == 0);
- return true;
+ return false;
}
#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK
@@ -546,24 +542,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
try_lock_until(const chrono::time_point<chrono::steady_clock,
_Duration>& __atime)
{
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
-
- __gthread_time_t __ts =
- {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
-
+ struct timespec __ts = chrono::__to_timeout_timespec(__atime);
int __ret = pthread_rwlock_clockwrlock(&_M_rwlock, CLOCK_MONOTONIC,
&__ts);
- // On self-deadlock, we just fail to acquire the lock. Technically,
- // the program violated the precondition.
- if (__ret == ETIMEDOUT || __ret == EDEADLK)
+ if (__ret == 0)
+ return true;
+ if (__ret == ETIMEDOUT)
return false;
- // Errors not handled: EINVAL
+ // Errors not handled: EINVAL, EDEADLK
__glibcxx_assert(__ret == 0);
- return true;
+ return false;
}
#endif
@@ -596,14 +584,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
try_lock_shared_until(const chrono::time_point<chrono::system_clock,
_Duration>& __atime)
{
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
-
- __gthread_time_t __ts =
- {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
+ struct timespec __ts = chrono::__to_timeout_timespec(__atime);
int __ret;
// Unlike for lock(), we are not allowed to throw an exception so if
@@ -615,18 +596,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// acquire the lock even if it would be logically free; however, this
// is allowed by the standard, and we made a "strong effort"
// (see C++14 30.4.1.4p26).
- // For cases where the implementation detects a deadlock we
- // intentionally block and timeout so that an early return isn't
- // mistaken for a spurious failure, which might help users realise
- // there is a deadlock.
do
__ret = __glibcxx_rwlock_timedrdlock(&_M_rwlock, &__ts);
- while (__ret == EAGAIN || __ret == EDEADLK);
+ while (__ret == EAGAIN);
+ if (__ret == 0)
+ return true;
if (__ret == ETIMEDOUT)
return false;
- // Errors not handled: EINVAL
+ // Errors not handled: EINVAL, EDEADLK
__glibcxx_assert(__ret == 0);
- return true;
+ return false;
}
#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK
@@ -636,24 +615,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
try_lock_shared_until(const chrono::time_point<chrono::steady_clock,
_Duration>& __atime)
{
- auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
- auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
-
- __gthread_time_t __ts =
- {
- static_cast<std::time_t>(__s.time_since_epoch().count()),
- static_cast<long>(__ns.count())
- };
-
+ struct timespec __ts = chrono::__to_timeout_timespec(__atime);
int __ret = pthread_rwlock_clockrdlock(&_M_rwlock, CLOCK_MONOTONIC,
&__ts);
- // On self-deadlock, we just fail to acquire the lock. Technically,
- // the program violated the precondition.
- if (__ret == ETIMEDOUT || __ret == EDEADLK)
+ // On self-deadlock, if _GLIBCXX_ASSERTIONS is not defined, we just
+ // fail to acquire the lock. Technically, the program violated the
+ // precondition.
+ if (__ret == 0)
+ return true;
+ if (__ret == ETIMEDOUT)
return false;
- // Errors not handled: EINVAL
+ // Errors not handled: EINVAL, EDEADLK
__glibcxx_assert(__ret == 0);
- return true;
+ return false;
}
#endif
diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
index 49ab910..5808911 100644
--- a/libstdc++-v3/include/std/span
+++ b/libstdc++-v3/include/std/span
@@ -376,7 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
else
static_assert(_Count <= extent);
using _Sp = span<element_type, _Count>;
- return _Sp{ _SizedPtr{this->data()} };
+ return _Sp(_SizedPtr{this->data()});
}
[[nodiscard]]
@@ -384,7 +384,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
first(size_type __count) const noexcept
{
__glibcxx_assert(__count <= size());
- return { this->data(), __count };
+ return span<element_type>(this->data(), __count);
}
template<size_t _Count>
@@ -397,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
else
static_assert(_Count <= extent);
using _Sp = span<element_type, _Count>;
- return _Sp{ _SizedPtr{this->data() + (this->size() - _Count)} };
+ return _Sp(_SizedPtr{this->data() + (this->size() - _Count)});
}
[[nodiscard]]
@@ -405,7 +405,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
last(size_type __count) const noexcept
{
__glibcxx_assert(__count <= size());
- return { this->data() + (this->size() - __count), __count };
+ return span<element_type>(this->data() + (this->size() - __count),
+ __count);
}
template<size_t _Offset, size_t _Count = dynamic_extent>
@@ -424,7 +425,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using _Sp = span<element_type, _S_subspan_extent<_Offset, _Count>()>;
if constexpr (_Count == dynamic_extent)
- return _Sp{ this->data() + _Offset, this->size() - _Offset };
+ return _Sp(this->data() + _Offset, this->size() - _Offset);
else
{
if constexpr (_Extent == dynamic_extent)
@@ -437,7 +438,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(_Count <= extent);
static_assert(_Count <= (extent - _Offset));
}
- return _Sp{ _SizedPtr{this->data() + _Offset} };
+ return _Sp(_SizedPtr{this->data() + _Offset});
}
}
@@ -454,7 +455,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_assert(__count <= size());
__glibcxx_assert(__offset + __count <= size());
}
- return {this->data() + __offset, __count};
+ return span<element_type>(this->data() + __offset, __count);
}
private:
@@ -476,6 +477,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
// deduction guides
+ namespace __detail
+ {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4351. integral-constant-like needs more remove_cvref_t
+ template<typename _Tp>
+ concept __integral_constant_like =
+ is_integral_v<remove_cvref_t<decltype(_Tp::value)>>
+ && !is_same_v<bool, remove_cvref_t<decltype(_Tp::value)>>
+ && convertible_to<_Tp, decltype(_Tp::value)>
+ && equality_comparable_with<_Tp, decltype(_Tp::value)>
+ && bool_constant<_Tp() == _Tp::value>::value
+ && bool_constant<static_cast<decltype(_Tp::value)>(_Tp()) == _Tp::value>
+ ::value;
+
+ template<typename _Tp>
+ constexpr size_t __maybe_static_ext = dynamic_extent;
+
+ template<__integral_constant_like _Tp>
+ constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value};
+ }
template<typename _Type, size_t _ArrayExtent>
span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>;
@@ -489,7 +510,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<contiguous_iterator _Iter, typename _End>
span(_Iter, _End)
- -> span<remove_reference_t<iter_reference_t<_Iter>>>;
+ -> span<remove_reference_t<iter_reference_t<_Iter>>,
+ __detail::__maybe_static_ext<_End>>;
template<ranges::contiguous_range _Range>
span(_Range &&)
diff --git a/libstdc++-v3/include/std/spanstream b/libstdc++-v3/include/std/spanstream
index 23a340a..fbb40ff 100644
--- a/libstdc++-v3/include/std/spanstream
+++ b/libstdc++-v3/include/std/spanstream
@@ -152,7 +152,7 @@ template<typename _CharT, typename _Traits>
if (__way == ios_base::beg)
{
- if (0 <= __off && __off <= _M_buf.size())
+ if (0 <= __off && (size_t)__off <= _M_buf.size())
{
if (__which & ios_base::in)
this->setg(this->eback(), this->eback() + __off, this->egptr());
@@ -188,7 +188,7 @@ template<typename _CharT, typename _Traits>
if (__builtin_add_overflow(__base, __off, &__off)) [[unlikely]]
return __ret;
- if (__off < 0 || __off > _M_buf.size()) [[unlikely]]
+ if (__off < 0 || (size_t)__off > _M_buf.size()) [[unlikely]]
return __ret;
if (__which & ios_base::in)
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 5cea476..507b974 100644
--- a/libstdc++-v3/include/std/stack
+++ b/libstdc++-v3/include/std/stack
@@ -61,11 +61,61 @@
#include <bits/requires_hosted.h> // containers
-#include <deque>
-#include <bits/stl_stack.h>
-
#define __glibcxx_want_adaptor_iterator_pair_constructor
#define __glibcxx_want_containers_ranges
#include <bits/version.h>
+#include <deque>
+#include <bits/stl_stack.h>
+
+#ifdef __glibcxx_format_ranges // C++ >= 23 && HOSTED
+#include <bits/formatfwd.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ // Standard does not constrain accepted _CharT, we do so we can
+ // befriend specializations.
+ template<__format::__char _CharT, typename _Tp,
+ formattable<_CharT> _Container>
+ struct formatter<stack<_Tp, _Container>, _CharT>
+ {
+ private:
+ using __maybe_const_adaptor
+ = __conditional_t<
+ __format::__const_formattable_range<_Container, _CharT>,
+ const stack<_Tp, _Container>, stack<_Tp, _Container>>;
+
+ public:
+ // Standard declares this as template accepting unconstrained
+ // ParseContext type.
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ { return _M_f.parse(__pc); }
+
+ // Standard declares this as template accepting unconstrained
+ // FormatContext type.
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(__maybe_const_adaptor& __a,
+ basic_format_context<_Out, _CharT>& __fc) const
+ { return _M_f.format(__a.c, __fc); }
+
+ private:
+ // Standard uses formatter<ref_view<_Container>, _CharT>.
+ range_formatter<_Tp, _CharT> _M_f;
+ };
+
+#if __glibcxx_print >= 202406L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4398. enable_nonlocking_formatter_optimization should be disabled for container adaptors
+ template<typename _Tp, typename _Container>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<stack<_Tp, _Container>> = false;
+#endif
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // __glibcxx_format_ranges
+
+
#endif /* _GLIBCXX_STACK */
diff --git a/libstdc++-v3/include/std/stacktrace b/libstdc++-v3/include/std/stacktrace
index 4911222..587a163 100644
--- a/libstdc++-v3/include/std/stacktrace
+++ b/libstdc++-v3/include/std/stacktrace
@@ -208,6 +208,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (_S_current(__cb, std::__addressof(__ret)))
__ret._M_clear();
+ else
+ __ret._M_trim();
}
return __ret;
}
@@ -224,6 +226,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (_S_current(__cb, std::__addressof(__ret), __skip))
__ret._M_clear();
+ else
+ __ret._M_trim();
}
return __ret;
@@ -260,6 +264,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
}
+ else
+ __ret._M_trim();
}
return __ret;
}
@@ -651,6 +657,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
};
+ void
+ _M_trim() noexcept
+ {
+ // libbacktrace adds an invalid -1UL entry at the end, remove it.
+ if (!empty() && !end()[-1])
+ _M_impl._M_resize(size() - 1, _M_alloc);
+ }
+
[[no_unique_address]] allocator_type _M_alloc{};
_Impl _M_impl{};
@@ -669,13 +683,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline ostream&
operator<<(ostream& __os, const stacktrace_entry& __f)
{
+ if (!__f) [[unlikely]]
+ return __os << "<unknown>";
+
string __desc, __file;
int __line;
- if (__f._M_get_info(&__desc, &__file, &__line))
+ if (__f._M_get_info(&__desc, &__file, &__line)) [[likely]]
{
- __os.width(4);
- __os << __desc << " at " << __file << ':' << __line;
+ __os << ' ';
+ if (__desc.empty()) [[unlikely]]
+ __os << "<unknown>";
+ else
+ __os << __desc;
+ if (!__file.empty()) [[likely]]
+ __os << " at " << __file << ':' << __line;
}
+
+ struct _Flag_guard // Set and restore hex format
+ {
+ _Flag_guard(ios& __s) : _M_ios(__s) { }
+ ~_Flag_guard() { _M_ios.setf(_M_f); }
+
+ ios& _M_ios;
+ ios::fmtflags _M_f = _M_ios.setf(ios::hex, ios::basefield);
+ };
+ _Flag_guard __g(__os);
+ __os << " [0x" << __f.native_handle() << ']';
return __os;
}
@@ -683,7 +716,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline ostream&
operator<<(ostream& __os, const basic_stacktrace<_Allocator>& __st)
{
- for (stacktrace::size_type __i = 0; __i < __st.size(); ++__i)
+ using size_type = typename basic_stacktrace<_Allocator>::size_type;
+ for (size_type __i = 0, __size = __st.size(); __i < __size; ++__i)
{
__os.width(4);
__os << __i << "# " << __st[__i] << '\n';
@@ -765,6 +799,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__format::_Spec<char> _M_spec;
};
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<stacktrace_entry> = true;
+#endif
+
template<typename _Allocator>
class formatter<basic_stacktrace<_Allocator>>
{
@@ -790,6 +830,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
};
+#if __glibcxx_print >= 202406L
+ template<typename _Allocator>
+ constexpr bool
+ enable_nonlocking_formatter_optimization<basic_stacktrace<_Allocator>> = true;
+#endif
+
namespace pmr
{
using stacktrace
diff --git a/libstdc++-v3/include/std/stop_token b/libstdc++-v3/include/std/stop_token
index 1225b3a..b593daf 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>
@@ -649,7 +648,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Callback>
stop_callback(stop_token, _Callback) -> stop_callback<_Callback>;
+ /// @cond undocumented
+ namespace __detail::__variant
+ {
+ template<typename> struct _Never_valueless_alt; // see <variant>
+
+ // Provide the strong exception-safety guarantee when emplacing a
+ // stop_token or stop_source into a variant.
+ template<>
+ struct _Never_valueless_alt<std::stop_token>
+ : true_type
+ { };
+
+ template<>
+ struct _Never_valueless_alt<std::stop_source>
+ : true_type
+ { };
+ } // namespace __detail::__variant
+ /// @endcond
+
_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 7186471..918b415 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -51,7 +51,6 @@
#include <bits/stl_function.h> // For less
#include <ext/numeric_traits.h>
#include <bits/stl_algobase.h>
-#include <bits/refwrap.h>
#include <bits/range_access.h>
#include <bits/basic_string.h>
#include <bits/basic_string.tcc>
@@ -64,6 +63,7 @@
#define __glibcxx_want_erase_if
#define __glibcxx_want_nonmember_container_access
#define __glibcxx_want_string_resize_and_overwrite
+#define __glibcxx_want_string_subview
#define __glibcxx_want_string_udls
#define __glibcxx_want_to_string
#include <bits/version.h>
@@ -96,33 +96,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _CharT, typename _Traits, typename _Alloc,
typename _Predicate>
- _GLIBCXX20_CONSTEXPR
- inline typename basic_string<_CharT, _Traits, _Alloc>::size_type
+ constexpr typename basic_string<_CharT, _Traits, _Alloc>::size_type
erase_if(basic_string<_CharT, _Traits, _Alloc>& __cont, _Predicate __pred)
{
using namespace __gnu_cxx;
const auto __osz = __cont.size();
const auto __end = __cont.end();
auto __removed = std::__remove_if(__cont.begin(), __end,
- __ops::__pred_iter(std::ref(__pred)));
+ std::move(__pred));
__cont.erase(__removed, __end);
return __osz - __cont.size();
}
template<typename _CharT, typename _Traits, typename _Alloc,
typename _Up _GLIBCXX26_DEF_VAL_T(_CharT)>
- _GLIBCXX20_CONSTEXPR
- inline typename basic_string<_CharT, _Traits, _Alloc>::size_type
+ constexpr typename basic_string<_CharT, _Traits, _Alloc>::size_type
erase(basic_string<_CharT, _Traits, _Alloc>& __cont, const _Up& __value)
- {
- using namespace __gnu_cxx;
- const auto __osz = __cont.size();
- const auto __end = __cont.end();
- auto __removed = std::__remove_if(__cont.begin(), __end,
- __ops::__iter_equals_val(__value));
- __cont.erase(__removed, __end);
- return __osz - __cont.size();
- }
+ { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cpp_lib_erase_if
diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view
index 842f6ad..b226544 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -40,9 +40,10 @@
#define __glibcxx_want_constexpr_char_traits
#define __glibcxx_want_constexpr_string_view
#define __glibcxx_want_freestanding_string_view
-#define __glibcxx_want_string_view
#define __glibcxx_want_starts_ends_with
#define __glibcxx_want_string_contains
+#define __glibcxx_want_string_subview
+#define __glibcxx_want_string_view
#include <bits/version.h>
#if __cplusplus >= 201703L
@@ -342,6 +343,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return basic_string_view{_M_str + __pos, __rlen};
}
+#ifdef __glibcxx_string_subview // >= C++26
+ [[nodiscard]]
+ constexpr basic_string_view
+ subview(size_type __pos = 0, size_type __n = npos) const
+ { return substr(__pos, __n); }
+#endif
+
[[nodiscard]]
constexpr int
compare(basic_string_view __str) const noexcept
diff --git a/libstdc++-v3/include/std/syncstream b/libstdc++-v3/include/std/syncstream
index e2b5a19..1e17597 100644
--- a/libstdc++-v3/include/std/syncstream
+++ b/libstdc++-v3/include/std/syncstream
@@ -46,7 +46,6 @@
#include <bits/alloc_traits.h>
#include <bits/allocator.h>
#include <bits/functexcept.h>
-#include <bits/functional_hash.h>
#include <bits/std_mutex.h>
namespace std _GLIBCXX_VISIBILITY(default)
@@ -199,11 +198,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __mutex
{
#if _GLIBCXX_HAS_GTHREADS
- mutex* _M_mtx;
+ mutex* _M_mtx = nullptr;
- __mutex(void* __t)
- : _M_mtx(__t ? &_S_get_mutex(__t) : nullptr)
- { }
+ __mutex(void* __t) // __t is the underlying sbuf, as hash seed.
+ {
+ extern mutex& __syncbuf_get_mutex(void*); // in src/c++20/syncbuf.cc
+ if (__t) _M_mtx = &__syncbuf_get_mutex(__t);
+ }
void
swap(__mutex& __other) noexcept
@@ -220,17 +221,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_M_mtx->unlock();
}
-
- // FIXME: This should be put in the .so
- static mutex&
- _S_get_mutex(void* __t)
- {
- const unsigned char __mask = 0xf;
- static mutex __m[__mask + 1];
-
- auto __key = _Hash_impl::hash(__t) & __mask;
- return __m[__key];
- }
#else
__mutex(void*) { }
void swap(__mutex&&) noexcept { }
diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread
index d2f91ad..ccab1e4 100644
--- a/libstdc++-v3/include/std/thread
+++ b/libstdc++-v3/include/std/thread
@@ -294,10 +294,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
stop_source _M_stop_source;
thread _M_thread;
};
+
+ /// @cond undocumented
+ namespace __detail::__variant
+ {
+ template<typename> struct _Never_valueless_alt; // see <variant>
+
+ // Provide the strong exception-safety guarantee when emplacing a
+ // jthread into a variant.
+ template<>
+ struct _Never_valueless_alt<std::jthread>
+ : true_type
+ { };
+ } // namespace __detail::__variant
+ /// @endcond
#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 +323,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,41 +351,46 @@ _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:
__format::_Spec<_CharT> _M_spec;
};
+
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<thread::id> = true;
+#endif
+
#endif // __cpp_lib_formatters
/// @} group threads
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 2e69af1..d4db125 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -1984,14 +1984,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class tuple<>
{
public:
+ // We need the default since we're going to define no-op
+ // allocator constructors.
+ tuple() = default;
+ // Defaulted copy operations to maintain trivial copyability.
+ // and support non-const assignment expressions.
+ tuple(const tuple&) = default;
+ tuple& operator=(const tuple&) = default;
+
_GLIBCXX20_CONSTEXPR
void swap(tuple&) noexcept { /* no-op */ }
+
#if __cpp_lib_ranges_zip // >= C++23
- constexpr void swap(const tuple&) const noexcept { /* no-op */ }
+ template<same_as<tuple> _Tuple = tuple>
+ constexpr const tuple&
+ operator=(const _Tuple&) const noexcept
+ { return *this; }
+
+ constexpr void swap(const tuple&) const noexcept
+ { /* no-op */ }
#endif
- // We need the default since we're going to define no-op
- // allocator constructors.
- tuple() = default;
+
// No-op allocator constructors.
template<typename _Alloc>
_GLIBCXX20_CONSTEXPR
@@ -1999,6 +2012,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Alloc>
_GLIBCXX20_CONSTEXPR
tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
+
+#if __cpp_lib_tuple_like // >= C++23
+ template<__tuple_like _UTuple>
+ requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
+ && (!is_same_v<remove_cvref_t<_UTuple>, allocator_arg_t>)
+ && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
+ constexpr
+ tuple(_UTuple&&) noexcept { }
+
+ template<typename _Alloc, __tuple_like _UTuple>
+ requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
+ && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
+ constexpr
+ tuple(allocator_arg_t, const _Alloc&, _UTuple&&) noexcept { }
+
+ template<__tuple_like _UTuple>
+ requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
+ && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
+ constexpr tuple&
+ operator=(_UTuple&&) noexcept
+ { return *this; }
+
+ template<__tuple_like _UTuple>
+ requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
+ && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
+ constexpr const tuple&
+ operator=(_UTuple&&) const noexcept
+ { return *this; }
+
+ template<__tuple_like _UTuple>
+ requires (!__is_tuple_v<_UTuple>) && (tuple_size_v<_UTuple> == 0)
+ [[nodiscard]]
+ friend constexpr bool
+ operator==(const tuple&, const _UTuple&) noexcept
+ { return true; }
+
+ template<__tuple_like _UTuple>
+ requires (!__is_tuple_v<_UTuple>) && (tuple_size_v<_UTuple> == 0)
+ friend constexpr strong_ordering
+ operator<=>(const tuple&, const _UTuple&) noexcept
+ { return strong_ordering::equal; }
+#endif // C++23
};
#if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
@@ -2681,54 +2736,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
/// @cond undocumented
- template<size_t, typename, typename, size_t>
- struct __make_tuple_impl;
-
- template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
- struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
- : __make_tuple_impl<_Idx + 1,
- tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
- _Tuple, _Nm>
- { };
+ template<typename _Tuple, typename _Idx_tuple>
+ struct __do_make_tuple;
- template<size_t _Nm, typename _Tuple, typename... _Tp>
- struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
+ template<typename _Tuple, size_t... _Idx>
+ struct __do_make_tuple<_Tuple, _Index_tuple<_Idx...>>
{
- typedef tuple<_Tp...> __type;
+ using __type = tuple<__tuple_element_t<_Idx, _Tuple>...>;
};
- template<typename _Tuple>
- struct __do_make_tuple
- : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
- { };
-
// Returns the std::tuple equivalent of a tuple-like type.
- template<typename _Tuple>
+ template<typename _Tuple,
+ typename _Tup = __remove_cvref_t<_Tuple>,
+ typename _Indices = _Build_index_tuple<tuple_size<_Tup>::value>>
struct __make_tuple
- : public __do_make_tuple<__remove_cvref_t<_Tuple>>
+ : __do_make_tuple<_Tup, typename _Indices::__type>
{ };
- // Combines several std::tuple's into a single one.
+ // Combines several std::tuple types into a single one.
template<typename...>
struct __combine_tuples;
template<>
struct __combine_tuples<>
{
- typedef tuple<> __type;
+ using __type = tuple<>;
};
template<typename... _Ts>
struct __combine_tuples<tuple<_Ts...>>
{
- typedef tuple<_Ts...> __type;
+ using __type = tuple<_Ts...>;
+ };
+
+ template<typename... _T1s, typename... _T2s>
+ struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>>
+ {
+ using __type = tuple<_T1s..., _T2s...>;
};
- template<typename... _T1s, typename... _T2s, typename... _Rem>
- struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
+ template<typename... _T1s, typename... _T2s, typename... _T3s,
+ typename... _Rem>
+ struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, tuple<_T3s...>,
+ _Rem...>
{
- typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
- _Rem...>::__type __type;
+ using _First = tuple<_T1s..., _T2s..., _T3s...>;
+ using _Second = typename __combine_tuples<_Rem...>::__type;
+ using __type = typename __combine_tuples<_First, _Second>::__type;
};
// Computes the result type of tuple_cat given a set of tuple-like types.
@@ -2835,6 +2889,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ __x.swap(__y); }
#if __cpp_lib_ranges_zip // >= C++23
+ /// Exchange the values of two const tuples (if const elements can be swapped)
template<typename... _Elements>
requires (is_swappable_v<const _Elements> && ...)
constexpr void
@@ -2844,7 +2899,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif // C++23
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
- /// Exchange the values of two const tuples (if const elements can be swapped)
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2766. Swapping non-swappable types
template<typename... _Elements>
_GLIBCXX20_CONSTEXPR
typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
@@ -2939,19 +2995,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..3f0bcc4e 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -41,11 +41,14 @@
#define __glibcxx_want_bool_constant
#define __glibcxx_want_bounded_array_traits
+#define __glibcxx_want_common_reference
+#define __glibcxx_want_constant_wrapper
#define __glibcxx_want_has_unique_object_representations
#define __glibcxx_want_integral_constant_callable
#define __glibcxx_want_is_aggregate
#define __glibcxx_want_is_constant_evaluated
#define __glibcxx_want_is_final
+#define __glibcxx_want_is_implicit_lifetime
#define __glibcxx_want_is_invocable
#define __glibcxx_want_is_layout_compatible
#define __glibcxx_want_is_nothrow_convertible
@@ -280,11 +283,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 +293,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).
@@ -459,6 +467,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_3>
: public true_type { };
#endif
+
+#if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
+ __extension__
+ template<>
+ struct __is_integral_helper<__int128>
+ : public true_type { };
+
+ __extension__
+ template<>
+ struct __is_integral_helper<unsigned __int128>
+ : public true_type { };
+#endif
+
/// @endcond
/// is_integral
@@ -514,7 +535,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public true_type { };
#endif
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
+#ifdef _GLIBCXX_USE_FLOAT128
template<>
struct __is_floating_point_helper<__float128>
: public true_type { };
@@ -805,7 +826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Check if a type is one of the signed integer types.
__extension__
template<typename _Tp>
- using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>,
+ using __is_signed_integer = __is_one_of<_Tp,
signed char, signed short, signed int, signed long,
signed long long
#if defined(__GLIBCXX_TYPE_INT_N_0)
@@ -820,12 +841,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if defined(__GLIBCXX_TYPE_INT_N_3)
, signed __GLIBCXX_TYPE_INT_N_3
#endif
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+ , signed __int128
+#endif
>;
// Check if a type is one of the unsigned integer types.
__extension__
template<typename _Tp>
- using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>,
+ using __is_unsigned_integer = __is_one_of<_Tp,
unsigned char, unsigned short, unsigned int, unsigned long,
unsigned long long
#if defined(__GLIBCXX_TYPE_INT_N_0)
@@ -840,11 +864,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if defined(__GLIBCXX_TYPE_INT_N_3)
, unsigned __GLIBCXX_TYPE_INT_N_3
#endif
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+ , unsigned __int128
+#endif
>;
// Check if a type is one of the signed or unsigned integer types.
+ // i.e. an integral type except bool, char, wchar_t, and charN_t.
template<typename _Tp>
- using __is_standard_integer
+ using __is_signed_or_unsigned_integer
= __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>;
// __void_t (std::void_t for C++11)
@@ -1036,9 +1064,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 +1128,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 +1190,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 +1498,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 +1514,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>
@@ -1896,6 +1950,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __make_unsigned<__GLIBCXX_TYPE_INT_N_3>
{ using __type = unsigned __GLIBCXX_TYPE_INT_N_3; };
#endif
+#if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
+ __extension__
+ template<>
+ struct __make_unsigned<__int128>
+ { using __type = unsigned __int128; };
+#endif
// Select between integral and enum: not possible to be both.
template<typename _Tp,
@@ -1942,8 +2002,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: __make_unsigned_selector_base
{
// With -fshort-enums, an enum may be as small as a char.
+ __extension__
using _UInts = _List<unsigned char, unsigned short, unsigned int,
- unsigned long, unsigned long long>;
+ unsigned long, unsigned long long
+#ifdef __SIZEOF_INT128__
+ , unsigned __int128
+#endif
+ >;
using __unsigned_type = typename __select<sizeof(_Tp), _UInts>::__type;
@@ -2056,6 +2121,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_3>
{ using __type = __GLIBCXX_TYPE_INT_N_3; };
#endif
+#if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
+ __extension__
+ template<>
+ struct __make_signed<unsigned __int128>
+ { using __type = __int128; };
+#endif
// Select between integral and enum: not possible to be both.
template<typename _Tp,
@@ -3212,7 +3283,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 +3338,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 +3652,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 +3685,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 +3734,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 +3798,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;
@@ -3959,6 +4062,22 @@ template<typename _Ret, typename _Fn, typename... _Args>
# endif
#endif
+#ifdef __cpp_lib_is_implicit_lifetime // C++ >= 23
+ /// True if the type is an implicit-lifetime type.
+ /// @since C++23
+
+ template<typename _Tp>
+ struct is_implicit_lifetime
+ : bool_constant<__builtin_is_implicit_lifetime(_Tp)>
+ { };
+
+ /// @ingroup variable_templates
+ /// @since C++23
+ template<typename _Tp>
+ inline constexpr bool is_implicit_lifetime_v
+ = __builtin_is_implicit_lifetime(_Tp);
+#endif
+
#ifdef __cpp_lib_reference_from_temporary // C++ >= 23 && ref_{converts,constructs}_from_temp
/// True if _Tp is a reference type, a _Up value can be bound to _Tp in
/// direct-initialization, and a temporary object would be bound to
@@ -4002,7 +4121,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
@@ -4113,7 +4233,7 @@ template<typename _Ret, typename _Fn, typename... _Args>
{ using type = _Tp0; };
/// @cond undocumented
- template<typename _Tp1, typename _Tp2, int _Bullet = 1, typename = void>
+ template<typename _Tp1, typename _Tp2, int _Bullet = 1>
struct __common_reference_impl
: __common_reference_impl<_Tp1, _Tp2, _Bullet + 1>
{ };
@@ -4126,46 +4246,38 @@ template<typename _Ret, typename _Fn, typename... _Args>
// If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, ...
template<typename _Tp1, typename _Tp2>
- struct __common_reference_impl<_Tp1&, _Tp2&, 1,
- void_t<__common_ref<_Tp1&, _Tp2&>>>
- { using type = __common_ref<_Tp1&, _Tp2&>; };
-
- template<typename _Tp1, typename _Tp2>
- struct __common_reference_impl<_Tp1&&, _Tp2&&, 1,
- void_t<__common_ref<_Tp1&&, _Tp2&&>>>
- { using type = __common_ref<_Tp1&&, _Tp2&&>; };
-
- template<typename _Tp1, typename _Tp2>
- struct __common_reference_impl<_Tp1&, _Tp2&&, 1,
- void_t<__common_ref<_Tp1&, _Tp2&&>>>
- { using type = __common_ref<_Tp1&, _Tp2&&>; };
-
- template<typename _Tp1, typename _Tp2>
- struct __common_reference_impl<_Tp1&&, _Tp2&, 1,
- void_t<__common_ref<_Tp1&&, _Tp2&>>>
- { using type = __common_ref<_Tp1&&, _Tp2&>; };
+ requires is_reference_v<_Tp1> && is_reference_v<_Tp2>
+ && requires { typename __common_ref<_Tp1, _Tp2>; }
+#if __cpp_lib_common_reference // C++ >= 20
+ && is_convertible_v<add_pointer_t<_Tp1>,
+ add_pointer_t<__common_ref<_Tp1, _Tp2>>>
+ && is_convertible_v<add_pointer_t<_Tp2>,
+ add_pointer_t<__common_ref<_Tp1, _Tp2>>>
+#endif
+ struct __common_reference_impl<_Tp1, _Tp2, 1>
+ { using type = __common_ref<_Tp1, _Tp2>; };
// Otherwise, if basic_common_reference<...>::type is well-formed, ...
template<typename _Tp1, typename _Tp2>
- struct __common_reference_impl<_Tp1, _Tp2, 2,
- void_t<__basic_common_ref<_Tp1, _Tp2>>>
+ requires requires { typename __basic_common_ref<_Tp1, _Tp2>; }
+ struct __common_reference_impl<_Tp1, _Tp2, 2>
{ using type = __basic_common_ref<_Tp1, _Tp2>; };
// Otherwise, if COND-RES(T1, T2) is well-formed, ...
template<typename _Tp1, typename _Tp2>
- struct __common_reference_impl<_Tp1, _Tp2, 3,
- void_t<__cond_res<_Tp1, _Tp2>>>
+ requires requires { typename __cond_res<_Tp1, _Tp2>; }
+ struct __common_reference_impl<_Tp1, _Tp2, 3>
{ using type = __cond_res<_Tp1, _Tp2>; };
// Otherwise, if common_type_t<T1, T2> is well-formed, ...
template<typename _Tp1, typename _Tp2>
- struct __common_reference_impl<_Tp1, _Tp2, 4,
- void_t<common_type_t<_Tp1, _Tp2>>>
+ requires requires { typename common_type_t<_Tp1, _Tp2>; }
+ struct __common_reference_impl<_Tp1, _Tp2, 4>
{ using type = common_type_t<_Tp1, _Tp2>; };
// Otherwise, there shall be no member type.
template<typename _Tp1, typename _Tp2>
- struct __common_reference_impl<_Tp1, _Tp2, 5, void>
+ struct __common_reference_impl<_Tp1, _Tp2, 5>
{ };
// Otherwise, if sizeof...(T) is greater than two, ...
@@ -4184,7 +4296,399 @@ template<typename _Ret, typename _Fn, typename... _Args>
{ };
/// @endcond
-#endif // C++2a
+#endif // C++20
+
+#if __cplusplus >= 201103L
+ // Stores a tuple of indices. Used by tuple and pair, and by bind() to
+ // extract the elements in a tuple.
+ template<size_t... _Indexes> struct _Index_tuple { };
+
+ // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
+ template<size_t _Num>
+ struct _Build_index_tuple
+ {
+#if __has_builtin(__make_integer_seq)
+ template<typename, size_t... _Indices>
+ using _IdxTuple = _Index_tuple<_Indices...>;
+
+ // Clang defines __make_integer_seq for this purpose.
+ using __type = __make_integer_seq<_IdxTuple, size_t, _Num>;
+#else
+ // For GCC and other compilers, use __integer_pack instead.
+ using __type = _Index_tuple<__integer_pack(_Num)...>;
+#endif
+ };
+#endif // C++11
+
+#ifdef __cpp_lib_constant_wrapper // C++ >= 26
+ template<typename _Tp>
+ struct _CwFixedValue
+ {
+ using __type = _Tp;
+
+ constexpr
+ _CwFixedValue(__type __v) noexcept
+ : _M_data(__v) { }
+
+ __type _M_data;
+ };
+
+ template<typename _Tp, size_t _Extent>
+ struct _CwFixedValue<_Tp[_Extent]>
+ {
+ using __type = _Tp[_Extent];
+
+ constexpr
+ _CwFixedValue(_Tp (&__arr)[_Extent]) noexcept
+ : _CwFixedValue(__arr, typename _Build_index_tuple<_Extent>::__type())
+ { }
+
+ template<size_t... _Indices>
+ constexpr
+ _CwFixedValue(_Tp (&__arr)[_Extent], _Index_tuple<_Indices...>) noexcept
+ : _M_data{__arr[_Indices]...}
+ { }
+
+ _Tp _M_data[_Extent];
+ };
+
+ template<typename _Tp, size_t _Extent>
+ _CwFixedValue(_Tp (&)[_Extent]) -> _CwFixedValue<_Tp[_Extent]>;
+
+ template<_CwFixedValue _Xv,
+ typename = typename decltype(_CwFixedValue(_Xv))::__type>
+ struct constant_wrapper;
+
+ template<typename _Tp>
+ concept _ConstExprParam = requires
+ {
+ typename constant_wrapper<_Tp::value>;
+ };
+
+ struct _CwOperators
+ {
+ template<_ConstExprParam _Tp>
+ friend constexpr auto
+ operator+(_Tp) noexcept -> constant_wrapper<(+_Tp::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Tp>
+ friend constexpr auto
+ operator-(_Tp) noexcept -> constant_wrapper<(-_Tp::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Tp>
+ friend constexpr auto
+ operator~(_Tp) noexcept -> constant_wrapper<(~_Tp::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Tp>
+ friend constexpr auto
+ operator!(_Tp) noexcept -> constant_wrapper<(!_Tp::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Tp>
+ friend constexpr auto
+ operator&(_Tp) noexcept -> constant_wrapper<(&_Tp::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Tp>
+ friend constexpr auto
+ operator*(_Tp) noexcept -> constant_wrapper<(*_Tp::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator+(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value + _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator-(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value - _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator*(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value * _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator/(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value / _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator%(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value % _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator<<(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value << _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator>>(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value >> _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator&(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value & _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator|(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value | _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator^(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value ^ _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ requires (!is_constructible_v<bool, decltype(_Left::value)>
+ || !is_constructible_v<bool, decltype(_Right::value)>)
+ friend constexpr auto
+ operator&&(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value && _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ requires (!is_constructible_v<bool, decltype(_Left::value)>
+ || !is_constructible_v<bool, decltype(_Right::value)>)
+ friend constexpr auto
+ operator||(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value || _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator<=>(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value <=> _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator<(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value < _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator<=(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value <= _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator==(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value == _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator!=(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value != _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator>(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value > _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator>=(_Left, _Right) noexcept
+ -> constant_wrapper<(_Left::value >= _Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator,(_Left, _Right) noexcept = delete;
+
+ template<_ConstExprParam _Left, _ConstExprParam _Right>
+ friend constexpr auto
+ operator->*(_Left, _Right) noexcept
+ -> constant_wrapper<_Left::value->*(_Right::value)>
+ { return {}; }
+
+ template<_ConstExprParam _Tp, _ConstExprParam... _Args>
+ constexpr auto
+ operator()(this _Tp, _Args...) noexcept
+ requires
+ requires(_Args...) { constant_wrapper<_Tp::value(_Args::value...)>(); }
+ { return constant_wrapper<_Tp::value(_Args::value...)>{}; }
+
+ template<_ConstExprParam _Tp, _ConstExprParam... _Args>
+ constexpr auto
+ operator[](this _Tp, _Args...) noexcept
+ -> constant_wrapper<(_Tp::value[_Args::value...])>
+ { return {}; }
+
+ template<_ConstExprParam _Tp>
+ constexpr auto
+ operator++(this _Tp) noexcept
+ requires requires(_Tp::value_type __x) { ++__x; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return ++__x; }()>{};
+ }
+
+ template<_ConstExprParam _Tp>
+ constexpr auto
+ operator++(this _Tp, int) noexcept
+ requires requires(_Tp::value_type __x) { __x++; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x++; }()>{};
+ }
+
+ template<_ConstExprParam _Tp>
+ constexpr auto
+ operator--(this _Tp) noexcept
+ requires requires(_Tp::value_type __x) { --__x; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return --__x; }()>{};
+ }
+
+ template<_ConstExprParam _Tp>
+ constexpr auto
+ operator--(this _Tp, int) noexcept
+ requires requires(_Tp::value_type __x) { __x--; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x--; }()>{};
+ }
+
+ template<_ConstExprParam _Tp, _ConstExprParam _Right>
+ constexpr auto
+ operator+=(this _Tp, _Right) noexcept
+ requires requires(_Tp::value_type __x) { __x += _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x += _Right::value; }()>{};
+ }
+
+ template<_ConstExprParam _Tp, _ConstExprParam _Right>
+ constexpr auto
+ operator-=(this _Tp, _Right) noexcept
+ requires requires(_Tp::value_type __x) { __x -= _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x -= _Right::value; }()>{};
+ }
+
+ template<_ConstExprParam _Tp, _ConstExprParam _Right>
+ constexpr auto
+ operator*=(this _Tp, _Right) noexcept
+ requires requires(_Tp::value_type __x) { __x *= _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x *= _Right::value; }()>{};
+ }
+
+ template<_ConstExprParam _Tp, _ConstExprParam _Right>
+ constexpr auto
+ operator/=(this _Tp, _Right) noexcept
+ requires requires(_Tp::value_type __x) { __x /= _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x /= _Right::value; }()>{};
+ }
+
+ template<_ConstExprParam _Tp, _ConstExprParam _Right>
+ constexpr auto
+ operator%=(this _Tp, _Right) noexcept
+ requires requires(_Tp::value_type __x) { __x %= _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x %= _Right::value; }()>{};
+ }
+
+ template<_ConstExprParam _Tp, _ConstExprParam _Right>
+ constexpr auto
+ operator&=(this _Tp, _Right) noexcept
+ requires requires(_Tp::value_type __x) { __x &= _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x &= _Right::value; }()>{};
+ }
+
+ template<_ConstExprParam _Tp, _ConstExprParam _Right>
+ constexpr auto
+ operator|=(this _Tp, _Right) noexcept
+ requires requires(_Tp::value_type __x) { __x |= _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x |= _Right::value; }()>{};
+ }
+
+ template<_ConstExprParam _Tp, _ConstExprParam _Right>
+ constexpr auto
+ operator^=(this _Tp, _Right) noexcept
+ requires requires(_Tp::value_type __x) { __x ^= _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x ^= _Right::value; }()>{};
+ }
+
+ template<_ConstExprParam _Tp, _ConstExprParam _Right>
+ constexpr auto
+ operator<<=(this _Tp, _Right) noexcept
+ requires requires(_Tp::value_type __x) { __x <<= _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x <<= _Right::value; }()>{};
+ }
+
+ template<_ConstExprParam _Tp, _ConstExprParam _Right>
+ constexpr auto
+ operator>>=(this _Tp, _Right) noexcept
+ requires requires(_Tp::value_type __x) { __x >>= _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = _Tp::value; return __x >>= _Right::value; }()>{};
+ }
+ };
+
+ template<_CwFixedValue _Xv, typename>
+ struct constant_wrapper : _CwOperators
+ {
+ static constexpr const auto& value = _Xv._M_data;
+ using type = constant_wrapper;
+ using value_type = typename decltype(_Xv)::__type;
+
+ template<_ConstExprParam _Right>
+ constexpr auto
+ operator=(_Right) const noexcept
+ requires requires(value_type __x) { __x = _Right::value; }
+ {
+ return constant_wrapper<
+ [] { auto __x = value; return __x = _Right::value; }()>{};
+ }
+
+ constexpr
+ operator decltype(value)() const noexcept
+ { return value; }
+ };
+
+ template<_CwFixedValue _Tp>
+ constexpr auto cw = constant_wrapper<_Tp>{};
+#endif
/// @} group metaprogramming
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index 1c15c75..0f6dd82 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -78,7 +78,7 @@
#include <bits/utility.h>
#if __cplusplus >= 202002L
-#include <ext/numeric_traits.h> // __is_standard_integer, __int_traits
+#include <bits/intcmp.h>
#endif
#if __cplusplus > 202302L
@@ -98,6 +98,7 @@
#define __glibcxx_want_tuple_element_t
#define __glibcxx_want_tuples_by_type
#define __glibcxx_want_unreachable
+#define __glibcxx_want_observable_checkpoint
#define __glibcxx_want_tuple_like
#define __glibcxx_want_constrained_equality
#include <bits/version.h>
@@ -128,80 +129,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void as_const(const _Tp&&) = delete;
#endif
-#ifdef __cpp_lib_integer_comparison_functions // C++ >= 20
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_equal(_Tp __t, _Up __u) noexcept
- {
- static_assert(__is_standard_integer<_Tp>::value);
- static_assert(__is_standard_integer<_Up>::value);
-
- if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
- return __t == __u;
- else if constexpr (is_signed_v<_Tp>)
- return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u;
- else
- return __u >= 0 && __t == make_unsigned_t<_Up>(__u);
- }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_not_equal(_Tp __t, _Up __u) noexcept
- { return !std::cmp_equal(__t, __u); }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_less(_Tp __t, _Up __u) noexcept
- {
- static_assert(__is_standard_integer<_Tp>::value);
- static_assert(__is_standard_integer<_Up>::value);
-
- if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
- return __t < __u;
- else if constexpr (is_signed_v<_Tp>)
- return __t < 0 || make_unsigned_t<_Tp>(__t) < __u;
- else
- return __u >= 0 && __t < make_unsigned_t<_Up>(__u);
- }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_greater(_Tp __t, _Up __u) noexcept
- { return std::cmp_less(__u, __t); }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_less_equal(_Tp __t, _Up __u) noexcept
- { return !std::cmp_less(__u, __t); }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_greater_equal(_Tp __t, _Up __u) noexcept
- { return !std::cmp_less(__t, __u); }
-
- template<typename _Res, typename _Tp>
- constexpr bool
- in_range(_Tp __t) noexcept
- {
- static_assert(__is_standard_integer<_Res>::value);
- static_assert(__is_standard_integer<_Tp>::value);
- using __gnu_cxx::__int_traits;
-
- if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>)
- return __int_traits<_Res>::__min <= __t
- && __t <= __int_traits<_Res>::__max;
- else if constexpr (is_signed_v<_Tp>)
- return __t >= 0
- && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max;
- else
- return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max);
- }
-#endif // __cpp_lib_integer_comparison_functions
-
#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); }
@@ -234,6 +165,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#endif
+
+#ifdef __cpp_lib_observable_checkpoint // C++ >= 26
+ /// Informs the compiler that prior actions are considered observable.
+ /**
+ * This may be used to limit the extent to which optimisations based on the
+ * assumed unreachability of undefined behaviour can propagate to earlier
+ * code.
+ *
+ * @since C++26
+ */
+ [[__gnu__::__always_inline__]]
+ inline void
+ observable_checkpoint() noexcept
+ {
+ return __builtin_observable_checkpoint();
+ }
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/std/valarray b/libstdc++-v3/include/std/valarray
index 82b58ef..ac15e79 100644
--- a/libstdc++-v3/include/std/valarray
+++ b/libstdc++-v3/include/std/valarray
@@ -720,7 +720,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
valarray<_Tp>::~valarray() _GLIBCXX_NOEXCEPT
{
std::__valarray_destroy_elements(_M_data, _M_data + _M_size);
- std::__valarray_release_memory(_M_data);
+ std::__valarray_release_memory(_M_data, _M_size);
}
template<typename _Tp>
@@ -736,7 +736,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_data)
{
std::__valarray_destroy_elements(_M_data, _M_data + _M_size);
- std::__valarray_release_memory(_M_data);
+ std::__valarray_release_memory(_M_data, _M_size);
}
_M_size = __v._M_size;
_M_data = __valarray_get_storage<_Tp>(_M_size);
@@ -754,7 +754,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_data)
{
std::__valarray_destroy_elements(_M_data, _M_data + _M_size);
- std::__valarray_release_memory(_M_data);
+ std::__valarray_release_memory(_M_data, _M_size);
}
_M_size = __v._M_size;
_M_data = __v._M_data;
@@ -776,7 +776,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_data)
{
std::__valarray_destroy_elements(_M_data, _M_data + _M_size);
- std::__valarray_release_memory(_M_data);
+ std::__valarray_release_memory(_M_data, _M_size);
}
_M_size = __l.size();
_M_data = __valarray_get_storage<_Tp>(_M_size);
@@ -854,7 +854,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_data)
{
std::__valarray_destroy_elements(_M_data, _M_data + _M_size);
- std::__valarray_release_memory(_M_data);
+ std::__valarray_release_memory(_M_data, _M_size);
}
_M_size = __e.size();
_M_data = __valarray_get_storage<_Tp>(_M_size);
@@ -1049,7 +1049,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::__valarray_destroy_elements(_M_data, _M_data + _M_size);
if (_M_size != __n)
{
- std::__valarray_release_memory(_M_data);
+ std::__valarray_release_memory(_M_data, _M_size);
_M_size = __n;
_M_data = __valarray_get_storage<_Tp>(__n);
}
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index ec46ff1..f2f5583 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -393,8 +393,29 @@ namespace __variant
_Variadic_union(in_place_index_t<_Np>, _Args&&...) = delete;
};
- template<bool __trivially_destructible, typename _First, typename... _Rest>
- union _Variadic_union<__trivially_destructible, _First, _Rest...>
+ template<typename _First, typename... _Rest>
+ union _Variadic_union<true, _First, _Rest...>
+ {
+ constexpr _Variadic_union() : _M_rest() { }
+
+ template<typename... _Args>
+ constexpr
+ _Variadic_union(in_place_index_t<0>, _Args&&... __args)
+ : _M_first(in_place_index<0>, std::forward<_Args>(__args)...)
+ { }
+
+ template<size_t _Np, typename... _Args>
+ constexpr
+ _Variadic_union(in_place_index_t<_Np>, _Args&&... __args)
+ : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
+ { }
+
+ _Uninitialized<_First> _M_first;
+ _Variadic_union<true, _Rest...> _M_rest;
+ };
+
+ template<typename _First, typename... _Rest>
+ union _Variadic_union<false, _First, _Rest...>
{
constexpr _Variadic_union() : _M_rest() { }
@@ -410,24 +431,19 @@ namespace __variant
: _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
{ }
-#if __cpp_lib_variant >= 202106L
_Variadic_union(const _Variadic_union&) = default;
_Variadic_union(_Variadic_union&&) = default;
_Variadic_union& operator=(const _Variadic_union&) = default;
_Variadic_union& operator=(_Variadic_union&&) = default;
- ~_Variadic_union() = default;
-
// If any alternative type is not trivially destructible then we need a
// user-provided destructor that does nothing. The active alternative
// will be destroyed by _Variant_storage::_M_reset() instead of here.
- constexpr ~_Variadic_union()
- requires (!__trivially_destructible)
+ _GLIBCXX20_CONSTEXPR ~_Variadic_union()
{ }
-#endif
_Uninitialized<_First> _M_first;
- _Variadic_union<__trivially_destructible, _Rest...> _M_rest;
+ _Variadic_union<(is_trivially_destructible_v<_Rest> && ...), _Rest...> _M_rest;
};
// _Never_valueless_alt is true for variant alternatives that can
@@ -1387,6 +1403,8 @@ namespace __detail::__variant
noexcept(noexcept(__lhs.swap(__rhs)))
{ __lhs.swap(__rhs); }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2766. Swapping non-swappable types
template<typename... _Types>
enable_if_t<!((is_move_constructible_v<_Types> && ...)
&& (is_swappable_v<_Types> && ...))>
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index a98ffb1..375011f 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -67,7 +67,6 @@
#include <bits/stl_uninitialized.h>
#include <bits/stl_vector.h>
#include <bits/stl_bvector.h>
-#include <bits/refwrap.h>
#include <bits/range_access.h>
#ifndef _GLIBCXX_EXPORT_TEMPLATE
@@ -113,20 +112,16 @@ namespace std _GLIBCXX_VISIBILITY(default)
_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Alloc, typename _Predicate>
- _GLIBCXX20_CONSTEXPR
- inline typename vector<_Tp, _Alloc>::size_type
- erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
+ constexpr typename _GLIBCXX_STD_C::vector<_Tp, _Alloc>::size_type
+ erase_if(_GLIBCXX_STD_C::vector<_Tp, _Alloc>& __cont, _Predicate __pred)
{
- using namespace __gnu_cxx;
- _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __ucont = __cont;
const auto __osz = __cont.size();
- const auto __end = __ucont.end();
- auto __removed = std::__remove_if(__ucont.begin(), __end,
- __ops::__pred_iter(std::ref(__pred)));
+ const auto __end = __cont.end();
+ auto __removed = std::__remove_if(__cont.begin(), __end,
+ std::move(__pred));
if (__removed != __end)
{
- __cont.erase(__niter_wrap(__cont.begin(), __removed),
- __cont.end());
+ __cont.erase(__removed, __end);
return __osz - __cont.size();
}
@@ -135,25 +130,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Alloc,
typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>
- _GLIBCXX20_CONSTEXPR
- inline typename vector<_Tp, _Alloc>::size_type
- erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
- {
- using namespace __gnu_cxx;
- _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __ucont = __cont;
- const auto __osz = __cont.size();
- const auto __end = __ucont.end();
- auto __removed = std::__remove_if(__ucont.begin(), __end,
- __ops::__iter_equals_val(__value));
- if (__removed != __end)
- {
- __cont.erase(__niter_wrap(__cont.begin(), __removed),
- __cont.end());
- return __osz - __cont.size();
- }
+ constexpr typename _GLIBCXX_STD_C::vector<_Tp, _Alloc>::size_type
+ erase(_GLIBCXX_STD_C::vector<_Tp, _Alloc>& __cont, const _Up& __value)
+ { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }
- return 0;
- }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cpp_lib_erase_if
@@ -186,6 +166,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
__format::__formatter_int<_CharT> _M_f;
};
+
+#if __glibcxx_print >= 202406L
+ template<>
+ inline constexpr bool
+ enable_nonlocking_formatter_optimization<_GLIBCXX_STD_C::_Bit_reference> = true;
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __glibcxx_format_ranges
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset
index 2446f35..b308e72 100644
--- a/libstdc++-v3/include/tr2/dynamic_bitset
+++ b/libstdc++-v3/include/tr2/dynamic_bitset
@@ -99,7 +99,9 @@ namespace tr2
if (__val == 0)
return;
- if _GLIBCXX17_CONSTEXPR (sizeof(__val) == sizeof(block_type))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ if constexpr (sizeof(__val) == sizeof(block_type))
_M_w[0] = __val;
else
{
@@ -111,6 +113,7 @@ namespace tr2
__val >>= _S_bits_per_block;
}
}
+#pragma GCC diagnostic pop
}
void
@@ -667,13 +670,16 @@ namespace tr2
operator=(dynamic_bitset&& __b)
noexcept(std::is_nothrow_move_assignable<_Base>::value)
{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
static_cast<_Base&>(*this) = static_cast<_Base&&>(__b);
_M_Nb = __b._M_Nb;
- if _GLIBCXX17_CONSTEXPR (std::is_nothrow_move_assignable<_Base>::value)
+ if constexpr (std::is_nothrow_move_assignable<_Base>::value)
__b._M_Nb = 0;
else if (get_allocator() == __b.get_allocator())
__b._M_Nb = 0;
return *this;
+#pragma GCC diagnostic pop
}
/**