diff options
author | Martin Liska <mliska@suse.cz> | 2022-09-05 10:44:56 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-09-05 10:44:56 +0200 |
commit | d8e441f4b8698f38e4564fe1bbe9ff112814ecff (patch) | |
tree | 62aac45da0a2358e1ea29a07ab734f607a201e5b /libstdc++-v3 | |
parent | 4483fe115cef3eea1d64e913816e2d117b38ac73 (diff) | |
parent | ca60bd93e216ae0425f790e1d4f4dc4a48763c0e (diff) | |
download | gcc-d8e441f4b8698f38e4564fe1bbe9ff112814ecff.zip gcc-d8e441f4b8698f38e4564fe1bbe9ff112814ecff.tar.gz gcc-d8e441f4b8698f38e4564fe1bbe9ff112814ecff.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'libstdc++-v3')
72 files changed, 3521 insertions, 675 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index d88ffec..d905767 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,417 @@ +2022-09-02 Patrick Palka <ppalka@redhat.com> + + * include/std/tuple (tuple::_UseOtherCtor): Use ::type when + deriving from __and_, __or_ or __not_. + * include/std/type_traits (negation): Likewise. + (is_unsigned): Likewise. + (__is_implicitly_default_constructible): Likewise. + (is_trivially_destructible): Likewise. + (__is_nt_invocable_impl): Likewise. + +2022-09-02 Jonathan Wakely <jwakely@redhat.com> + + * include/std/type_traits (is_constructible_v) + (is_default_constructible_v, is_copy_constructible_v) + (is_move_constructible_v): Define using __is_constructible. + (is_assignable_v, is_copy_assignable_v, is_move_assignable_v): + Define using __is_assignable. + (is_trivially_constructible_v) + (is_trivially_default_constructible_v) + (is_trivially_copy_constructible_v) + (is_trivially_move_constructible_v): Define using + __is_trivially_constructible. + (is_trivially_assignable_v, is_trivially_copy_assignable_v) + (is_trivially_move_assignable_v): Define using + __is_trivially_assignable. + (is_nothrow_constructible_v) + (is_nothrow_default_constructible_v) + (is_nothrow_copy_constructible_v) + (is_nothrow_move_constructible_v): Define using + __is_nothrow_constructible. + (is_nothrow_assignable_v, is_nothrow_copy_assignable_v) + (is_nothrow_move_assignable_v): Define using + __is_nothrow_assignable. + +2022-09-02 Patrick Palka <ppalka@redhat.com> + + * include/std/type_traits (__or_, __and_, __not_): Redefine as a + class template instead of as an alias template. + * testsuite/20_util/logical_traits/requirements/short_circuit.cc: + Add more tests for conjunction and disjunction. Add corresponding + tests for __and_ and __or_. + +2022-09-01 Jonathan Wakely <jwakely@redhat.com> + + * include/std/ranges (adjacent_transform_view::_Iterator): Add + typename keyword before dependent qualified-id. + +2022-09-01 Jonathan Wakely <jwakely@redhat.com> + + * include/std/type_traits (__is_referenceable): Remove. + (__add_lvalue_reference_helper, __add_rvalue_reference_helper): + Use __void_t instead of __is_referenceable. + (__add_pointer_helper): Likewise. + (add_pointer): Add partial specializations for reference types. + +2022-09-01 Jonathan Wakely <jwakely@redhat.com> + + * include/std/type_traits (__is_constructible_impl): Replace + class template with alias template. + (is_default_constructible, is_nothrow_constructible) + (is_nothrow_constructible): Simplify base-specifier. + (__is_copy_constructible_impl, __is_move_constructible_impl) + (__is_nothrow_copy_constructible_impl) + (__is_nothrow_move_constructible_impl): Remove class templates. + (is_copy_constructible, is_move_constructible) + (is_nothrow_constructible, is_nothrow_default_constructible) + (is_nothrow_copy_constructible, is_nothrow_move_constructible): + Adjust base-specifiers to use __is_constructible_impl. + (__is_copy_assignable_impl, __is_move_assignable_impl) + (__is_nt_copy_assignable_impl, __is_nt_move_assignable_impl): + Remove class templates. + (__is_assignable_impl): New alias template. + (is_assignable, is_copy_assignable, is_move_assignable): + Adjust base-specifiers to use new alias template. + (is_nothrow_copy_assignable, is_nothrow_move_assignable): + Adjust base-specifiers to use existing alias template. + (__is_trivially_constructible_impl): New alias template. + (is_trivially_constructible, is_trivially_default_constructible) + (is_trivially_copy_constructible) + (is_trivially_move_constructible): Adjust base-specifiers to use + new alias template. + (__is_trivially_assignable_impl): New alias template. + (is_trivially_assignable, is_trivially_copy_assignable) + (is_trivially_move_assignable): Adjust base-specifier to use + new alias template. + (__add_lval_ref_t, __add_rval_ref_t): New alias templates. + (add_lvalue_reference, add_rvalue_reference): Use new alias + templates. + +2022-09-01 Jonathan Wakely <jwakely@redhat.com> + + * include/std/type_traits (__decay_selector): Add partial + specializations for array types. Only check for function types + when not dealing with an array. + (decay): Add partial specializations for reference types. + +2022-09-01 Jonathan Wakely <jwakely@redhat.com> + + * include/std/type_traits (is_lvalue_reference_v) + (is_rvalue_reference_v, is_reference_v, is_const_v) + (is_volatile_v): Define using partial specializations instead + of instantiating class templates. + +2022-09-01 Jonathan Wakely <jwakely@redhat.com> + + * include/std/type_traits (is_enum_v, is_class_v, is_union_v) + (is_empty_v, is_polymoprhic_v, is_abstract_v, is_final_v) + (is_base_of_v, is_aggregate_v): Use built-in directly instead of + instantiating class template. + +2022-09-01 Jonathan Wakely <jwakely@redhat.com> + + * include/std/type_traits (is_scoped_enum): Remove workaround. + +2022-09-01 Patrick Palka <ppalka@redhat.com> + + * include/std/ranges (__detail::__unarize): Define. + (adjacent_view::_Iterator): Befriend adjacent_transform_view. + (adjacent_transform_view): Define. + (adjacent_transform_view::_Iterator): Define. + (adjacent_transform_view::_Sentinel): Define. + (views::__detail::__can_adjacent_transform_view): Define. + (views::_AdjacentTransform): Define. + (views::adjacent_transform): Define. + (views::pairwise_transform): Define. + * testsuite/std/ranges/adaptors/adjacent_transform/1.cc: New test. + +2022-09-01 Jonathan Wakely <jwakely@redhat.com> + + * include/std/type_traits (__is_array_known_bounds): Add partial + specialization instead of using std::extent. + (__is_array_unknown_bounds): Likewise. + (extent): Add partial specializations to stop recursion after + the result is found. + (is_array_v): Add partial specializations instead of + instantiating the class template. + (rank_v, extent_v): Likewise. + (is_bounded_array_v, is_unbounded_array_v): Likewise. + (is_bounded_array, is_unbounded_array): Define in terms of the + variable templates. + +2022-08-31 Patrick Palka <ppalka@redhat.com> + + * include/bits/ranges_base.h (__advance_fn::operator()): Add + parentheses in assert condition to avoid -Wparentheses warning. + * include/std/ranges: (take_view::take_view): Uglify 'base'. + (take_while_view::take_while_view): Likewise. + (elements_view::elements_view): Likewise. + (views::_Zip::operator()): Adjust position of [[nodiscard]] for + compatibility with -fconcepts-ts. + (zip_transform_view::_Sentinel): Uglify 'OtherConst'. + (views::_ZipTransform::operator()): Adjust position of + [[nodiscard]] for compatibilty with -fconcepts-ts. + +2022-08-31 Martin Liska <mliska@suse.cz> + + * configure: Regenerate. + * crossconfig.m4: Remove deprecated ports. + +2022-08-31 François Dumont <fdumont@gcc.gnu.org> + + * include/debug/debug.h: Use nullptr rather than '0' in checks in post-C++11. + * include/debug/string: Likewise. + * testsuite/21_strings/basic_string/operations/ends_with/char.cc: Use __gnu_test::string. + * testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc: Likewise. + * testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc: Likewise. + * testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc: Likewise. + * testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc: Likewise. + * testsuite/21_strings/basic_string/operations/starts_with/char.cc: Likewise.. + +2022-08-31 Patrick Palka <ppalka@redhat.com> + + * include/std/ranges (adjacent_view): Define. + (enable_borrowed_range<adjacent_view>): Define. + (__detail::__repeated_tuple): Define. + (adjacent_view::_Iterator): Define. + (adjacent_view::_Sentinel): Define. + (views::__detail::__can_adjacent_view): Define. + (views::_Adjacent): Define. + (views::adjacent): Define. + (views::pairwise): Define. + * testsuite/std/ranges/adaptors/adjacent/1.cc: New test. + +2022-08-31 François Dumont <fdumont@gcc.gnu.org> + + * include/debug/formatter.h + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_state): Declare. + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_create_state): Declare. + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full_callback): Define. + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_error_callback): Define. + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full_func): Define. + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full): Declare. + [_GLIBCXX_HAVE_STACKTRACE](_Error_formatter::_M_backtrace_state): New. + [_GLIBCXX_HAVE_STACKTRACE](_Error_formatter::_M_backtrace_full): New. + * src/c++11/debug.cc [_GLIBCXX_HAVE_STACKTRACE](print_backtrace): New. + (_Error_formatter::_M_error()): Adapt. + * src/libbacktrace/Makefile.am: Add backtrace.c. + * src/libbacktrace/Makefile.in: Regenerate. + * src/libbacktrace/backtrace-rename.h (backtrace_full): New. + * testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc: New test. + * doc/xml/manual/debug_mode.xml: Document _GLIBCXX_DEBUG_BACKTRACE. + * doc/xml/manual/using.xml: Likewise. + +2022-08-31 Patrick Palka <ppalka@redhat.com> + + * testsuite/20_util/logical_traits/requirements/short_circuit.cc: New test. + +2022-08-31 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/refwrap.h (reference_wrapper::operator()): Add + noexcept-specifier and use __invoke_result instead of result_of. + * testsuite/20_util/reference_wrapper/invoke-noexcept.cc: New test. + +2022-08-31 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/20_util/reference_wrapper/invoke-2.cc: Improve + comments. + * testsuite/20_util/reference_wrapper/invoke-3.cc: Likewise. + * testsuite/20_util/reference_wrapper/invoke.cc: Likewise. + +2022-08-31 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/basic_string.h (basic_string): Add nodiscard + attribute to all relevant functions. + * include/std/string_view (basic_string_view): Likewise. + * testsuite/21_strings/basic_string/capacity/1.cc: Cast unused + results to void. + * testsuite/21_strings/basic_string/capacity/char/1.cc: + Likewise. + * testsuite/21_strings/basic_string/capacity/wchar_t/1.cc: + Likewise. + * testsuite/21_strings/basic_string/cons/char/self_move.cc: + Likewise. + * testsuite/21_strings/basic_string/element_access/char/1.cc: + Likewise. + * testsuite/21_strings/basic_string/element_access/char/21674.cc: + Likewise. + * testsuite/21_strings/basic_string/element_access/wchar_t/1.cc: + Likewise. + * testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc: + Likewise. + * testsuite/21_strings/basic_string/lwg2758.cc: Likewise. + * testsuite/21_strings/basic_string/lwg2946.cc: Likewise. + * testsuite/21_strings/basic_string/operations/contains/nonnull.cc: + Add -Wno-unused-result to options. + * testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc: + Likewise. + * testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc: + Likewise. + * testsuite/21_strings/basic_string/operators/char/1.cc: Cast + unused results to void. + * testsuite/21_strings/basic_string/operators/wchar_t/1.cc: + Likewise. + * testsuite/21_strings/basic_string_view/capacity/1.cc: + Likewise. + * testsuite/21_strings/basic_string_view/element_access/char/1.cc: + Likewise. + * testsuite/21_strings/basic_string_view/element_access/char/2.cc: + Likewise. + * testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc: + Likewise. + * testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc: + Likewise. + * testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc: + Likewise. + Add -Wno-unused-result to options. + * testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc: + Likewise. + * testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc: + Likewise. + * testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc: Cast + unused results to void. + * testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc: + Likewise. + * testsuite/27_io/basic_stringbuf/sungetc/char/1.cc: Likewise. + * testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc: + Likewise. + +2022-08-27 Patrick Palka <ppalka@redhat.com> + + * testsuite/20_util/logical_traits/requirements/base_classes.cc: New test. + +2022-08-26 Patrick Palka <ppalka@redhat.com> + + * include/std/ranges (zip_view::_Iterator::operator<): Remove + as per LWG 3692. + (zip_view::_Iterator::operator>): Likewise. + (zip_view::_Iterator::operator<=): Likewise. + (zip_view::_Iterator::operator>=): Likewise. + (zip_view::_Iterator::operator<=>): Remove three_way_comparable + constraint as per LWG 3692. + (zip_transform_view::_Iterator): Ditto as per LWG 3702. + +2022-08-26 Patrick Palka <ppalka@redhat.com> + + * include/std/ranges (zip_view::_Iterator): Befriend + zip_transform_view. + (__detail::__range_iter_cat): Define. + (zip_transform_view): Define. + (zip_transform_view::_Iterator): Define. + (zip_transform_view::_Sentinel): Define. + (views::__detail::__can_zip_transform_view): Define. + (views::_ZipTransform): Define. + (views::zip_transform): Define. + * testsuite/std/ranges/zip_transform/1.cc: New test. + +2022-08-26 Patrick Palka <ppalka@redhat.com> + + * include/std/type_traits (enable_if, __enable_if_t): Define them + earlier. + (__detail::__first_t): Define. + (__detail::__or_fn, __detail::__and_fn): Declare. + (__or_, __and_): Redefine as alias templates in terms of __or_fn + and __and_fn. + (__not_): Redefine as an alias template. + (__detail::__disjunction_impl, __detail::__conjunction_impl): + Define. + (conjuction, disjunction): Redefine in terms of __disjunction_impl + and __conjunction_impl. + +2022-08-26 Jonathan Wakely <jwakely@redhat.com> + + * include/std/system_error (error_code::_Check): New alias + template for constructor SFINAE constraint. + (error_code::error_code(ErrorCodeEnum)): Use it. + (error_code::operator=(ErrorCodeEnum)): Remove. + (error_condition::_Check): New alias template for constraint. + (error_condition::error_condition(ErrorConditionEnum)): Use it. + (error_condition::operator=(ErrorConditionEnum)): Remove. + * testsuite/19_diagnostics/error_code/cons/1.cc: Check + constructor taking user-defined error enum. + * testsuite/19_diagnostics/error_condition/cons/1.cc: Likewise. + +2022-08-26 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/basic_string.h (starts_with, ends_with, contains): + Add nonnull attribute. + * include/bits/cow_string.h (starts_with, ends_with, contains): + Likewise. + * include/std/string_view (starts_with, ends_with, contains): + Likewise. + * testsuite/21_strings/basic_string/operations/contains/nonnull.cc + * testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc + * testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc + * testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc + * testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc + * testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc + +2022-08-25 Patrick Palka <ppalka@redhat.com> + + * include/std/ranges (lazy_split_view::_OuterIter::_M_current): + Remove redundant comment. + (lazy_split_view::_M_current): Likewise. + (common_view::common_view): Remove commented out view-converting + constructor as per LWG3405. + (elements_view::_Iterator::_Iterator): Uglify 'current' and 'i'. + +2022-08-24 Patrick Palka <ppalka@redhat.com> + + * include/bits/ranges_algo.h (__min_fn, min): Move to ... + * include/bits/ranges_util.h: ... here, in order to avoid + including all of ranges_algo.h from <ranges>. + * include/std/ranges (__detail::__zip_is_common): Define for + C++23 as per P2321R2. + (__detail::__tuple_or_pair): Likewise. + (__detail::__tuple_or_pair_t): Likewise. + (__detail::__tuple_transform): Likewise. + (__detail::__tuple_for_each): Likewise. + (zip_view): Likewise. + (enable_borrowed_range<zip_view>): Likewise. + (__detail::__all_random_access): Likewise. + (__detail::__all_bidirectional): Likewise. + (__detail::__all_forward): Likewise. + (__detail::__zip_view_iter_cat): Likewise. + (zip_view::_Iterator): Likewise. + (zip_view::_Sentinel): Likewise. + * testsuite/std/ranges/zip/1.cc: New test. + +2022-08-24 Jonathan Wakely <jwakely@redhat.com> + + Revert: + 2022-08-24 Will Hawkins <whh8b@obs.cr> + + * include/bits/basic_string.h (operator+(const string&, const char*)): + Remove naive implementation. + * include/bits/basic_string.tcc (operator+(const string&, const char*)): + Add single-allocation implementation. + +2022-08-24 Patrick Palka <ppalka@redhat.com> + + * include/bits/stl_pair.h (pair::swap const): Add non-standard + is_swappable_v constraints. + * include/std/tuple (tuple::swap const): Likewise. + * testsuite/20_util/tuple/cons/noexcept_specs.cc: Correct some + asserts in C++23 mode. + +2022-08-24 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/stl_algo.h (__stable_sort): Cast size to + iterator's difference type. + * testsuite/25_algorithms/stable_sort/4.cc: New test. + +2022-08-24 Will Hawkins <whh8b@obs.cr> + + * include/bits/basic_string.h (operator+(const string&, const char*)): + Remove naive implementation. + * include/bits/basic_string.tcc (operator+(const string&, const char*)): + Add single-allocation implementation. + +2022-08-24 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/20_util/duration_cast/rounding.cc: Check abs with + non-reduced duration. + 2022-08-23 Patrick Palka <ppalka@redhat.com> * include/bits/stl_bvector.h (_Bit_reference::operator=): Define diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 9e2ee86..1772eef 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -47955,20 +47955,6 @@ $as_echo "$gcc_cv_have_tls" >&6; } $as_echo "#define HAVE_TLS 1" >>confdefs.h fi - case "$target" in - *-hpux10*) - $as_echo "#define HAVE_ISINF 1" >>confdefs.h - - $as_echo "#define HAVE_ISINFF 1" >>confdefs.h - - $as_echo "#define HAVE_ISNANF 1" >>confdefs.h - - $as_echo "#define HAVE_FINITE 1" >>confdefs.h - - $as_echo "#define HAVE_FINITEF 1" >>confdefs.h - - ;; - esac ;; *-linux* | *-uclinux* | *-gnu* | *-kfreebsd*-gnu | *-cygwin* | *-solaris*) diff --git a/libstdc++-v3/crossconfig.m4 b/libstdc++-v3/crossconfig.m4 index e8ff89f..130f47f 100644 --- a/libstdc++-v3/crossconfig.m4 +++ b/libstdc++-v3/crossconfig.m4 @@ -173,15 +173,6 @@ case "${host}" in AC_DEFINE(HAVE_STRTOLD) GCC_CHECK_TLS - case "$target" in - *-hpux10*) - AC_DEFINE(HAVE_ISINF) - AC_DEFINE(HAVE_ISINFF) - AC_DEFINE(HAVE_ISNANF) - AC_DEFINE(HAVE_FINITE) - AC_DEFINE(HAVE_FINITEF) - ;; - esac ;; *-linux* | *-uclinux* | *-gnu* | *-kfreebsd*-gnu | *-cygwin* | *-solaris*) GLIBCXX_CHECK_COMPILER_FEATURES diff --git a/libstdc++-v3/doc/xml/manual/debug_mode.xml b/libstdc++-v3/doc/xml/manual/debug_mode.xml index 988c4a9..dadc0cd 100644 --- a/libstdc++-v3/doc/xml/manual/debug_mode.xml +++ b/libstdc++-v3/doc/xml/manual/debug_mode.xml @@ -161,6 +161,12 @@ which always works correctly. <code>GLIBCXX_DEBUG_MESSAGE_LENGTH</code> can be used to request a different length.</para> +<para>Note that libstdc++ is able to produce backtraces on error. + It requires that you configure libstdc++ build with + <option>--enable-libstdcxx-backtrace=yes</option>. + Use <code>-D_GLIBCXX_DEBUG_BACKTRACE</code> to activate it. + You'll then have to link with libstdc++_libbacktrace static library + (<option>-lstdc++_libbacktrace</option>) to build your application.</para> </section> <section xml:id="debug_mode.using.specific" xreflabel="Using Specific"><info><title>Using a Specific Debug Container</title></info> diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml index 0b9a0c9..0acdba6 100644 --- a/libstdc++-v3/doc/xml/manual/using.xml +++ b/libstdc++-v3/doc/xml/manual/using.xml @@ -1144,6 +1144,15 @@ g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2 hello.cc -o test.exe extensions and libstdc++-specific behavior into errors. </para> </listitem></varlistentry> + <varlistentry><term><code>_GLIBCXX_DEBUG_BACKTRACE</code></term> + <listitem> + <para> + Undefined by default. Considered only if libstdc++ has been configured with + <option>--enable-libstdcxx-backtrace=yes</option> and if <code>_GLIBCXX_DEBUG</code> + is defined. When defined display backtraces on + <link linkend="manual.ext.debug_mode">debug mode</link> assertions. + </para> + </listitem></varlistentry> <varlistentry><term><code>_GLIBCXX_PARALLEL</code></term> <listitem> <para>Undefined by default. When defined, compiles user code @@ -1650,6 +1659,7 @@ A quick read of the relevant part of the GCC header will remain compatible between different GCC releases. </para> </section> + </section> <section xml:id="manual.intro.using.concurrency" xreflabel="Concurrency"><info><title>Concurrency</title></info> diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index b04fba9..0df64ea 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -942,7 +942,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write iterator that points to the first character in * the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR iterator begin() _GLIBCXX_NOEXCEPT { return iterator(_M_data()); } @@ -951,7 +951,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points to the first * character in the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_iterator begin() const _GLIBCXX_NOEXCEPT { return const_iterator(_M_data()); } @@ -960,7 +960,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write iterator that points one past the last * character in the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR iterator end() _GLIBCXX_NOEXCEPT { return iterator(_M_data() + this->size()); } @@ -969,7 +969,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points one past the * last character in the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_iterator end() const _GLIBCXX_NOEXCEPT { return const_iterator(_M_data() + this->size()); } @@ -979,7 +979,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * character in the %string. Iteration is done in reverse element * order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reverse_iterator rbegin() _GLIBCXX_NOEXCEPT { return reverse_iterator(this->end()); } @@ -989,7 +989,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to the last character in the %string. Iteration is done in * reverse element order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reverse_iterator rbegin() const _GLIBCXX_NOEXCEPT { return const_reverse_iterator(this->end()); } @@ -999,7 +999,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * first character in the %string. Iteration is done in reverse * element order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reverse_iterator rend() _GLIBCXX_NOEXCEPT { return reverse_iterator(this->begin()); } @@ -1009,7 +1009,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to one before the first character in the %string. Iteration * is done in reverse element order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reverse_iterator rend() const _GLIBCXX_NOEXCEPT { return const_reverse_iterator(this->begin()); } @@ -1019,7 +1019,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points to the first * character in the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_iterator cbegin() const noexcept { return const_iterator(this->_M_data()); } @@ -1028,7 +1028,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points one past the * last character in the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_iterator cend() const noexcept { return const_iterator(this->_M_data() + this->size()); } @@ -1038,7 +1038,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to the last character in the %string. Iteration is done in * reverse element order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(this->end()); } @@ -1048,7 +1048,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to one before the first character in the %string. Iteration * is done in reverse element order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reverse_iterator crend() const noexcept { return const_reverse_iterator(this->begin()); } @@ -1058,20 +1058,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // Capacity: /// Returns the number of characters in the string, not including any /// null-termination. - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type size() const _GLIBCXX_NOEXCEPT { return _M_string_length; } /// Returns the number of characters in the string, not including any /// null-termination. - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type length() const _GLIBCXX_NOEXCEPT { return _M_string_length; } /// Returns the size() of the largest possible %string. - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type max_size() const _GLIBCXX_NOEXCEPT { return (_Alloc_traits::max_size(_M_get_allocator()) - 1) / 2; } @@ -1127,7 +1127,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns the total number of characters that the %string can hold * before needing to allocate more memory. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type capacity() const _GLIBCXX_NOEXCEPT { @@ -1194,7 +1194,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * out_of_range lookups are not defined. (For checked lookups * see at().) */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reference operator[] (size_type __pos) const _GLIBCXX_NOEXCEPT { @@ -1212,7 +1212,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * out_of_range lookups are not defined. (For checked lookups * see at().) */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reference operator[](size_type __pos) { @@ -1234,7 +1234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * first checked that it is in the range of the string. The function * throws out_of_range if the check fails. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reference at(size_type __n) const { @@ -1256,7 +1256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * first checked that it is in the range of the string. The function * throws out_of_range if the check fails. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reference at(size_type __n) { @@ -1273,7 +1273,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write reference to the data at the first * element of the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reference front() noexcept { @@ -1285,7 +1285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) reference to the data at the first * element of the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reference front() const noexcept { @@ -1297,7 +1297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write reference to the data at the last * element of the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reference back() noexcept { @@ -1309,7 +1309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) reference to the data at the * last element of the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reference back() const noexcept { @@ -2549,7 +2549,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * This is a handle to internal data. Do not modify or dire things may * happen. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const _CharT* c_str() const _GLIBCXX_NOEXCEPT { return _M_data(); } @@ -2562,7 +2562,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * allows modifying the contents use @c &str[0] instead, * (or in C++17 the non-const @c str.data() overload). */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const _CharT* data() const _GLIBCXX_NOEXCEPT { return _M_data(); } @@ -2574,7 +2574,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * This is a pointer to the character sequence held by the string. * Modifying the characters in the sequence is allowed. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _CharT* data() noexcept { return _M_data(); } @@ -2583,7 +2583,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 /** * @brief Return copy of allocator used to construct this string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR allocator_type get_allocator() const _GLIBCXX_NOEXCEPT { return _M_get_allocator(); } @@ -2600,7 +2600,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it begins. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2615,7 +2615,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it begins. If not * found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find(const basic_string& __str, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2629,7 +2629,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of first occurrence. */ template<typename _Tp> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find(const _Tp& __svt, size_type __pos = 0) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2649,7 +2649,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * __s within this string. If found, returns the index where * it begins. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT { @@ -2667,7 +2667,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it was * found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT; @@ -2681,7 +2681,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * __str within this string. If found, returns the index where * it begins. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type rfind(const basic_string& __str, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2695,7 +2695,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of last occurrence. */ template<typename _Tp> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> rfind(const _Tp& __svt, size_type __pos = npos) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2717,7 +2717,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it begins. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2732,7 +2732,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @a __s within this string. If found, returns the index * where it begins. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type rfind(const _CharT* __s, size_type __pos = npos) const { @@ -2750,7 +2750,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it was * found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT; @@ -2765,7 +2765,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2780,7 +2780,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of first occurrence. */ template<typename _Tp> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find_first_of(const _Tp& __svt, size_type __pos = 0) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2802,7 +2802,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * found, returns the index where it was found. If not found, * returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2817,7 +2817,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * characters of @a __s within this string. If found, returns * the index where it was found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_of(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2838,7 +2838,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * * Note: equivalent to find(__c, __pos). */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT { return this->find(__c, __pos); } @@ -2854,7 +2854,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2869,7 +2869,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of last occurrence. */ template<typename _Tp> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find_last_of(const _Tp& __svt, size_type __pos = npos) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2891,7 +2891,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * found, returns the index where it was found. If not found, * returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2906,7 +2906,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * characters of @a __s within this string. If found, returns * the index where it was found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_of(const _CharT* __s, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2927,7 +2927,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * * Note: equivalent to rfind(__c, __pos). */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT { return this->rfind(__c, __pos); } @@ -2942,7 +2942,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * in @a __str within this string. If found, returns the index where it * was found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2957,8 +2957,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of first occurrence. */ template<typename _Tp> + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> - _GLIBCXX20_CONSTEXPR find_first_not_of(const _Tp& __svt, size_type __pos = 0) const noexcept(is_same<_Tp, __sv_type>::value) { @@ -2979,7 +2979,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it was * found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2994,7 +2994,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * contained in @a __s within this string. If found, returns * the index where it was found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -3013,7 +3013,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * other than @a __c within this string. If found, returns the * index where it was found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_not_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT; @@ -3029,7 +3029,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -3044,7 +3044,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of last occurrence. */ template<typename _Tp> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find_last_not_of(const _Tp& __svt, size_type __pos = npos) const noexcept(is_same<_Tp, __sv_type>::value) @@ -3066,7 +3066,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * If found, returns the index where it was found. If not found, * returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -3081,7 +3081,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_not_of(const _CharT* __s, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -3100,7 +3100,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @a __c within this string. If found, returns the index where it was * found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_not_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT; @@ -3117,7 +3117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * short, use the remainder of the characters. If @a __pos is * beyond the end of the string, out_of_range is thrown. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR basic_string substr(size_type __pos = 0, size_type __n = npos) const { return basic_string(*this, @@ -3137,7 +3137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * If the result of the comparison is nonzero returns it, * otherwise the shorter one is ordered first. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(const basic_string& __str) const { @@ -3158,7 +3158,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ template<typename _Tp> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, int> compare(const _Tp& __svt) const noexcept(is_same<_Tp, __sv_type>::value) @@ -3183,7 +3183,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ template<typename _Tp> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, int> compare(size_type __pos, size_type __n, const _Tp& __svt) const noexcept(is_same<_Tp, __sv_type>::value) @@ -3203,7 +3203,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ template<typename _Tp> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, int> compare(size_type __pos1, size_type __n1, const _Tp& __svt, size_type __pos2, size_type __n2 = npos) const @@ -3234,7 +3234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * result of the comparison is nonzero returns it, otherwise * the shorter one is ordered first. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(size_type __pos, size_type __n, const basic_string& __str) const { @@ -3271,7 +3271,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * If the result of the comparison is nonzero returns it, * otherwise the shorter one is ordered first. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos) const @@ -3302,7 +3302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * comparison is nonzero returns it, otherwise the shorter one is * ordered first. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT { @@ -3337,7 +3337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * the comparison is nonzero returns it, otherwise the shorter * one is ordered first. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(size_type __pos, size_type __n1, const _CharT* __s) const { @@ -3376,7 +3376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * NB: s must have at least n2 characters, '\\0' has * no special meaning. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(size_type __pos, size_type __n1, const _CharT* __s, size_type __n2) const @@ -3392,40 +3392,49 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } #if __cplusplus >= 202002L + [[nodiscard]] constexpr bool starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } + [[nodiscard]] constexpr bool starts_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } + [[nodiscard, __gnu__::__nonnull__]] constexpr bool starts_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } + [[nodiscard]] constexpr bool ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } + [[nodiscard]] constexpr bool ends_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } + [[nodiscard, __gnu__::__nonnull__]] constexpr bool ends_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } #endif // C++20 #if __cplusplus > 202002L + [[nodiscard]] constexpr bool contains(basic_string_view<_CharT, _Traits> __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } + [[nodiscard]] constexpr bool contains(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } + [[nodiscard, __gnu__::__nonnull__]] constexpr bool contains(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } @@ -3480,7 +3489,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with value of @a __lhs followed by @a __rhs. */ template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3497,7 +3506,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with value of @a __lhs followed by @a __rhs. */ template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR basic_string<_CharT,_Traits,_Alloc> operator+(const _CharT* __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs); @@ -3509,7 +3518,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with @a __lhs followed by @a __rhs. */ template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR basic_string<_CharT,_Traits,_Alloc> operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs); @@ -3520,7 +3529,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with @a __lhs followed by @a __rhs. */ template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3537,7 +3546,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with @a __lhs followed by @a __rhs. */ template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs) { @@ -3550,7 +3559,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus >= 201103L template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3564,7 +3573,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 { return std::move(__rhs.insert(0, __lhs)); } template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) @@ -3587,28 +3596,28 @@ _GLIBCXX_END_NAMESPACE_CXX11 } template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(const _CharT* __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) { return std::move(__rhs.insert(0, __lhs)); } template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(_CharT __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) { return std::move(__rhs.insert(0, 1, __lhs)); } template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, const _CharT* __rhs) { return std::move(__lhs.append(__rhs)); } template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, _CharT __rhs) @@ -3623,7 +3632,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline bool operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3640,7 +3649,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline bool operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3658,6 +3667,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * greater than, or incomparable with `__rhs`. */ template<typename _CharT, typename _Traits, typename _Alloc> + [[nodiscard]] constexpr auto operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) noexcept @@ -3672,6 +3682,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * greater than, or incomparable with `__rhs`. */ template<typename _CharT, typename _Traits, typename _Alloc> + [[nodiscard]] constexpr auto operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) noexcept @@ -3685,6 +3696,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __rhs.compare(@a __lhs) == 0. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator==(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3698,6 +3710,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3711,6 +3724,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __rhs.compare(@a __lhs) != 0. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator!=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3723,6 +3737,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3736,6 +3751,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs precedes @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3749,6 +3765,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs precedes @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3761,6 +3778,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs precedes @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator<(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3774,6 +3792,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs follows @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3787,6 +3806,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs follows @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3799,6 +3819,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs follows @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator>(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3812,6 +3833,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3825,6 +3847,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3837,6 +3860,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator<=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3850,6 +3874,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3863,6 +3888,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3875,6 +3901,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX_NODISCARD inline bool operator>=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -4057,6 +4084,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // DR 1261. Insufficent overloads for to_string / to_wstring + _GLIBCXX_NODISCARD inline string to_string(int __val) #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_INT__) <= 32 @@ -4071,6 +4099,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __str; } + _GLIBCXX_NODISCARD inline string to_string(unsigned __val) #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_INT__) <= 32 @@ -4082,6 +4111,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __str; } + _GLIBCXX_NODISCARD inline string to_string(long __val) #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_LONG__) <= 32 @@ -4096,6 +4126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __str; } + _GLIBCXX_NODISCARD inline string to_string(unsigned long __val) #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_LONG__) <= 32 @@ -4107,6 +4138,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __str; } + _GLIBCXX_NODISCARD inline string to_string(long long __val) { @@ -4119,6 +4151,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __str; } + _GLIBCXX_NODISCARD inline string to_string(unsigned long long __val) { @@ -4130,6 +4163,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if _GLIBCXX_USE_C99_STDIO // NB: (v)snprintf vs sprintf. + _GLIBCXX_NODISCARD inline string to_string(float __val) { @@ -4139,6 +4173,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 "%f", __val); } + _GLIBCXX_NODISCARD inline string to_string(double __val) { @@ -4148,6 +4183,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 "%f", __val); } + _GLIBCXX_NODISCARD inline string to_string(long double __val) { @@ -4199,40 +4235,47 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #ifndef _GLIBCXX_HAVE_BROKEN_VSWPRINTF // DR 1261. + _GLIBCXX_NODISCARD inline wstring to_wstring(int __val) { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, 4 * sizeof(int), L"%d", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(unsigned __val) { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, 4 * sizeof(unsigned), L"%u", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(long __val) { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, 4 * sizeof(long), L"%ld", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(unsigned long __val) { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, 4 * sizeof(unsigned long), L"%lu", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(long long __val) { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, 4 * sizeof(long long), L"%lld", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(unsigned long long __val) { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, 4 * sizeof(unsigned long long), L"%llu", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(float __val) { @@ -4242,6 +4285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 L"%f", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(double __val) { @@ -4251,6 +4295,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 L"%f", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(long double __val) { @@ -4284,6 +4329,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __str_hash_base : public __hash_base<size_t, _StrT> { + [[__nodiscard__]] size_t operator()(const _StrT& __s) const noexcept { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(_CharT)); } diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h index f16e33a..f5f0333 100644 --- a/libstdc++-v3/include/bits/cow_string.h +++ b/libstdc++-v3/include/bits/cow_string.h @@ -3012,6 +3012,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION starts_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } + [[__gnu__::__nonnull__]] bool starts_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } @@ -3024,6 +3025,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ends_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } + [[__gnu__::__nonnull__]] bool ends_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } @@ -3038,6 +3040,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION contains(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } + [[__gnu__::__nonnull__]] bool contains(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index 3d30fb1..2a11636 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -2902,59 +2902,7 @@ namespace ranges inline constexpr __set_symmetric_difference_fn set_symmetric_difference{}; - struct __min_fn - { - template<typename _Tp, typename _Proj = identity, - indirect_strict_weak_order<projected<const _Tp*, _Proj>> - _Comp = ranges::less> - constexpr const _Tp& - operator()(const _Tp& __a, const _Tp& __b, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (std::__invoke(__comp, - std::__invoke(__proj, __b), - std::__invoke(__proj, __a))) - return __b; - else - return __a; - } - - template<input_range _Range, typename _Proj = identity, - indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> - _Comp = ranges::less> - requires indirectly_copyable_storable<iterator_t<_Range>, - range_value_t<_Range>*> - 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; - while (++__first != __last) - { - auto __tmp = *__first; - if (std::__invoke(__comp, - std::__invoke(__proj, __tmp), - std::__invoke(__proj, __result))) - __result = std::move(__tmp); - } - return __result; - } - - template<copyable _Tp, typename _Proj = identity, - indirect_strict_weak_order<projected<const _Tp*, _Proj>> - _Comp = ranges::less> - constexpr _Tp - operator()(initializer_list<_Tp> __r, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::subrange(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __min_fn min{}; + // min is defined in <bits/ranges_util.h>. struct __max_fn { diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 38db33f..866d7c5 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -778,7 +778,7 @@ namespace ranges else if (__n != 0) [[likely]] { // n and bound must not lead in opposite directions: - __glibcxx_assert(__n < 0 == __diff < 0); + __glibcxx_assert((__n < 0) == (__diff < 0)); (*this)(__it, __n); return 0; diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 37d7bc8..bb56dee 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -649,6 +649,61 @@ namespace ranges }; inline constexpr __search_fn search{}; + + struct __min_fn + { + template<typename _Tp, typename _Proj = identity, + indirect_strict_weak_order<projected<const _Tp*, _Proj>> + _Comp = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(__comp, + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return __b; + else + return __a; + } + + template<input_range _Range, typename _Proj = identity, + indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable<iterator_t<_Range>, + range_value_t<_Range>*> + 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; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result))) + __result = std::move(__tmp); + } + return __result; + } + + template<copyable _Tp, typename _Proj = identity, + indirect_strict_weak_order<projected<const _Tp*, _Proj>> + _Comp = ranges::less> + constexpr _Tp + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __min_fn min{}; + } // namespace ranges using ranges::get; diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h index 8016f87..976902b 100644 --- a/libstdc++-v3/include/bits/refwrap.h +++ b/libstdc++-v3/include/bits/refwrap.h @@ -348,8 +348,9 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) template<typename... _Args> _GLIBCXX20_CONSTEXPR - typename result_of<_Tp&(_Args&&...)>::type + typename __invoke_result<_Tp&, _Args...>::type operator()(_Args&&... __args) const + noexcept(__is_nothrow_invocable<_Tp&, _Args...>::value) { #if __cplusplus > 201703L if constexpr (is_object_v<type>) diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index c607805..57fa1c1 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -5026,8 +5026,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO _TmpBuf __buf(__first, (__last - __first + 1) / 2); if (__builtin_expect(__buf.requested_size() == __buf.size(), true)) - std::__stable_sort_adaptive(__first, __first + __buf.size(), __last, - __buf.begin(), __comp); + std::__stable_sort_adaptive(__first, + __first + _DistanceType(__buf.size()), + __last, __buf.begin(), __comp); else if (__builtin_expect(__buf.begin() == 0, false)) std::__inplace_stable_sort(__first, __last, __comp); else diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index bffca0d..d0f07b0 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -213,10 +213,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if __cplusplus > 202002L + // As an extension, we constrain the const swap member function in order + // to continue accepting explicit instantiation of pairs whose elements + // are not all const swappable. Without this constraint, such an + // explicit instantiation would also instantiate the ill-formed body of + // this function and yield a hard error. This constraint shouldn't + // affect the behavior of valid programs. constexpr void swap(const pair& __p) const noexcept(__and_v<__is_nothrow_swappable<const _T1>, __is_nothrow_swappable<const _T2>>) + requires is_swappable_v<const _T1> && is_swappable_v<const _T2> { using std::swap; swap(first, __p.first); diff --git a/libstdc++-v3/include/debug/debug.h b/libstdc++-v3/include/debug/debug.h index 28e250f..f423376 100644 --- a/libstdc++-v3/include/debug/debug.h +++ b/libstdc++-v3/include/debug/debug.h @@ -118,10 +118,17 @@ namespace __gnu_debug __glibcxx_check_heap(_First,_Last) # define __glibcxx_requires_heap_pred(_First,_Last,_Pred) \ __glibcxx_check_heap_pred(_First,_Last,_Pred) -# define __glibcxx_requires_string(_String) \ +# if __cplusplus < 201103L +# define __glibcxx_requires_string(_String) \ _GLIBCXX_DEBUG_PEDASSERT(_String != 0) -# define __glibcxx_requires_string_len(_String,_Len) \ +# define __glibcxx_requires_string_len(_String,_Len) \ _GLIBCXX_DEBUG_PEDASSERT(_String != 0 || _Len == 0) +# else +# define __glibcxx_requires_string(_String) \ + _GLIBCXX_DEBUG_PEDASSERT(_String != nullptr) +# define __glibcxx_requires_string_len(_String,_Len) \ + _GLIBCXX_DEBUG_PEDASSERT(_String != nullptr || _Len == 0) +# endif # define __glibcxx_requires_irreflexive(_First,_Last) \ __glibcxx_check_irreflexive(_First,_Last) # define __glibcxx_requires_irreflexive2(_First,_Last) \ diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h index 748d4fb..b4b7238 100644 --- a/libstdc++-v3/include/debug/formatter.h +++ b/libstdc++-v3/include/debug/formatter.h @@ -31,6 +31,37 @@ #include <bits/c++config.h> +#if _GLIBCXX_HAVE_STACKTRACE +struct __glibcxx_backtrace_state; + +extern "C" +{ + __glibcxx_backtrace_state* + __glibcxx_backtrace_create_state(const char*, int, + void(*)(void*, const char*, int), + void*); + + typedef int (*__glibcxx_backtrace_full_callback) ( + void*, __UINTPTR_TYPE__, const char *, int, const char*); + + typedef void (*__glibcxx_backtrace_error_callback) ( + void*, const char*, int); + + typedef int (*__glibcxx_backtrace_full_func) ( + __glibcxx_backtrace_state*, int, + __glibcxx_backtrace_full_callback, + __glibcxx_backtrace_error_callback, + void*); + + int + __glibcxx_backtrace_full( + __glibcxx_backtrace_state*, int, + __glibcxx_backtrace_full_callback, + __glibcxx_backtrace_error_callback, + void*); +} +#endif + #if __cpp_rtti # include <typeinfo> # define _GLIBCXX_TYPEID(_Type) &typeid(_Type) @@ -576,6 +607,15 @@ namespace __gnu_debug const char* __function) : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) , _M_function(__function) +#if _GLIBCXX_HAVE_STACKTRACE +# ifdef _GLIBCXX_DEBUG_BACKTRACE + , _M_backtrace_state( + __glibcxx_backtrace_create_state(nullptr, 0, nullptr, nullptr)) + , _M_backtrace_full(&__glibcxx_backtrace_full) +# else + , _M_backtrace_state() +# endif +#endif { } #if !_GLIBCXX_INLINE_VERSION @@ -591,6 +631,10 @@ namespace __gnu_debug unsigned int _M_num_parameters; const char* _M_text; const char* _M_function; +#if _GLIBCXX_HAVE_STACKTRACE + __glibcxx_backtrace_state* _M_backtrace_state; + __glibcxx_backtrace_full_func _M_backtrace_full; +#endif public: static _Error_formatter& diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string index a4482db..c16751c 100644 --- a/libstdc++-v3/include/debug/string +++ b/libstdc++-v3/include/debug/string @@ -50,14 +50,25 @@ #endif #ifdef _GLIBCXX_DEBUG_PEDANTIC -# define __glibcxx_check_string(_String) \ +# if __cplusplus < 201103L +# define __glibcxx_check_string(_String) \ _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(_String != 0, \ __FILE__, __LINE__, \ __PRETTY_FUNCTION__); -# define __glibcxx_check_string_len(_String,_Len) \ +# define __glibcxx_check_string_len(_String,_Len) \ _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(_String != 0 || _Len == 0, \ __FILE__, __LINE__, \ __PRETTY_FUNCTION__); +# else +# define __glibcxx_check_string(_String) \ + _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(_String != nullptr, \ + __FILE__, __LINE__, \ + __PRETTY_FUNCTION__); +# define __glibcxx_check_string_len(_String,_Len) \ + _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(_String != nullptr || _Len == 0, \ + __FILE__, __LINE__, \ + __PRETTY_FUNCTION__); +# endif #else # define __glibcxx_check_string(_String) # define __glibcxx_check_string_len(_String,_Len) @@ -75,8 +86,13 @@ namespace __gnu_debug const char* __function __attribute__((__unused__))) { #ifdef _GLIBCXX_DEBUG_PEDANTIC +# if __cplusplus < 201103L _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != 0 || __n == 0, __file, __line, __function); +# else + _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != nullptr || __n == 0, + __file, __line, __function); +# endif #endif return __s; } @@ -90,8 +106,13 @@ namespace __gnu_debug const char* __function __attribute__((__unused__))) { #ifdef _GLIBCXX_DEBUG_PEDANTIC +# if __cplusplus < 201103L _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != 0, __file, __line, __function); +# else + _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != nullptr, + __file, __line, __function); +# endif #endif return __s; } diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 3e71ecb..2b5cb05 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -2121,8 +2121,8 @@ namespace views::__adaptor take_view() requires default_initializable<_Vp> = default; constexpr - take_view(_Vp base, range_difference_t<_Vp> __count) - : _M_base(std::move(base)), _M_count(std::move(__count)) + take_view(_Vp __base, range_difference_t<_Vp> __count) + : _M_base(std::move(__base)), _M_count(std::move(__count)) { } constexpr _Vp @@ -2355,8 +2355,8 @@ namespace views::__adaptor = default; constexpr - take_while_view(_Vp base, _Pred __pred) - : _M_base(std::move(base)), _M_pred(std::move(__pred)) + take_while_view(_Vp __base, _Pred __pred) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) { } constexpr _Vp @@ -3116,7 +3116,6 @@ namespace views::__adaptor _Parent* _M_parent = nullptr; - // XXX: _M_current is present only if "V models forward_range" [[no_unique_address]] __detail::__maybe_present_t<forward_range<_Vp>, iterator_t<_Base>> _M_current; @@ -3370,7 +3369,6 @@ namespace views::__adaptor _Vp _M_base = _Vp(); _Pattern _M_pattern = _Pattern(); - // XXX: _M_current is "present only if !forward_range<V>" [[no_unique_address]] __detail::__maybe_present_t<!forward_range<_Vp>, __detail::__non_propagating_cache<iterator_t<_Vp>>> _M_current; @@ -3725,16 +3723,6 @@ namespace views::__adaptor : _M_base(std::move(__r)) { } - /* XXX: LWG 3280 didn't remove this constructor, but I think it should? - template<viewable_range _Range> - requires (!common_range<_Range>) - && constructible_from<_Vp, views::all_t<_Range>> - constexpr explicit - common_view(_Range&& __r) - : _M_base(views::all(std::forward<_Range>(__r))) - { } - */ - constexpr _Vp base() const& requires copy_constructible<_Vp> { return _M_base; } @@ -3994,8 +3982,8 @@ namespace views::__adaptor elements_view() requires default_initializable<_Vp> = default; constexpr explicit - elements_view(_Vp base) - : _M_base(std::move(base)) + elements_view(_Vp __base) + : _M_base(std::move(__base)) { } constexpr _Vp @@ -4115,14 +4103,14 @@ namespace views::__adaptor _Iterator() requires default_initializable<iterator_t<_Base>> = default; constexpr explicit - _Iterator(iterator_t<_Base> current) - : _M_current(std::move(current)) + _Iterator(iterator_t<_Base> __current) + : _M_current(std::move(__current)) { } constexpr - _Iterator(_Iterator<!_Const> i) + _Iterator(_Iterator<!_Const> __i) requires _Const && convertible_to<iterator_t<_Vp>, iterator_t<_Base>> - : _M_current(std::move(i._M_current)) + : _M_current(std::move(__i._M_current)) { } constexpr const iterator_t<_Base>& @@ -4352,6 +4340,1445 @@ namespace views::__adaptor inline constexpr auto values = elements<1>; } // namespace views +#if __cplusplus > 202002L + namespace __detail + { + template<typename... _Rs> + concept __zip_is_common = (sizeof...(_Rs) == 1 && (common_range<_Rs> && ...)) + || (!(bidirectional_range<_Rs> && ...) && (common_range<_Rs> && ...)) + || ((random_access_range<_Rs> && ...) && (sized_range<_Rs> && ...)); + + template<typename... _Ts> + struct __tuple_or_pair + { using type = std::tuple<_Ts...>; }; + + template<typename _Tp, typename _Up> + struct __tuple_or_pair<_Tp, _Up> + { using type = pair<_Tp, _Up>; }; + + template<typename... _Ts> + using __tuple_or_pair_t = typename __tuple_or_pair<_Ts...>::type; + + template<typename _Fp, typename _Tuple> + constexpr auto + __tuple_transform(_Fp&& __f, _Tuple&& __tuple) + { + return std::apply([&]<typename... _Ts>(_Ts&&... __elts) { + return __tuple_or_pair_t<invoke_result_t<_Fp&, _Ts>...> + (std::__invoke(__f, std::forward<_Ts>(__elts))...); + }, std::forward<_Tuple>(__tuple)); + } + + template<typename _Fp, typename _Tuple> + constexpr void + __tuple_for_each(_Fp&& __f, _Tuple&& __tuple) + { + std::apply([&]<typename... _Ts>(_Ts&&... __elts) { + (std::__invoke(__f, std::forward<_Ts>(__elts)), ...); + }, std::forward<_Tuple>(__tuple)); + } + } // namespace __detail + + template<input_range... _Vs> + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) + class zip_view : public view_interface<zip_view<_Vs...>> + { + tuple<_Vs...> _M_views; + + template<bool> class _Iterator; + template<bool> class _Sentinel; + + public: + zip_view() = default; + + constexpr explicit + zip_view(_Vs... __views) + : _M_views(std::move(__views)...) + { } + + constexpr auto + begin() requires (!(__detail::__simple_view<_Vs> && ...)) + { return _Iterator<false>(__detail::__tuple_transform(ranges::begin, _M_views)); } + + constexpr auto + begin() const requires (range<const _Vs> && ...) + { return _Iterator<true>(__detail::__tuple_transform(ranges::begin, _M_views)); } + + constexpr auto + end() requires (!(__detail::__simple_view<_Vs> && ...)) + { + if constexpr (!__detail::__zip_is_common<_Vs...>) + return _Sentinel<false>(__detail::__tuple_transform(ranges::end, _M_views)); + else if constexpr ((random_access_range<_Vs> && ...)) + return begin() + iter_difference_t<_Iterator<false>>(size()); + else + return _Iterator<false>(__detail::__tuple_transform(ranges::end, _M_views)); + } + + constexpr auto + end() const requires (range<const _Vs> && ...) + { + if constexpr (!__detail::__zip_is_common<const _Vs...>) + return _Sentinel<true>(__detail::__tuple_transform(ranges::end, _M_views)); + else if constexpr ((random_access_range<const _Vs> && ...)) + return begin() + iter_difference_t<_Iterator<true>>(size()); + else + return _Iterator<true>(__detail::__tuple_transform(ranges::end, _M_views)); + } + + constexpr auto + size() requires (sized_range<_Vs> && ...) + { + return std::apply([](auto... sizes) { + using _CT = __detail::__make_unsigned_like_t<common_type_t<decltype(sizes)...>>; + return ranges::min({_CT(sizes)...}); + }, __detail::__tuple_transform(ranges::size, _M_views)); + } + + constexpr auto + size() const requires (sized_range<const _Vs> && ...) + { + return std::apply([](auto... sizes) { + using _CT = __detail::__make_unsigned_like_t<common_type_t<decltype(sizes)...>>; + return ranges::min({_CT(sizes)...}); + }, __detail::__tuple_transform(ranges::size, _M_views)); + } + }; + + template<typename... _Rs> + zip_view(_Rs&&...) -> zip_view<views::all_t<_Rs>...>; + + template<typename... _Views> + inline constexpr bool enable_borrowed_range<zip_view<_Views...>> + = (enable_borrowed_range<_Views> && ...); + + namespace __detail + { + template<bool _Const, typename... _Vs> + concept __all_random_access + = (random_access_range<__maybe_const_t<_Const, _Vs>> && ...); + + template<bool _Const, typename... _Vs> + concept __all_bidirectional + = (bidirectional_range<__maybe_const_t<_Const, _Vs>> && ...); + + template<bool _Const, typename... _Vs> + concept __all_forward + = (forward_range<__maybe_const_t<_Const, _Vs>> && ...); + + template<bool _Const, typename... _Views> + struct __zip_view_iter_cat + { }; + + template<bool _Const, typename... _Views> + requires __all_forward<_Const, _Views...> + struct __zip_view_iter_cat<_Const, _Views...> + { using iterator_category = input_iterator_tag; }; + } // namespace __detail + + template<input_range... _Vs> + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) + template<bool _Const> + class zip_view<_Vs...>::_Iterator + : public __detail::__zip_view_iter_cat<_Const, _Vs...> + { + __detail::__tuple_or_pair_t<iterator_t<__detail::__maybe_const_t<_Const, _Vs>>...> _M_current; + + constexpr explicit + _Iterator(decltype(_M_current) __current) + : _M_current(std::move(__current)) + { } + + static auto + _S_iter_concept() + { + if constexpr (__detail::__all_random_access<_Const, _Vs...>) + return random_access_iterator_tag{}; + else if constexpr (__detail::__all_bidirectional<_Const, _Vs...>) + return bidirectional_iterator_tag{}; + else if constexpr (__detail::__all_forward<_Const, _Vs...>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + template<copy_constructible _Fp, input_range... _Ws> + requires (view<_Ws> && ...) && (sizeof...(_Ws) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Ws>...> + && std::__detail::__can_reference<invoke_result_t<_Fp&, range_reference_t<_Ws>...>> + friend class zip_transform_view; + + public: + // iterator_category defined in __zip_view_iter_cat + using iterator_concept = decltype(_S_iter_concept()); + using value_type + = __detail::__tuple_or_pair_t<range_value_t<__detail::__maybe_const_t<_Const, _Vs>>...>; + using difference_type + = common_type_t<range_difference_t<__detail::__maybe_const_t<_Const, _Vs>>...>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator<!_Const> __i) + requires _Const + && (convertible_to<iterator_t<_Vs>, + iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + : _M_current(std::move(__i._M_current)) + { } + + constexpr auto + operator*() const + { + auto __f = [](auto& __i) -> decltype(auto) { + return *__i; + }; + return __detail::__tuple_transform(__f, _M_current); + } + + constexpr _Iterator& + operator++() + { + __detail::__tuple_for_each([](auto& __i) { ++__i; }, _M_current); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) + requires __detail::__all_forward<_Const, _Vs...> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + requires __detail::__all_bidirectional<_Const, _Vs...> + { + __detail::__tuple_for_each([](auto& __i) { --__i; }, _M_current); + return *this; + } + + constexpr _Iterator + operator--(int) + requires __detail::__all_bidirectional<_Const, _Vs...> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __f = [&]<typename _It>(_It& __i) { + __i += iter_difference_t<_It>(__x); + }; + __detail::__tuple_for_each(__f, _M_current); + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __f = [&]<typename _It>(_It& __i) { + __i -= iter_difference_t<_It>(__x); + }; + __detail::__tuple_for_each(__f, _M_current); + return *this; + } + + constexpr auto + operator[](difference_type __n) const + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __f = [&]<typename _It>(_It& __i) -> decltype(auto) { + return __i[iter_difference_t<_It>(__n)]; + }; + return __detail::__tuple_transform(__f, _M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires (equality_comparable<iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + { + if constexpr (__detail::__all_bidirectional<_Const, _Vs...>) + return __x._M_current == __y._M_current; + else + return [&]<size_t... _Is>(index_sequence<_Is...>) { + return ((std::get<_Is>(__x._M_current) == std::get<_Is>(__y._M_current)) || ...); + }(make_index_sequence<sizeof...(_Vs)>{}); + } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires __detail::__all_random_access<_Const, _Vs...> + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires (sized_sentinel_for<iterator_t<__detail::__maybe_const_t<_Const, _Vs>>, + iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + { + return [&]<size_t... _Is>(index_sequence<_Is...>) { + return ranges::min({difference_type(std::get<_Is>(__x._M_current) + - std::get<_Is>(__y._M_current))...}, + ranges::less{}, + [](difference_type __i) -> make_unsigned_t<difference_type> { + return __i < 0 ? -__i : __i; + }); + }(make_index_sequence<sizeof...(_Vs)>{}); + } + + friend constexpr auto + iter_move(const _Iterator& __i) + { return __detail::__tuple_transform(ranges::iter_move, __i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __l, const _Iterator& __r) + requires (indirectly_swappable<iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + { + [&]<size_t... _Is>(index_sequence<_Is...>) { + (ranges::iter_swap(std::get<_Is>(__l._M_current), std::get<_Is>(__r._M_current)), ...); + }(make_index_sequence<sizeof...(_Vs)>{}); + } + + friend class zip_view; + }; + + template<input_range... _Vs> + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) + template<bool _Const> + class zip_view<_Vs...>::_Sentinel + { + __detail::__tuple_or_pair_t<sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>...> _M_end; + + constexpr explicit + _Sentinel(decltype(_M_end) __end) + : _M_end(__end) + { } + + friend class zip_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel<!_Const> __i) + requires _Const + && (convertible_to<sentinel_t<_Vs>, + sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + : _M_end(std::move(__i._M_end)) + { } + + template<bool _OtherConst> + requires (sentinel_for<sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...) + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { + return [&]<size_t... _Is>(index_sequence<_Is...>) { + return ((std::get<_Is>(__x._M_current) == std::get<_Is>(__y._M_end)) || ...); + }(make_index_sequence<sizeof...(_Vs)>{}); + } + + template<bool _OtherConst> + requires (sized_sentinel_for<sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...) + friend constexpr auto + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { + using _Ret + = common_type_t<range_difference_t<__detail::__maybe_const_t<_OtherConst, _Vs>>...>; + return [&]<size_t... _Is>(index_sequence<_Is...>) { + return ranges::min({_Ret(std::get<_Is>(__x._M_current) - std::get<_Is>(__y._M_end))...}, + ranges::less{}, + [](_Ret __i) -> make_unsigned_t<_Ret> { + return __i < 0 ? -__i : __i; + }); + }(make_index_sequence<sizeof...(_Vs)>{}); + } + + template<bool _OtherConst> + requires (sized_sentinel_for<sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...) + friend constexpr auto + operator-(const _Sentinel& __y, const _Iterator<_OtherConst>& __x) + { return -(__x - __y); } + }; + + namespace views + { + namespace __detail + { + template<typename... _Ts> + concept __can_zip_view + = requires { zip_view<all_t<_Ts>...>(std::declval<_Ts>()...); }; + } + + struct _Zip + { + template<typename... _Ts> + requires (sizeof...(_Ts) == 0 || __detail::__can_zip_view<_Ts...>) + constexpr auto + operator() [[nodiscard]] (_Ts&&... __ts) const + { + if constexpr (sizeof...(_Ts) == 0) + return views::empty<tuple<>>; + else + return zip_view<all_t<_Ts>...>(std::forward<_Ts>(__ts)...); + } + }; + + inline constexpr _Zip zip; + } + + namespace __detail + { + template<typename _Range, bool _Const> + using __range_iter_cat + = typename iterator_traits<iterator_t<__maybe_const_t<_Const, _Range>>>::iterator_category; + } + + template<copy_constructible _Fp, input_range... _Vs> + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vs>...> + && std::__detail::__can_reference<invoke_result_t<_Fp&, range_reference_t<_Vs>...>> + class zip_transform_view : public view_interface<zip_transform_view<_Fp, _Vs...>> + { + [[no_unique_address]] __detail::__box<_Fp> _M_fun; + zip_view<_Vs...> _M_zip; + + using _InnerView = zip_view<_Vs...>; + + template<bool _Const> + using __ziperator = iterator_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template<bool _Const> + using __zentinel = sentinel_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template<bool _Const> + using _Base = __detail::__maybe_const_t<_Const, _InnerView>; + + template<bool _Const> + struct __iter_cat + { }; + + template<bool _Const> + requires forward_range<_Base<_Const>> + struct __iter_cat<_Const> + { + private: + static auto + _S_iter_cat() + { + using __detail::__maybe_const_t; + using __detail::__range_iter_cat; + using _Res = invoke_result_t<__maybe_const_t<_Const, _Fp>&, + range_reference_t<__maybe_const_t<_Const, _Vs>>...>; + if constexpr (!is_lvalue_reference_v<_Res>) + return input_iterator_tag{}; + else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>, + random_access_iterator_tag> && ...)) + return random_access_iterator_tag{}; + else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>, + bidirectional_iterator_tag> && ...)) + return bidirectional_iterator_tag{}; + else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>, + forward_iterator_tag> && ...)) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + + template<bool> class _Iterator; + template<bool> class _Sentinel; + + public: + zip_transform_view() = default; + + constexpr explicit + zip_transform_view(_Fp __fun, _Vs... __views) + : _M_fun(std::move(__fun)), _M_zip(std::move(__views)...) + { } + + constexpr auto + begin() + { return _Iterator<false>(*this, _M_zip.begin()); } + + constexpr auto + begin() const + requires range<const _InnerView> + && regular_invocable<const _Fp&, range_reference_t<const _Vs>...> + { return _Iterator<true>(*this, _M_zip.begin()); } + + constexpr auto + end() + { + if constexpr (common_range<_InnerView>) + return _Iterator<false>(*this, _M_zip.end()); + else + return _Sentinel<false>(_M_zip.end()); + } + + constexpr auto + end() const + requires range<const _InnerView> + && regular_invocable<const _Fp&, range_reference_t<const _Vs>...> + { + if constexpr (common_range<const _InnerView>) + return _Iterator<true>(*this, _M_zip.end()); + else + return _Sentinel<true>(_M_zip.end()); + } + + constexpr auto + size() requires sized_range<_InnerView> + { return _M_zip.size(); } + + constexpr auto + size() const requires sized_range<const _InnerView> + { return _M_zip.size(); } + }; + + template<class _Fp, class... Rs> + zip_transform_view(_Fp, Rs&&...) -> zip_transform_view<_Fp, views::all_t<Rs>...>; + + template<copy_constructible _Fp, input_range... _Vs> + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vs>...> + && std::__detail::__can_reference<invoke_result_t<_Fp&, range_reference_t<_Vs>...>> + template<bool _Const> + class zip_transform_view<_Fp, _Vs...>::_Iterator : public __iter_cat<_Const> + { + using _Parent = __detail::__maybe_const_t<_Const, zip_transform_view>; + + _Parent* _M_parent = nullptr; + __ziperator<_Const> _M_inner; + + constexpr + _Iterator(_Parent& __parent, __ziperator<_Const> __inner) + : _M_parent(std::__addressof(__parent)), _M_inner(std::move(__inner)) + { } + + friend class zip_transform_view; + + public: + // iterator_category defined in zip_transform_view::__iter_cat + using iterator_concept = typename __ziperator<_Const>::iterator_concept; + using value_type + = remove_cvref_t<invoke_result_t<__detail::__maybe_const_t<_Const, _Fp>&, + range_reference_t<__detail::__maybe_const_t<_Const, _Vs>>...>>; + using difference_type = range_difference_t<_Base<_Const>>; + + _Iterator() = default; + + 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)) + { } + + constexpr decltype(auto) + operator*() const + { + return std::apply([&](const auto&... __iters) -> decltype(auto) { + return std::__invoke(*_M_parent->_M_fun, *__iters...); + }, _M_inner._M_current); + } + + constexpr _Iterator& + operator++() + { + ++_M_inner; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base<_Const>> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base<_Const>> + { + --_M_inner; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base<_Const>> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) requires random_access_range<_Base<_Const>> + { + _M_inner += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) requires random_access_range<_Base<_Const>> + { + _M_inner -= __x; + return *this; + } + + constexpr decltype(auto) + 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)]...); + }, _M_inner._M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<__ziperator<_Const>> + { return __x._M_inner == __y._M_inner; } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base<_Const>> + { return __x._M_inner <=> __y._M_inner; } + + 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); } + + 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); } + + 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); } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for<__ziperator<_Const>, __ziperator<_Const>> + { return __x._M_inner - __y._M_inner; } + }; + + template<copy_constructible _Fp, input_range... _Vs> + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vs>...> + && std::__detail::__can_reference<invoke_result_t<_Fp&, range_reference_t<_Vs>...>> + template<bool _Const> + class zip_transform_view<_Fp, _Vs...>::_Sentinel + { + __zentinel<_Const> _M_inner; + + constexpr explicit + _Sentinel(__zentinel<_Const> __inner) + : _M_inner(__inner) + { } + + friend class zip_transform_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel<!_Const> __i) + requires _Const && convertible_to<__zentinel<false>, __zentinel<_Const>> + : _M_inner(std::move(__i._M_inner)) + { } + + template<bool _OtherConst> + requires sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_inner == __y._M_inner; } + + template<bool _OtherConst> + requires sized_sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_inner - __y._M_inner; } + + template<bool _OtherConst> + requires sized_sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Sentinel& __x, const _Iterator<_OtherConst>& __y) + { return __x._M_inner - __y._M_inner; } + }; + + namespace views + { + namespace __detail + { + template<typename _Fp, typename... _Ts> + concept __can_zip_transform_view + = requires { zip_transform_view(std::declval<_Fp>(), std::declval<_Ts>()...); }; + } + + struct _ZipTransform + { + template<typename _Fp, typename... _Ts> + requires (sizeof...(_Ts) == 0) || __detail::__can_zip_transform_view<_Fp, _Ts...> + constexpr auto + operator() [[nodiscard]] (_Fp&& __f, _Ts&&... __ts) const + { + if constexpr (sizeof...(_Ts) == 0) + return views::empty<decay_t<invoke_result_t<_Fp>>>; + else + return zip_transform_view(std::forward<_Fp>(__f), std::forward<_Ts>(__ts)...); + } + }; + + inline constexpr _ZipTransform zip_transform; + } + + template<forward_range _Vp, size_t _Nm> + requires view<_Vp> && (_Nm > 0) + class adjacent_view : public view_interface<adjacent_view<_Vp, _Nm>> + { + _Vp _M_base = _Vp(); + + template<bool> class _Iterator; + template<bool> class _Sentinel; + + struct __as_sentinel + { }; + + public: + adjacent_view() requires default_initializable<_Vp> = default; + + constexpr explicit + adjacent_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return _Iterator<false>(ranges::begin(_M_base), ranges::end(_M_base)); } + + constexpr auto + begin() const requires range<const _Vp> + { return _Iterator<true>(ranges::begin(_M_base), ranges::end(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (common_range<_Vp>) + return _Iterator<false>(__as_sentinel{}, ranges::begin(_M_base), ranges::end(_M_base)); + else + return _Sentinel<false>(ranges::end(_M_base)); + } + + constexpr auto + end() const requires range<const _Vp> + { + if constexpr (common_range<const _Vp>) + return _Iterator<true>(__as_sentinel{}, ranges::begin(_M_base), ranges::end(_M_base)); + else + return _Sentinel<true>(ranges::end(_M_base)); + } + + constexpr auto + size() requires sized_range<_Vp> + { + using _ST = decltype(ranges::size(_M_base)); + using _CT = common_type_t<_ST, size_t>; + auto __sz = static_cast<_CT>(ranges::size(_M_base)); + __sz -= std::min<_CT>(__sz, _Nm - 1); + return static_cast<_ST>(__sz); + } + + constexpr auto + size() const requires sized_range<const _Vp> + { + using _ST = decltype(ranges::size(_M_base)); + using _CT = common_type_t<_ST, size_t>; + auto __sz = static_cast<_CT>(ranges::size(_M_base)); + __sz -= std::min<_CT>(__sz, _Nm - 1); + return static_cast<_ST>(__sz); + } + }; + + template<typename _Vp, size_t _Nm> + inline constexpr bool enable_borrowed_range<adjacent_view<_Vp, _Nm>> + = enable_borrowed_range<_Vp>; + + namespace __detail + { + // 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>>())); + + // For a functor F that is callable with N arguments, the expression + // declval<__unarize<F, N>>(x) is equivalent to declval<F>(x, ..., x). + template<typename _Fp, size_t _Nm> + struct __unarize + { + template<typename... _Ts> + static invoke_result_t<_Fp, _Ts...> + __tuple_apply(const tuple<_Ts...>&); // not defined + + template<typename _Tp> + decltype(__tuple_apply(std::declval<__repeated_tuple<_Tp, _Nm>>())) + operator()(_Tp&&); // not defined + }; + } + + template<forward_range _Vp, size_t _Nm> + requires view<_Vp> && (_Nm > 0) + template<bool _Const> + class adjacent_view<_Vp, _Nm>::_Iterator + { + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + array<iterator_t<_Base>, _Nm> _M_current = array<iterator_t<_Base>, _Nm>(); + + constexpr + _Iterator(iterator_t<_Base> __first, sentinel_t<_Base> __last) + { + for (auto& __i : _M_current) + { + __i = __first; + ranges::advance(__first, 1, __last); + } + } + + constexpr + _Iterator(__as_sentinel, iterator_t<_Base> __first, iterator_t<_Base> __last) + { + if constexpr (!bidirectional_range<_Base>) + for (auto& __it : _M_current) + __it = __last; + else + for (size_t __i = 0; __i < _Nm; ++__i) + { + _M_current[_Nm - 1 - __i] = __last; + ranges::advance(__last, -1, __first); + } + } + + static auto + _S_iter_concept() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else + return forward_iterator_tag{}; + } + + friend class adjacent_view; + + template<forward_range _Wp, copy_constructible _Fp, size_t _Mm> + requires view<_Wp> && (_Mm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Mm>, range_reference_t<_Wp>> + && std::__detail::__can_reference<invoke_result_t<__detail::__unarize<_Fp&, _Mm>, + range_reference_t<_Wp>>> + friend class adjacent_transform_view; + + 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 difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator<!_Const> __i) + requires _Const && convertible_to<iterator_t<_Vp>, iterator_t<_Base>> + { + for (size_t __j = 0; __j < _Nm; ++__j) + _M_current[__j] = std::move(__i[__j]); + } + + constexpr auto + operator*() const + { + auto __f = [](auto& __i) -> decltype(auto) { return *__i; }; + return __detail::__tuple_transform(__f, _M_current); + } + + constexpr _Iterator& + operator++() + { + for (auto& __i : _M_current) + ++__i; + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + for (auto& __i : _M_current) + --__i; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires random_access_range<_Base> + { + for (auto& __i : _M_current) + __i += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires random_access_range<_Base> + { + for (auto& __i : _M_current) + __i -= __x; + return *this; + } + + constexpr auto + operator[](difference_type __n) const + requires random_access_range<_Base> + { + auto __f = [&](auto& __i) -> decltype(auto) { return __i[__n]; }; + return __detail::__tuple_transform(__f, _M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { return __x._M_current.back() == __y._M_current.back(); } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current.back() < __y._M_current.back(); } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x < __y); } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable<iterator_t<_Base>> + { return __x._M_current.back() <=> __y._M_current.back(); } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> + { return __x._M_current.back() - __y._M_current.back(); } + + friend constexpr auto + iter_move(const _Iterator& __i) + { return __detail::__tuple_transform(ranges::iter_move, __i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __l, const _Iterator& __r) + requires indirectly_swappable<iterator_t<_Base>> + { + for (size_t __i = 0; __i < _Nm; __i++) + ranges::iter_swap(__l._M_current[__i], __r._M_current[__i]); + } + }; + + template<forward_range _Vp, size_t _Nm> + requires view<_Vp> && (_Nm > 0) + template<bool _Const> + class adjacent_view<_Vp, _Nm>::_Sentinel + { + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(__end) + { } + + friend class adjacent_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel<!_Const> __i) + requires _Const && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>> + : _M_end(std::move(__i._M_end)) + { } + + template<bool _OtherConst> + requires sentinel_for<sentinel_t<_Base>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_current.back() == __y._M_end; } + + template<bool _OtherConst> + requires sized_sentinel_for<sentinel_t<_Base>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _Vp>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_current.back() - __y._M_end; } + + template<bool _OtherConst> + requires sized_sentinel_for<sentinel_t<_Base>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _Vp>> + operator-(const _Sentinel& __y, const _Iterator<_OtherConst>& __x) + { return __y._M_end - __x._M_current.back(); } + }; + + namespace views + { + namespace __detail + { + template<size_t _Nm, typename _Range> + concept __can_adjacent_view + = requires { adjacent_view<all_t<_Range>, _Nm>(std::declval<_Range>()); }; + } + + template<size_t _Nm> + struct _Adjacent : __adaptor::_RangeAdaptorClosure + { + template<viewable_range _Range> + requires (_Nm == 0) || __detail::__can_adjacent_view<_Nm, _Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { + if constexpr (_Nm == 0) + return views::empty<tuple<>>; + else + return adjacent_view<all_t<_Range>, _Nm>(std::forward<_Range>(__r)); + } + }; + + template<size_t _Nm> + inline constexpr _Adjacent<_Nm> adjacent; + + inline constexpr auto pairwise = adjacent<2>; + } + + template<forward_range _Vp, copy_constructible _Fp, size_t _Nm> + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference<invoke_result_t<__detail::__unarize<_Fp&, _Nm>, + range_reference_t<_Vp>>> + class adjacent_transform_view : public view_interface<adjacent_transform_view<_Vp, _Fp, _Nm>> + { + [[no_unique_address]] __detail::__box<_Fp> _M_fun; + adjacent_view<_Vp, _Nm> _M_inner; + + using _InnerView = adjacent_view<_Vp, _Nm>; + + template<bool _Const> + using _InnerIter = iterator_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template<bool _Const> + using _InnerSent = sentinel_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template<bool> class _Iterator; + template<bool> class _Sentinel; + + public: + adjacent_transform_view() = default; + + constexpr explicit + adjacent_transform_view(_Vp __base, _Fp __fun) + : _M_fun(std::move(__fun)), _M_inner(std::move(__base)) + { } + + constexpr auto + begin() + { return _Iterator<false>(*this, _M_inner.begin()); } + + constexpr auto + begin() const + requires range<const _InnerView> + && regular_invocable<__detail::__unarize<const _Fp&, _Nm>, + range_reference_t<const _Vp>> + { return _Iterator<true>(*this, _M_inner.begin()); } + + constexpr auto + end() + { + if constexpr (common_range<_InnerView>) + return _Iterator<false>(*this, _M_inner.end()); + else + return _Sentinel<false>(_M_inner.end()); + } + + constexpr auto + end() const + requires range<const _InnerView> + && regular_invocable<__detail::__unarize<const _Fp&, _Nm>, + range_reference_t<const _Vp>> + { + if constexpr (common_range<const _InnerView>) + return _Iterator<true>(*this, _M_inner.end()); + else + return _Sentinel<true>(_M_inner.end()); + } + + constexpr auto + size() requires sized_range<_InnerView> + { return _M_inner.size(); } + + constexpr auto + size() const requires sized_range<const _InnerView> + { return _M_inner.size(); } + }; + + template<forward_range _Vp, copy_constructible _Fp, size_t _Nm> + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference<invoke_result_t<__detail::__unarize<_Fp&, _Nm>, + range_reference_t<_Vp>>> + template<bool _Const> + class adjacent_transform_view<_Vp, _Fp, _Nm>::_Iterator + { + using _Parent = __detail::__maybe_const_t<_Const, adjacent_transform_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + _Parent* _M_parent = nullptr; + _InnerIter<_Const> _M_inner; + + constexpr + _Iterator(_Parent& __parent, _InnerIter<_Const> __inner) + : _M_parent(std::__addressof(__parent)), _M_inner(std::move(__inner)) + { } + + static auto + _S_iter_cat() + { + using __detail::__maybe_const_t; + using __detail::__unarize; + using _Res = invoke_result_t<__unarize<__maybe_const_t<_Const, _Fp>&, _Nm>, + range_reference_t<_Base>>; + using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category; + if constexpr (!is_lvalue_reference_v<_Res>) + return input_iterator_tag{}; + else if constexpr (derived_from<_Cat, random_access_iterator_tag>) + return random_access_iterator_tag{}; + else if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) + return bidirectional_iterator_tag{}; + else if constexpr (derived_from<_Cat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend class adjacent_transform_view; + + public: + using iterator_category = decltype(_S_iter_cat()); + using iterator_concept = typename _InnerIter<_Const>::iterator_concept; + using value_type + = remove_cvref_t<invoke_result_t + <__detail::__unarize<__detail::__maybe_const_t<_Const, _Fp>&, _Nm>, + range_reference_t<_Base>>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + 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)) + { } + + constexpr decltype(auto) + operator*() const + { + return std::apply([&](const auto&... __iters) -> decltype(auto) { + return std::__invoke(*_M_parent->_M_fun, *__iters...); + }, _M_inner._M_current); + } + + constexpr _Iterator& + operator++() + { + ++_M_inner; + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_inner; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) requires random_access_range<_Base> + { + _M_inner += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) requires random_access_range<_Base> + { + _M_inner -= __x; + return *this; + } + + constexpr decltype(auto) + 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]...); + }, _M_inner._M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { return __x._M_inner == __y._M_inner; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner < __y._M_inner; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner > __y._M_inner; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner <= __y._M_inner; } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner >= __y._M_inner; } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> && + three_way_comparable<_InnerIter<_Const>> + { return __x._M_inner <=> __y._M_inner; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { return _Iterator(*__i._M_parent, __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); } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { return _Iterator(*__i._M_parent, __i._M_inner - __n); } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for<_InnerIter<_Const>, _InnerIter<_Const>> + { return __x._M_inner - __y._M_inner; } + }; + + template<forward_range _Vp, copy_constructible _Fp, size_t _Nm> + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference<invoke_result_t<__detail::__unarize<_Fp&, _Nm>, + range_reference_t<_Vp>>> + template<bool _Const> + class adjacent_transform_view<_Vp, _Fp, _Nm>::_Sentinel + { + _InnerSent<_Const> _M_inner; + + constexpr explicit + _Sentinel(_InnerSent<_Const> __inner) + : _M_inner(__inner) + { } + + friend class adjacent_transform_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel<!_Const> __i) + requires _Const && convertible_to<_InnerSent<false>, _InnerSent<_Const>> + : _M_inner(std::move(__i._M_inner)) + { } + + template<bool _OtherConst> + requires sentinel_for<_InnerSent<_Const>, _InnerIter<_OtherConst>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_inner == __y._M_inner; } + + template<bool _OtherConst> + requires sized_sentinel_for<_InnerSent<_Const>, _InnerIter<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_inner - __y._M_inner; } + + template<bool _OtherConst> + requires sized_sentinel_for<_InnerSent<_Const>, _InnerIter<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Sentinel& __x, const _Iterator<_OtherConst>& __y) + { return __x._M_inner - __y._M_inner; } + }; + + namespace views + { + namespace __detail + { + template<size_t _Nm, typename _Range, typename _Fp> + concept __can_adjacent_transform_view + = requires { adjacent_transform_view<all_t<_Range>, decay_t<_Fp>, _Nm> + (std::declval<_Range>(), std::declval<_Fp>()); }; + } + + template<size_t _Nm> + struct _AdjacentTransform : __adaptor::_RangeAdaptor<_AdjacentTransform<_Nm>> + { + template<viewable_range _Range, typename _Fp> + requires (_Nm == 0) || __detail::__can_adjacent_transform_view<_Nm, _Range, _Fp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Fp&& __f) const + { + if constexpr (_Nm == 0) + return views::empty<tuple<>>; + else + return adjacent_transform_view<all_t<_Range>, decay_t<_Fp>, _Nm> + (std::forward<_Range>(__r), std::forward<_Fp>(__f)); + } + + using __adaptor::_RangeAdaptor<_AdjacentTransform>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + template<size_t _Nm> + inline constexpr _AdjacentTransform<_Nm> adjacent_transform; + + inline constexpr auto pairwise_transform = adjacent_transform<2>; + } +#endif // C++23 } // namespace ranges namespace views = ranges::views; diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index 30ff136..2604af2 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -129,7 +129,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr basic_string_view(const basic_string_view&) noexcept = default; - __attribute__((__nonnull__)) constexpr + [[__gnu__::__nonnull__]] + constexpr basic_string_view(const _CharT* __str) noexcept : _M_len{traits_type::length(__str)}, _M_str{__str} @@ -172,54 +173,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif // C++23 #endif // C++20 - constexpr basic_string_view& operator=(const basic_string_view&) noexcept = default; // [string.view.iterators], iterator support + [[nodiscard]] constexpr const_iterator begin() const noexcept { return this->_M_str; } + [[nodiscard]] constexpr const_iterator end() const noexcept { return this->_M_str + this->_M_len; } + [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return this->_M_str; } + [[nodiscard]] constexpr const_iterator cend() const noexcept { return this->_M_str + this->_M_len; } + [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(this->end()); } + [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(this->begin()); } + [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(this->end()); } + [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(this->begin()); } // [string.view.capacity], capacity + [[nodiscard]] constexpr size_type size() const noexcept { return this->_M_len; } + [[nodiscard]] constexpr size_type length() const noexcept { return _M_len; } + [[nodiscard]] constexpr size_type max_size() const noexcept { @@ -227,12 +238,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION / sizeof(value_type) / 4; } - [[nodiscard]] constexpr bool + [[nodiscard]] + constexpr bool empty() const noexcept { return this->_M_len == 0; } // [string.view.access], element access + [[nodiscard]] constexpr const_reference operator[](size_type __pos) const noexcept { @@ -240,6 +253,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *(this->_M_str + __pos); } + [[nodiscard]] constexpr const_reference at(size_type __pos) const { @@ -250,6 +264,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *(this->_M_str + __pos); } + [[nodiscard]] constexpr const_reference front() const noexcept { @@ -257,6 +272,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this->_M_str; } + [[nodiscard]] constexpr const_reference back() const noexcept { @@ -264,6 +280,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *(this->_M_str + this->_M_len - 1); } + [[nodiscard]] constexpr const_pointer data() const noexcept { return this->_M_str; } @@ -305,6 +322,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __rlen; } + [[nodiscard]] constexpr basic_string_view substr(size_type __pos = 0, size_type __n = npos) const noexcept(false) { @@ -313,6 +331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return basic_string_view{_M_str + __pos, __rlen}; } + [[nodiscard]] constexpr int compare(basic_string_view __str) const noexcept { @@ -323,10 +342,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __ret; } + [[nodiscard]] constexpr int compare(size_type __pos1, size_type __n1, basic_string_view __str) const { return this->substr(__pos1, __n1).compare(__str); } + [[nodiscard]] constexpr int compare(size_type __pos1, size_type __n1, basic_string_view __str, size_type __pos2, size_type __n2) const @@ -334,14 +355,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); } - __attribute__((__nonnull__)) constexpr int + [[nodiscard, __gnu__::__nonnull__]] + constexpr int compare(const _CharT* __str) const noexcept { return this->compare(basic_string_view{__str}); } - __attribute__((__nonnull__)) constexpr int + [[nodiscard, __gnu__::__nonnull__]] + constexpr int compare(size_type __pos1, size_type __n1, const _CharT* __str) const { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } + [[nodiscard]] constexpr int compare(size_type __pos1, size_type __n1, const _CharT* __str, size_type __n2) const noexcept(false) @@ -352,18 +376,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus > 201703L #define __cpp_lib_starts_ends_with 201711L + [[nodiscard]] constexpr bool starts_with(basic_string_view __x) const noexcept { return this->substr(0, __x.size()) == __x; } + [[nodiscard]] constexpr bool starts_with(_CharT __x) const noexcept { return !this->empty() && traits_type::eq(this->front(), __x); } + [[nodiscard, __gnu__::__nonnull__]] constexpr bool starts_with(const _CharT* __x) const noexcept { return this->starts_with(basic_string_view(__x)); } + [[nodiscard]] constexpr bool ends_with(basic_string_view __x) const noexcept { @@ -373,10 +401,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && traits_type::compare(end() - __xlen, __x.data(), __xlen) == 0; } + [[nodiscard]] constexpr bool ends_with(_CharT __x) const noexcept { return !this->empty() && traits_type::eq(this->back(), __x); } + [[nodiscard, __gnu__::__nonnull__]] constexpr bool ends_with(const _CharT* __x) const noexcept { return this->ends_with(basic_string_view(__x)); } @@ -384,14 +414,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus > 202002L #define __cpp_lib_string_contains 202011L + [[nodiscard]] constexpr bool contains(basic_string_view __x) const noexcept { return this->find(__x) != npos; } + [[nodiscard]] constexpr bool contains(_CharT __x) const noexcept { return this->find(__x) != npos; } + [[nodiscard, __gnu__::__nonnull__]] constexpr bool contains(const _CharT* __x) const noexcept { return this->find(__x) != npos; } @@ -399,99 +432,123 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [string.view.find], searching + [[nodiscard]] constexpr size_type find(basic_string_view __str, size_type __pos = 0) const noexcept { return this->find(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type find(_CharT __c, size_type __pos = 0) const noexcept; + [[nodiscard]] constexpr size_type find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type find(const _CharT* __str, size_type __pos = 0) const noexcept { return this->find(__str, __pos, traits_type::length(__str)); } + [[nodiscard]] constexpr size_type rfind(basic_string_view __str, size_type __pos = npos) const noexcept { return this->rfind(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type rfind(_CharT __c, size_type __pos = npos) const noexcept; + [[nodiscard]] constexpr size_type rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type rfind(const _CharT* __str, size_type __pos = npos) const noexcept { return this->rfind(__str, __pos, traits_type::length(__str)); } + [[nodiscard]] constexpr size_type find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept { return this->find_first_of(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type find_first_of(_CharT __c, size_type __pos = 0) const noexcept { return this->find(__c, __pos); } + [[nodiscard]] constexpr size_type find_first_of(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept { return this->find_first_of(__str, __pos, traits_type::length(__str)); } + [[nodiscard]] constexpr size_type find_last_of(basic_string_view __str, size_type __pos = npos) const noexcept { return this->find_last_of(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type find_last_of(_CharT __c, size_type __pos=npos) const noexcept { return this->rfind(__c, __pos); } + [[nodiscard]] constexpr size_type find_last_of(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept { return this->find_last_of(__str, __pos, traits_type::length(__str)); } + [[nodiscard]] constexpr size_type find_first_not_of(basic_string_view __str, size_type __pos = 0) const noexcept { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; + [[nodiscard]] constexpr size_type find_first_not_of(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept { return this->find_first_not_of(__str, __pos, traits_type::length(__str)); } + [[nodiscard]] constexpr size_type find_last_not_of(basic_string_view __str, size_type __pos = npos) const noexcept { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; + [[nodiscard]] constexpr size_type find_last_not_of(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type find_last_not_of(const _CharT* __str, size_type __pos = npos) const noexcept { @@ -536,12 +593,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // type (see N3766). template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator==(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.size() == __y.size() && __x.compare(__y) == 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator==(basic_string_view<_CharT, _Traits> __x, __type_identity_t<basic_string_view<_CharT, _Traits>> __y) @@ -550,6 +609,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cpp_lib_three_way_comparison template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr auto operator<=>(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept @@ -557,6 +617,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr auto operator<=>(basic_string_view<_CharT, _Traits> __x, __type_identity_t<basic_string_view<_CharT, _Traits>> __y) @@ -565,18 +626,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } #else template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator==(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.size() == __y.size() && __x.compare(__y) == 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator!=(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return !(__x == __y); } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator!=(basic_string_view<_CharT, _Traits> __x, __type_identity_t<basic_string_view<_CharT, _Traits>> __y) @@ -584,18 +648,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !(__x == __y); } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator!=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return !(__x == __y); } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator< (basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) < 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator< (basic_string_view<_CharT, _Traits> __x, __type_identity_t<basic_string_view<_CharT, _Traits>> __y) @@ -603,18 +670,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x.compare(__y) < 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator< (__type_identity_t<basic_string_view<_CharT, _Traits>> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) < 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator> (basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) > 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator> (basic_string_view<_CharT, _Traits> __x, __type_identity_t<basic_string_view<_CharT, _Traits>> __y) @@ -622,18 +692,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x.compare(__y) > 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator> (__type_identity_t<basic_string_view<_CharT, _Traits>> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) > 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator<=(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) <= 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator<=(basic_string_view<_CharT, _Traits> __x, __type_identity_t<basic_string_view<_CharT, _Traits>> __y) @@ -641,18 +714,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x.compare(__y) <= 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator<=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) <= 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator>=(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) >= 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator>=(basic_string_view<_CharT, _Traits> __x, __type_identity_t<basic_string_view<_CharT, _Traits>> __y) @@ -660,6 +736,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x.compare(__y) >= 0; } template<typename _CharT, typename _Traits> + [[nodiscard]] constexpr bool operator>=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, basic_string_view<_CharT, _Traits> __y) noexcept @@ -693,6 +770,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash<string_view> : public __hash_base<size_t, string_view> { + [[nodiscard]] size_t operator()(const string_view& __str) const noexcept { return std::_Hash_impl::hash(__str.data(), __str.length()); } @@ -706,6 +784,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash<wstring_view> : public __hash_base<size_t, wstring_view> { + [[nodiscard]] size_t operator()(const wstring_view& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), @@ -721,6 +800,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash<u8string_view> : public __hash_base<size_t, u8string_view> { + [[nodiscard]] size_t operator()(const u8string_view& __str) const noexcept { return std::_Hash_impl::hash(__str.data(), __str.length()); } @@ -735,6 +815,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash<u16string_view> : public __hash_base<size_t, u16string_view> { + [[nodiscard]] size_t operator()(const u16string_view& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), @@ -749,6 +830,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash<u32string_view> : public __hash_base<size_t, u32string_view> { + [[nodiscard]] size_t operator()(const u32string_view& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error index 87cf720..0504394 100644 --- a/libstdc++-v3/include/std/system_error +++ b/libstdc++-v3/include/std/system_error @@ -216,6 +216,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) */ class error_code { + template<typename _ErrorCodeEnum> + using _Check + = __enable_if_t<is_error_code_enum<_ErrorCodeEnum>::value>; + public: error_code() noexcept : _M_value(0), _M_cat(&system_category()) { } @@ -223,11 +227,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) error_code(int __v, const error_category& __cat) noexcept : _M_value(__v), _M_cat(&__cat) { } - template<typename _ErrorCodeEnum, typename = typename - enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type> + /// Initialize with a user-defined type, by calling make_error_code. + template<typename _ErrorCodeEnum, + typename = _Check<_ErrorCodeEnum>> error_code(_ErrorCodeEnum __e) noexcept { *this = make_error_code(__e); } + error_code(const error_code&) = default; + error_code& operator=(const error_code&) = default; + void assign(int __v, const error_category& __cat) noexcept { @@ -239,13 +247,6 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) clear() noexcept { assign(0, system_category()); } - // DR 804. - template<typename _ErrorCodeEnum> - typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value, - error_code&>::type - operator=(_ErrorCodeEnum __e) noexcept - { return *this = make_error_code(__e); } - /// The error value. [[__nodiscard__]] int @@ -345,6 +346,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) */ class error_condition { + template<typename _ErrorConditionEnum> + using _Check + = __enable_if_t<is_error_condition_enum<_ErrorConditionEnum>::value>; + public: /// Initialize with a zero (no error) value and the generic category. error_condition() noexcept @@ -354,11 +359,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) error_condition(int __v, const error_category& __cat) noexcept : _M_value(__v), _M_cat(&__cat) { } - template<typename _ErrorConditionEnum, typename = typename - enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type> + /// Initialize with a user-defined type, by calling make_error_condition. + template<typename _ErrorConditionEnum, + typename = _Check<_ErrorConditionEnum>> error_condition(_ErrorConditionEnum __e) noexcept { *this = make_error_condition(__e); } + error_condition(const error_condition&) = default; + error_condition& operator=(const error_condition&) = default; + /// Set the value and category. void assign(int __v, const error_category& __cat) noexcept @@ -367,13 +376,6 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) _M_cat = &__cat; } - // DR 804. - template<typename _ErrorConditionEnum> - typename enable_if<is_error_condition_enum - <_ErrorConditionEnum>::value, error_condition&>::type - operator=(_ErrorConditionEnum __e) noexcept - { return *this = make_error_condition(__e); } - /// Reset the value and category to the default-constructed state. void clear() noexcept diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 05433d5..26e2484 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -826,7 +826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // then TUPLE should match tuple(UTypes&&...) instead. template<typename _Tuple, typename _Tp, typename _Up> struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>> - : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>> + : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type { }; // If TUPLE and *this each have a single element of the same type, // then TUPLE should match a copy/move constructor instead. @@ -1176,9 +1176,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _Inherited::_M_swap(__in); } #if __cplusplus > 202002L + // As an extension, we constrain the const swap member function in order + // to continue accepting explicit instantiation of tuples whose elements + // are not all const swappable. Without this constraint, such an + // explicit instantiation would also instantiate the ill-formed body of + // this function and yield a hard error. This constraint shouldn't + // affect the behavior of valid programs. constexpr void swap(const tuple& __in) const noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>) + requires (is_swappable_v<const _Elements> && ...) { _Inherited::_M_swap(__in); } #endif // C++23 }; @@ -1730,6 +1737,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION swap(const tuple& __in) const noexcept(__and_v<__is_nothrow_swappable<const _T1>, __is_nothrow_swappable<const _T2>>) + requires is_swappable_v<const _T1> && is_swappable_v<const _T2> { _Inherited::_M_swap(__in); } #endif // C++23 }; diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 14b029c..c7a9607 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -100,6 +100,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Metaprogramming helper types. + // Primary template. + /// Define a member typedef `type` only if a boolean constant is true. + template<bool, typename _Tp = void> + struct enable_if + { }; + + // Partial specialization for true. + template<typename _Tp> + struct enable_if<true, _Tp> + { typedef _Tp type; }; + + // __enable_if_t (std::enable_if_t for C++11) + template<bool _Cond, typename _Tp = void> + using __enable_if_t = typename enable_if<_Cond, _Tp>::type; + template<bool> struct __conditional { @@ -127,55 +142,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> using __type_identity_t = typename __type_identity<_Tp>::type; - template<typename...> - struct __or_; - - template<> - struct __or_<> - : public false_type - { }; - - template<typename _B1> - struct __or_<_B1> - : public _B1 - { }; - - template<typename _B1, typename _B2> - struct __or_<_B1, _B2> - : public __conditional_t<_B1::value, _B1, _B2> - { }; + namespace __detail + { + // A variadic alias template that resolves to its first argument. + template<typename _Tp, typename...> + using __first_t = _Tp; - template<typename _B1, typename _B2, typename _B3, typename... _Bn> - struct __or_<_B1, _B2, _B3, _Bn...> - : public __conditional_t<_B1::value, _B1, __or_<_B2, _B3, _Bn...>> - { }; + // These are deliberately not defined. + template<typename... _Bn> + auto __or_fn(int) -> __first_t<false_type, + __enable_if_t<!bool(_Bn::value)>...>; - template<typename...> - struct __and_; + template<typename... _Bn> + auto __or_fn(...) -> true_type; - template<> - struct __and_<> - : public true_type - { }; + template<typename... _Bn> + auto __and_fn(int) -> __first_t<true_type, + __enable_if_t<bool(_Bn::value)>...>; - template<typename _B1> - struct __and_<_B1> - : public _B1 - { }; + template<typename... _Bn> + auto __and_fn(...) -> false_type; + } // namespace detail - template<typename _B1, typename _B2> - struct __and_<_B1, _B2> - : public __conditional_t<_B1::value, _B2, _B1> + // Like C++17 std::dis/conjunction, but usable in C++11 and resolves + // to either true_type or false_type which allows for a more efficient + // implementation that avoids recursive class template instantiation. + template<typename... _Bn> + struct __or_ + : decltype(__detail::__or_fn<_Bn...>(0)) { }; - template<typename _B1, typename _B2, typename _B3, typename... _Bn> - struct __and_<_B1, _B2, _B3, _Bn...> - : public __conditional_t<_B1::value, __and_<_B2, _B3, _Bn...>, _B1> + template<typename... _Bn> + struct __and_ + : decltype(__detail::__and_fn<_Bn...>(0)) { }; template<typename _Pp> struct __not_ - : public __bool_constant<!bool(_Pp::value)> + : __bool_constant<!bool(_Pp::value)> { }; /// @endcond @@ -186,23 +190,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline constexpr bool __or_v = __or_<_Bn...>::value; template<typename... _Bn> inline constexpr bool __and_v = __and_<_Bn...>::value; + + namespace __detail + { + template<typename /* = void */, typename _B1, typename... _Bn> + struct __disjunction_impl + { using type = _B1; }; + + template<typename _B1, typename _B2, typename... _Bn> + struct __disjunction_impl<__enable_if_t<!bool(_B1::value)>, _B1, _B2, _Bn...> + { using type = typename __disjunction_impl<void, _B2, _Bn...>::type; }; + + template<typename /* = void */, typename _B1, typename... _Bn> + struct __conjunction_impl + { using type = _B1; }; + + template<typename _B1, typename _B2, typename... _Bn> + struct __conjunction_impl<__enable_if_t<bool(_B1::value)>, _B1, _B2, _Bn...> + { using type = typename __conjunction_impl<void, _B2, _Bn...>::type; }; + } // namespace __detail /// @endcond #define __cpp_lib_logical_traits 201510L template<typename... _Bn> struct conjunction - : __and_<_Bn...> + : __detail::__conjunction_impl<void, _Bn...>::type + { }; + + template<> + struct conjunction<> + : true_type { }; template<typename... _Bn> struct disjunction - : __or_<_Bn...> + : __detail::__disjunction_impl<void, _Bn...>::type + { }; + + template<> + struct disjunction<> + : false_type { }; template<typename _Pp> struct negation - : __not_<_Pp> + : __not_<_Pp>::type { }; /** @ingroup variable_templates @@ -685,18 +718,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __void_t (std::void_t for C++11) template<typename...> using __void_t = void; - - // Utility to detect referenceable types ([defns.referenceable]). - - template<typename _Tp, typename = void> - struct __is_referenceable - : public false_type - { }; - - template<typename _Tp> - struct __is_referenceable<_Tp, __void_t<_Tp&>> - : public true_type - { }; /// @endcond // Type properties. @@ -824,7 +845,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_unsigned template<typename _Tp> struct is_unsigned - : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>> + : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type { }; /// @cond undocumented @@ -840,21 +861,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> auto declval() noexcept -> decltype(__declval<_Tp>(0)); - template<typename, unsigned = 0> - struct extent; - template<typename> struct remove_all_extents; /// @cond undocumented template<typename _Tp> struct __is_array_known_bounds - : public integral_constant<bool, (extent<_Tp>::value > 0)> + : public false_type + { }; + + template<typename _Tp, size_t _Size> + struct __is_array_known_bounds<_Tp[_Size]> + : public true_type { }; template<typename _Tp> struct __is_array_unknown_bounds - : public __and_<is_array<_Tp>, __not_<extent<_Tp>>> + : public false_type + { }; + + template<typename _Tp> + struct __is_array_unknown_bounds<_Tp[]> + : public true_type { }; // Destructible and constructible type properties. @@ -967,9 +995,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @cond undocumented template<typename _Tp, typename... _Args> - struct __is_constructible_impl - : public __bool_constant<__is_constructible(_Tp, _Args...)> - { }; + using __is_constructible_impl + = __bool_constant<__is_constructible(_Tp, _Args...)>; /// @endcond /// is_constructible @@ -984,53 +1011,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_default_constructible template<typename _Tp> struct is_default_constructible - : public __is_constructible_impl<_Tp>::type + : public __is_constructible_impl<_Tp> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// @cond undocumented - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_copy_constructible_impl; + template<typename _Tp, typename = void> + struct __add_lvalue_reference_helper + { using type = _Tp; }; template<typename _Tp> - struct __is_copy_constructible_impl<_Tp, false> - : public false_type { }; + struct __add_lvalue_reference_helper<_Tp, __void_t<_Tp&>> + { using type = _Tp&; }; template<typename _Tp> - struct __is_copy_constructible_impl<_Tp, true> - : public __is_constructible_impl<_Tp, const _Tp&> - { }; + using __add_lval_ref_t = typename __add_lvalue_reference_helper<_Tp>::type; /// @endcond /// is_copy_constructible template<typename _Tp> struct is_copy_constructible - : public __is_copy_constructible_impl<_Tp> + : public __is_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// @cond undocumented - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_move_constructible_impl; + template<typename _Tp, typename = void> + struct __add_rvalue_reference_helper + { using type = _Tp; }; template<typename _Tp> - struct __is_move_constructible_impl<_Tp, false> - : public false_type { }; + struct __add_rvalue_reference_helper<_Tp, __void_t<_Tp&&>> + { using type = _Tp&&; }; template<typename _Tp> - struct __is_move_constructible_impl<_Tp, true> - : public __is_constructible_impl<_Tp, _Tp&&> - { }; + using __add_rval_ref_t = typename __add_rvalue_reference_helper<_Tp>::type; /// @endcond /// is_move_constructible template<typename _Tp> struct is_move_constructible - : public __is_move_constructible_impl<_Tp> + : public __is_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1045,7 +1070,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_nothrow_constructible template<typename _Tp, typename... _Args> struct is_nothrow_constructible - : public __is_nothrow_constructible_impl<_Tp, _Args...>::type + : public __is_nothrow_constructible_impl<_Tp, _Args...> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1054,112 +1079,68 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_nothrow_default_constructible template<typename _Tp> struct is_nothrow_default_constructible - : public __bool_constant<__is_nothrow_constructible(_Tp)> + : public __is_nothrow_constructible_impl<_Tp> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - /// @cond undocumented - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_nothrow_copy_constructible_impl; - - template<typename _Tp> - struct __is_nothrow_copy_constructible_impl<_Tp, false> - : public false_type { }; - - template<typename _Tp> - struct __is_nothrow_copy_constructible_impl<_Tp, true> - : public __is_nothrow_constructible_impl<_Tp, const _Tp&> - { }; - /// @endcond - /// is_nothrow_copy_constructible template<typename _Tp> struct is_nothrow_copy_constructible - : public __is_nothrow_copy_constructible_impl<_Tp>::type + : public __is_nothrow_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - /// @cond undocumented - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_nothrow_move_constructible_impl; - - template<typename _Tp> - struct __is_nothrow_move_constructible_impl<_Tp, false> - : public false_type { }; - - template<typename _Tp> - struct __is_nothrow_move_constructible_impl<_Tp, true> - : public __is_nothrow_constructible_impl<_Tp, _Tp&&> - { }; - /// @endcond - /// is_nothrow_move_constructible template<typename _Tp> struct is_nothrow_move_constructible - : public __is_nothrow_move_constructible_impl<_Tp>::type + : public __is_nothrow_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; + /// @cond undocumented + template<typename _Tp, typename _Up> + using __is_assignable_impl = __bool_constant<__is_assignable(_Tp, _Up)>; + /// @endcond + /// is_assignable template<typename _Tp, typename _Up> struct is_assignable - : public __bool_constant<__is_assignable(_Tp, _Up)> + : public __is_assignable_impl<_Tp, _Up> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_copy_assignable_impl; - - template<typename _Tp> - struct __is_copy_assignable_impl<_Tp, false> - : public false_type { }; - - template<typename _Tp> - struct __is_copy_assignable_impl<_Tp, true> - : public __bool_constant<__is_assignable(_Tp&, const _Tp&)> - { }; - /// is_copy_assignable template<typename _Tp> struct is_copy_assignable - : public __is_copy_assignable_impl<_Tp>::type + : public __is_assignable_impl<__add_lval_ref_t<_Tp>, + __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_move_assignable_impl; - - template<typename _Tp> - struct __is_move_assignable_impl<_Tp, false> - : public false_type { }; - - template<typename _Tp> - struct __is_move_assignable_impl<_Tp, true> - : public __bool_constant<__is_assignable(_Tp&, _Tp&&)> - { }; - /// is_move_assignable template<typename _Tp> struct is_move_assignable - : public __is_move_assignable_impl<_Tp>::type + : public __is_assignable_impl<__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; + /// @cond undocumented template<typename _Tp, typename _Up> using __is_nothrow_assignable_impl = __bool_constant<__is_nothrow_assignable(_Tp, _Up)>; + /// @endcond /// is_nothrow_assignable template<typename _Tp, typename _Up> @@ -1170,52 +1151,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "template argument must be a complete class or an unbounded array"); }; - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_nt_copy_assignable_impl; - - template<typename _Tp> - struct __is_nt_copy_assignable_impl<_Tp, false> - : public false_type { }; - - template<typename _Tp> - struct __is_nt_copy_assignable_impl<_Tp, true> - : public __is_nothrow_assignable_impl<_Tp&, const _Tp&> - { }; - /// is_nothrow_copy_assignable template<typename _Tp> struct is_nothrow_copy_assignable - : public __is_nt_copy_assignable_impl<_Tp> + : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>, + __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_nt_move_assignable_impl; - - template<typename _Tp> - struct __is_nt_move_assignable_impl<_Tp, false> - : public false_type { }; - - template<typename _Tp> - struct __is_nt_move_assignable_impl<_Tp, true> - : public __is_nothrow_assignable_impl<_Tp&, _Tp&&> - { }; - /// is_nothrow_move_assignable template<typename _Tp> struct is_nothrow_move_assignable - : public __is_nt_move_assignable_impl<_Tp> + : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>, + __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; + /// @cond undocumented + template<typename _Tp, typename... _Args> + using __is_trivially_constructible_impl + = __bool_constant<__is_trivially_constructible(_Tp, _Args...)>; + /// @endcond + /// is_trivially_constructible template<typename _Tp, typename... _Args> struct is_trivially_constructible - : public __bool_constant<__is_trivially_constructible(_Tp, _Args...)> + : public __is_trivially_constructible_impl<_Tp, _Args...> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1224,7 +1189,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_trivially_default_constructible template<typename _Tp> struct is_trivially_default_constructible - : public __bool_constant<__is_trivially_constructible(_Tp)> + : public __is_trivially_constructible_impl<_Tp> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1257,101 +1222,57 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template <typename _Tp> struct __is_implicitly_default_constructible : public __and_<__is_constructible_impl<_Tp>, - __is_implicitly_default_constructible_safe<_Tp>> - { }; - - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_trivially_copy_constructible_impl; - - template<typename _Tp> - struct __is_trivially_copy_constructible_impl<_Tp, false> - : public false_type { }; - - template<typename _Tp> - struct __is_trivially_copy_constructible_impl<_Tp, true> - : public __and_<__is_copy_constructible_impl<_Tp>, - integral_constant<bool, - __is_trivially_constructible(_Tp, const _Tp&)>> + __is_implicitly_default_constructible_safe<_Tp>>::type { }; /// is_trivially_copy_constructible template<typename _Tp> struct is_trivially_copy_constructible - : public __is_trivially_copy_constructible_impl<_Tp> + : public __is_trivially_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_trivially_move_constructible_impl; - - template<typename _Tp> - struct __is_trivially_move_constructible_impl<_Tp, false> - : public false_type { }; - - template<typename _Tp> - struct __is_trivially_move_constructible_impl<_Tp, true> - : public __and_<__is_move_constructible_impl<_Tp>, - integral_constant<bool, - __is_trivially_constructible(_Tp, _Tp&&)>> - { }; - /// is_trivially_move_constructible template<typename _Tp> struct is_trivially_move_constructible - : public __is_trivially_move_constructible_impl<_Tp> + : public __is_trivially_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; + /// @cond undocumented + template<typename _Tp, typename _Up> + using __is_trivially_assignable_impl + = __bool_constant<__is_trivially_assignable(_Tp, _Up)>; + /// @endcond + /// is_trivially_assignable template<typename _Tp, typename _Up> struct is_trivially_assignable - : public __bool_constant<__is_trivially_assignable(_Tp, _Up)> + : public __is_trivially_assignable_impl<_Tp, _Up> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_trivially_copy_assignable_impl; - - template<typename _Tp> - struct __is_trivially_copy_assignable_impl<_Tp, false> - : public false_type { }; - - template<typename _Tp> - struct __is_trivially_copy_assignable_impl<_Tp, true> - : public __bool_constant<__is_trivially_assignable(_Tp&, const _Tp&)> - { }; - /// is_trivially_copy_assignable template<typename _Tp> struct is_trivially_copy_assignable - : public __is_trivially_copy_assignable_impl<_Tp> + : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>, + __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __is_trivially_move_assignable_impl; - - template<typename _Tp> - struct __is_trivially_move_assignable_impl<_Tp, false> - : public false_type { }; - - template<typename _Tp> - struct __is_trivially_move_assignable_impl<_Tp, true> - : public __bool_constant<__is_trivially_assignable(_Tp&, _Tp&&)> - { }; - /// is_trivially_move_assignable template<typename _Tp> struct is_trivially_move_assignable - : public __is_trivially_move_assignable_impl<_Tp> + : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>, + __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1361,7 +1282,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct is_trivially_destructible : public __and_<__is_destructible_safe<_Tp>, - __bool_constant<__has_trivial_destructor(_Tp)>> + __bool_constant<__has_trivial_destructor(_Tp)>>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1403,23 +1324,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { }; /// extent - template<typename, unsigned _Uint> + template<typename, unsigned _Uint = 0> struct extent - : public integral_constant<std::size_t, 0> { }; + : public integral_constant<size_t, 0> { }; + + template<typename _Tp, size_t _Size> + struct extent<_Tp[_Size], 0> + : public integral_constant<size_t, _Size> { }; - template<typename _Tp, unsigned _Uint, std::size_t _Size> + template<typename _Tp, unsigned _Uint, size_t _Size> struct extent<_Tp[_Size], _Uint> - : public integral_constant<std::size_t, - _Uint == 0 ? _Size : extent<_Tp, - _Uint - 1>::value> - { }; + : public extent<_Tp, _Uint - 1>::type { }; + + template<typename _Tp> + struct extent<_Tp[], 0> + : public integral_constant<size_t, 0> { }; template<typename _Tp, unsigned _Uint> struct extent<_Tp[], _Uint> - : public integral_constant<std::size_t, - _Uint == 0 ? 0 : extent<_Tp, - _Uint - 1>::value> - { }; + : public extent<_Tp, _Uint - 1>::type { }; // Type relations. @@ -1633,33 +1556,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct remove_reference<_Tp&&> { typedef _Tp type; }; - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __add_lvalue_reference_helper - { typedef _Tp type; }; - - template<typename _Tp> - struct __add_lvalue_reference_helper<_Tp, true> - { typedef _Tp& type; }; - /// add_lvalue_reference template<typename _Tp> struct add_lvalue_reference - : public __add_lvalue_reference_helper<_Tp> - { }; - - template<typename _Tp, bool = __is_referenceable<_Tp>::value> - struct __add_rvalue_reference_helper - { typedef _Tp type; }; - - template<typename _Tp> - struct __add_rvalue_reference_helper<_Tp, true> - { typedef _Tp&& type; }; + { using type = __add_lval_ref_t<_Tp>; }; /// add_rvalue_reference template<typename _Tp> struct add_rvalue_reference - : public __add_rvalue_reference_helper<_Tp> - { }; + { using type = __add_rval_ref_t<_Tp>; }; #if __cplusplus > 201103L /// Alias template for remove_reference @@ -2060,14 +1965,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>> { }; - template<typename _Tp, bool = __or_<__is_referenceable<_Tp>, - is_void<_Tp>>::value> + template<typename _Tp, typename = void> struct __add_pointer_helper - { typedef _Tp type; }; + { using type = _Tp; }; template<typename _Tp> - struct __add_pointer_helper<_Tp, true> - { typedef typename remove_reference<_Tp>::type* type; }; + struct __add_pointer_helper<_Tp, __void_t<_Tp*>> + { using type = _Tp*; }; /// add_pointer template<typename _Tp> @@ -2075,6 +1979,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __add_pointer_helper<_Tp> { }; + template<typename _Tp> + struct add_pointer<_Tp&> + { using type = _Tp*; }; + + template<typename _Tp> + struct add_pointer<_Tp&&> + { using type = _Tp*; }; + #if __cplusplus > 201103L /// Alias template for remove_pointer template<typename _Tp> @@ -2167,34 +2079,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Decay trait for arrays and functions, used for perfect forwarding // in make_pair, make_tuple, etc. - template<typename _Up, - bool _IsArray = is_array<_Up>::value, - bool _IsFunction = is_function<_Up>::value> - struct __decay_selector; - - // NB: DR 705. template<typename _Up> - struct __decay_selector<_Up, false, false> - { typedef __remove_cv_t<_Up> __type; }; + struct __decay_selector + : __conditional_t<is_const<const _Up>::value, // false for functions + remove_cv<_Up>, // N.B. DR 705. + add_pointer<_Up>> // function decays to pointer + { }; - template<typename _Up> - struct __decay_selector<_Up, true, false> - { typedef typename remove_extent<_Up>::type* __type; }; + template<typename _Up, size_t _Nm> + struct __decay_selector<_Up[_Nm]> + { using type = _Up*; }; template<typename _Up> - struct __decay_selector<_Up, false, true> - { typedef typename add_pointer<_Up>::type __type; }; + struct __decay_selector<_Up[]> + { using type = _Up*; }; + /// @endcond /// decay template<typename _Tp> - class decay - { - typedef typename remove_reference<_Tp>::type __remove_type; + struct decay + { using type = typename __decay_selector<_Tp>::type; }; - public: - typedef typename __decay_selector<__remove_type>::__type type; - }; + template<typename _Tp> + struct decay<_Tp&> + { using type = typename __decay_selector<_Tp>::type; }; + + template<typename _Tp> + struct decay<_Tp&&> + { using type = typename __decay_selector<_Tp>::type; }; /// @cond undocumented @@ -2219,23 +2132,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __decay_and_strip = __strip_reference_wrapper<__decay_t<_Tp>>; /// @endcond - // Primary template. - /// Define a member typedef `type` only if a boolean constant is true. - template<bool, typename _Tp = void> - struct enable_if - { }; - - // Partial specialization for true. - template<typename _Tp> - struct enable_if<true, _Tp> - { typedef _Tp type; }; - /// @cond undocumented - // __enable_if_t (std::enable_if_t for C++11) - template<bool _Cond, typename _Tp = void> - using __enable_if_t = typename enable_if<_Cond, _Tp>::type; - // Helper for SFINAE constraints template<typename... _Cond> using _Require = __enable_if_t<__and_<_Cond...>::value>; @@ -3077,7 +2975,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __is_nt_invocable_impl<_Result, _Ret, __void_t<typename _Result::type>> : __or_<is_void<_Ret>, - __is_nothrow_convertible<typename _Result::type, _Ret>> + __is_nothrow_convertible<typename _Result::type, _Ret>>::type { }; /// @endcond @@ -3121,16 +3019,24 @@ template <typename _Tp> inline constexpr bool is_integral_v = is_integral<_Tp>::value; template <typename _Tp> inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value; + +template <typename _Tp> + inline constexpr bool is_array_v = false; template <typename _Tp> - inline constexpr bool is_array_v = is_array<_Tp>::value; + inline constexpr bool is_array_v<_Tp[]> = true; +template <typename _Tp, size_t _Num> + inline constexpr bool is_array_v<_Tp[_Num]> = true; + template <typename _Tp> inline constexpr bool is_pointer_v = is_pointer<_Tp>::value; template <typename _Tp> - inline constexpr bool is_lvalue_reference_v = - is_lvalue_reference<_Tp>::value; + inline constexpr bool is_lvalue_reference_v = false; +template <typename _Tp> + inline constexpr bool is_lvalue_reference_v<_Tp&> = true; template <typename _Tp> - inline constexpr bool is_rvalue_reference_v = - is_rvalue_reference<_Tp>::value; + inline constexpr bool is_rvalue_reference_v = false; +template <typename _Tp> + inline constexpr bool is_rvalue_reference_v<_Tp&&> = true; template <typename _Tp> inline constexpr bool is_member_object_pointer_v = is_member_object_pointer<_Tp>::value; @@ -3138,15 +3044,19 @@ template <typename _Tp> inline constexpr bool is_member_function_pointer_v = is_member_function_pointer<_Tp>::value; template <typename _Tp> - inline constexpr bool is_enum_v = is_enum<_Tp>::value; + inline constexpr bool is_enum_v = __is_enum(_Tp); template <typename _Tp> - inline constexpr bool is_union_v = is_union<_Tp>::value; + inline constexpr bool is_union_v = __is_union(_Tp); template <typename _Tp> - inline constexpr bool is_class_v = is_class<_Tp>::value; + inline constexpr bool is_class_v = __is_class(_Tp); template <typename _Tp> inline constexpr bool is_function_v = is_function<_Tp>::value; template <typename _Tp> - inline constexpr bool is_reference_v = is_reference<_Tp>::value; + inline constexpr bool is_reference_v = false; +template <typename _Tp> + inline constexpr bool is_reference_v<_Tp&> = true; +template <typename _Tp> + inline constexpr bool is_reference_v<_Tp&&> = true; template <typename _Tp> inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value; template <typename _Tp> @@ -3160,9 +3070,13 @@ template <typename _Tp> template <typename _Tp> inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value; template <typename _Tp> - inline constexpr bool is_const_v = is_const<_Tp>::value; + inline constexpr bool is_const_v = false; +template <typename _Tp> + inline constexpr bool is_const_v<const _Tp> = true; template <typename _Tp> - inline constexpr bool is_volatile_v = is_volatile<_Tp>::value; + inline constexpr bool is_volatile_v = false; +template <typename _Tp> + inline constexpr bool is_volatile_v<volatile _Tp> = true; template <typename _Tp> inline constexpr bool is_trivial_v = is_trivial<_Tp>::value; template <typename _Tp> @@ -3179,83 +3093,93 @@ template <typename _Tp> _GLIBCXX17_DEPRECATED inline constexpr bool is_literal_type_v = is_literal_type<_Tp>::value; #pragma GCC diagnostic pop - template <typename _Tp> - inline constexpr bool is_empty_v = is_empty<_Tp>::value; template <typename _Tp> - inline constexpr bool is_polymorphic_v = is_polymorphic<_Tp>::value; + inline constexpr bool is_empty_v = __is_empty(_Tp); +template <typename _Tp> + inline constexpr bool is_polymorphic_v = __is_polymorphic(_Tp); template <typename _Tp> - inline constexpr bool is_abstract_v = is_abstract<_Tp>::value; + inline constexpr bool is_abstract_v = __is_abstract(_Tp); template <typename _Tp> - inline constexpr bool is_final_v = is_final<_Tp>::value; + inline constexpr bool is_final_v = __is_final(_Tp); template <typename _Tp> inline constexpr bool is_signed_v = is_signed<_Tp>::value; template <typename _Tp> inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value; + template <typename _Tp, typename... _Args> - inline constexpr bool is_constructible_v = - is_constructible<_Tp, _Args...>::value; + inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...); template <typename _Tp> - inline constexpr bool is_default_constructible_v = - is_default_constructible<_Tp>::value; + inline constexpr bool is_default_constructible_v = __is_constructible(_Tp); template <typename _Tp> - inline constexpr bool is_copy_constructible_v = - is_copy_constructible<_Tp>::value; + inline constexpr bool is_copy_constructible_v + = __is_constructible(_Tp, __add_lval_ref_t<const _Tp>); template <typename _Tp> - inline constexpr bool is_move_constructible_v = - is_move_constructible<_Tp>::value; + inline constexpr bool is_move_constructible_v + = __is_constructible(_Tp, __add_rval_ref_t<_Tp>); + template <typename _Tp, typename _Up> - inline constexpr bool is_assignable_v = is_assignable<_Tp, _Up>::value; + inline constexpr bool is_assignable_v = __is_assignable(_Tp, _Up); template <typename _Tp> - inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value; + inline constexpr bool is_copy_assignable_v + = __is_assignable(__add_lval_ref_t<_Tp>, __add_lval_ref_t<const _Tp>); template <typename _Tp> - inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value; + inline constexpr bool is_move_assignable_v + = __is_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); + template <typename _Tp> inline constexpr bool is_destructible_v = is_destructible<_Tp>::value; + template <typename _Tp, typename... _Args> - inline constexpr bool is_trivially_constructible_v = - is_trivially_constructible<_Tp, _Args...>::value; + inline constexpr bool is_trivially_constructible_v + = __is_trivially_constructible(_Tp, _Args...); template <typename _Tp> - inline constexpr bool is_trivially_default_constructible_v = - is_trivially_default_constructible<_Tp>::value; + inline constexpr bool is_trivially_default_constructible_v + = __is_trivially_constructible(_Tp); template <typename _Tp> - inline constexpr bool is_trivially_copy_constructible_v = - is_trivially_copy_constructible<_Tp>::value; + inline constexpr bool is_trivially_copy_constructible_v + = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>); template <typename _Tp> - inline constexpr bool is_trivially_move_constructible_v = - is_trivially_move_constructible<_Tp>::value; + inline constexpr bool is_trivially_move_constructible_v + = __is_trivially_constructible(_Tp, __add_rval_ref_t<_Tp>); + template <typename _Tp, typename _Up> - inline constexpr bool is_trivially_assignable_v = - is_trivially_assignable<_Tp, _Up>::value; + inline constexpr bool is_trivially_assignable_v + = __is_trivially_assignable(_Tp, _Up); template <typename _Tp> - inline constexpr bool is_trivially_copy_assignable_v = - is_trivially_copy_assignable<_Tp>::value; + inline constexpr bool is_trivially_copy_assignable_v + = __is_trivially_assignable(__add_lval_ref_t<_Tp>, + __add_lval_ref_t<const _Tp>); template <typename _Tp> - inline constexpr bool is_trivially_move_assignable_v = - is_trivially_move_assignable<_Tp>::value; + inline constexpr bool is_trivially_move_assignable_v + = __is_trivially_assignable(__add_lval_ref_t<_Tp>, + __add_rval_ref_t<_Tp>); template <typename _Tp> inline constexpr bool is_trivially_destructible_v = is_trivially_destructible<_Tp>::value; template <typename _Tp, typename... _Args> - inline constexpr bool is_nothrow_constructible_v = - is_nothrow_constructible<_Tp, _Args...>::value; + inline constexpr bool is_nothrow_constructible_v + = __is_nothrow_constructible(_Tp, _Args...); template <typename _Tp> - inline constexpr bool is_nothrow_default_constructible_v = - is_nothrow_default_constructible<_Tp>::value; + inline constexpr bool is_nothrow_default_constructible_v + = __is_nothrow_constructible(_Tp); template <typename _Tp> - inline constexpr bool is_nothrow_copy_constructible_v = - is_nothrow_copy_constructible<_Tp>::value; + inline constexpr bool is_nothrow_copy_constructible_v + = __is_nothrow_constructible(_Tp, __add_lval_ref_t<const _Tp>); template <typename _Tp> - inline constexpr bool is_nothrow_move_constructible_v = - is_nothrow_move_constructible<_Tp>::value; + inline constexpr bool is_nothrow_move_constructible_v + = __is_nothrow_constructible(_Tp, __add_rval_ref_t<_Tp>); + template <typename _Tp, typename _Up> - inline constexpr bool is_nothrow_assignable_v = - is_nothrow_assignable<_Tp, _Up>::value; + inline constexpr bool is_nothrow_assignable_v + = __is_nothrow_assignable(_Tp, _Up); template <typename _Tp> - inline constexpr bool is_nothrow_copy_assignable_v = - is_nothrow_copy_assignable<_Tp>::value; + inline constexpr bool is_nothrow_copy_assignable_v + = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, + __add_lval_ref_t<const _Tp>); template <typename _Tp> - inline constexpr bool is_nothrow_move_assignable_v = - is_nothrow_move_assignable<_Tp>::value; + inline constexpr bool is_nothrow_move_assignable_v + = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); + template <typename _Tp> inline constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<_Tp>::value; @@ -3264,10 +3188,25 @@ template <typename _Tp> has_virtual_destructor<_Tp>::value; template <typename _Tp> inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value; + template <typename _Tp> - inline constexpr size_t rank_v = rank<_Tp>::value; + inline constexpr size_t rank_v = 0; +template <typename _Tp, size_t _Size> + inline constexpr size_t rank_v<_Tp[_Size]> = 1 + rank_v<_Tp>; +template <typename _Tp> + inline constexpr size_t rank_v<_Tp[]> = 1 + rank_v<_Tp>; + template <typename _Tp, unsigned _Idx = 0> - inline constexpr size_t extent_v = extent<_Tp, _Idx>::value; + inline constexpr size_t extent_v = 0; +template <typename _Tp, size_t _Size> + inline constexpr size_t extent_v<_Tp[_Size], 0> = _Size; +template <typename _Tp, unsigned _Idx, size_t _Size> + inline constexpr size_t extent_v<_Tp[_Size], _Idx> = extent_v<_Tp, _Idx - 1>; +template <typename _Tp> + inline constexpr size_t extent_v<_Tp[], 0> = 0; +template <typename _Tp, unsigned _Idx> + inline constexpr size_t extent_v<_Tp[], _Idx> = extent_v<_Tp, _Idx - 1>; + #ifdef _GLIBCXX_HAVE_BUILTIN_IS_SAME template <typename _Tp, typename _Up> inline constexpr bool is_same_v = __is_same(_Tp, _Up); @@ -3276,7 +3215,7 @@ template <typename _Tp, typename _Up> inline constexpr bool is_same_v = std::is_same<_Tp, _Up>::value; #endif template <typename _Base, typename _Derived> - inline constexpr bool is_base_of_v = is_base_of<_Base, _Derived>::value; + inline constexpr bool is_base_of_v = __is_base_of(_Base, _Derived); template <typename _From, typename _To> inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value; template<typename _Fn, typename... _Args> @@ -3314,16 +3253,19 @@ template<typename _Ret, typename _Fn, typename... _Args> #ifdef _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE # define __cpp_lib_is_aggregate 201703L - /// is_aggregate + /// is_aggregate - true if the type is an aggregate. /// @since C++17 template<typename _Tp> struct is_aggregate : bool_constant<__is_aggregate(remove_cv_t<_Tp>)> { }; - /// @ingroup variable_templates + /** is_aggregate_v - true if the type is an aggregate. + * @ingroup variable_templates + * @since C++17 + */ template<typename _Tp> - inline constexpr bool is_aggregate_v = is_aggregate<_Tp>::value; + inline constexpr bool is_aggregate_v = __is_aggregate(remove_cv_t<_Tp>); #endif #endif // C++17 @@ -3396,30 +3338,36 @@ template<typename _Ret, typename _Fn, typename... _Args> #define __cpp_lib_bounded_array_traits 201902L /// True for a type that is an array of known bound. + /// @ingroup variable_templates /// @since C++20 template<typename _Tp> - struct is_bounded_array - : public __is_array_known_bounds<_Tp> - { }; + inline constexpr bool is_bounded_array_v = false; + + template<typename _Tp, size_t _Size> + inline constexpr bool is_bounded_array_v<_Tp[_Size]> = true; /// True for a type that is an array of unknown bound. + /// @ingroup variable_templates /// @since C++20 template<typename _Tp> - struct is_unbounded_array - : public __is_array_unknown_bounds<_Tp> - { }; + inline constexpr bool is_unbounded_array_v = false; - /// @ingroup variable_templates + template<typename _Tp> + inline constexpr bool is_unbounded_array_v<_Tp[]> = true; + + /// True for a type that is an array of known bound. /// @since C++20 template<typename _Tp> - inline constexpr bool is_bounded_array_v - = is_bounded_array<_Tp>::value; + struct is_bounded_array + : public bool_constant<is_bounded_array_v<_Tp>> + { }; - /// @ingroup variable_templates + /// True for a type that is an array of unknown bound. /// @since C++20 template<typename _Tp> - inline constexpr bool is_unbounded_array_v - = is_unbounded_array<_Tp>::value; + struct is_unbounded_array + : public bool_constant<is_unbounded_array_v<_Tp>> + { }; #if __has_builtin(__is_layout_compatible) @@ -3486,20 +3434,11 @@ template<typename _Ret, typename _Fn, typename... _Args> template<typename _Tp> requires __is_enum(_Tp) - && requires(_Tp __t) { __t = __t; } // fails if incomplete + && requires(remove_cv_t<_Tp> __t) { __t = __t; } // fails if incomplete struct is_scoped_enum<_Tp> : bool_constant<!requires(_Tp __t, void(*__f)(int)) { __f(__t); }> { }; - // FIXME remove this partial specialization and use remove_cv_t<_Tp> above - // when PR c++/99968 is fixed. - template<typename _Tp> - requires __is_enum(_Tp) - && requires(_Tp __t) { __t = __t; } // fails if incomplete - struct is_scoped_enum<const _Tp> - : bool_constant<!requires(_Tp __t, void(*__f)(int)) { __f(__t); }> - { }; - /// @ingroup variable_templates /// @since C++23 template<typename _Tp> diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc index 8ed61a6..abc4124 100644 --- a/libstdc++-v3/src/c++11/debug.cc +++ b/libstdc++-v3/src/c++11/debug.cc @@ -611,10 +611,12 @@ namespace void print_raw(PrintContext& ctx, const char* str, ptrdiff_t nbc = -1) { - if (nbc >= 0) - ctx._M_column += fprintf(stderr, "%.*s", (int)nbc, str); - else - ctx._M_column += fprintf(stderr, "%s", str); + if (nbc != 0) + { + ctx._M_column += (nbc > 0) + ? fprintf(stderr, "%.*s", (int)nbc, str) + : fprintf(stderr, "%s", str); + } } void @@ -680,7 +682,7 @@ namespace pos += 2; // advance past "__" if (memcmp(pos, cxx1998, 9) == 0) - pos += 9; // advance part "cxx1998::" + pos += 9; // advance past "cxx1998::" str = pos; } @@ -1093,6 +1095,58 @@ namespace void print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc) { print_string(ctx, str, nbc, nullptr, 0); } + +#if _GLIBCXX_HAVE_STACKTRACE + int + print_backtrace(void* data, __UINTPTR_TYPE__ pc, const char* filename, + int lineno, const char* function) + { + const int bufsize = 64; + char buf[bufsize]; + + PrintContext& ctx = *static_cast<PrintContext*>(data); + + int written = __builtin_sprintf(buf, "%p ", (void*)pc); + print_word(ctx, buf, written); + + int ret = 0; + if (function) + { + int status; + char* demangled_name = + __cxxabiv1::__cxa_demangle(function, NULL, NULL, &status); + if (status == 0) + pretty_print(ctx, demangled_name, &print_raw); + else + print_word(ctx, function); + + free(demangled_name); + ret = strstr(function, "main") ? 1 : 0; + } + + print_literal(ctx, "\n"); + + if (filename) + { + bool wordwrap = false; + swap(wordwrap, ctx._M_wordwrap); + print_word(ctx, filename); + + if (lineno) + { + written = __builtin_sprintf(buf, ":%u\n", lineno); + print_word(ctx, buf, written); + } + else + print_literal(ctx, "\n"); + swap(wordwrap, ctx._M_wordwrap); + } + else + print_literal(ctx, "???:0\n"); + + return ret; + } +#endif } namespace __gnu_debug @@ -1139,6 +1193,17 @@ namespace __gnu_debug print_literal(ctx, "\n"); } +#if _GLIBCXX_HAVE_STACKTRACE + if (_M_backtrace_state) + { + print_literal(ctx, "Backtrace:\n"); + _M_backtrace_full( + _M_backtrace_state, 1, print_backtrace, nullptr, &ctx); + ctx._M_first_line = true; + print_literal(ctx, "\n"); + } +#endif + print_literal(ctx, "Error: "); // Print the error message diff --git a/libstdc++-v3/src/libbacktrace/Makefile.am b/libstdc++-v3/src/libbacktrace/Makefile.am index 0f11435..52d8f81 100644 --- a/libstdc++-v3/src/libbacktrace/Makefile.am +++ b/libstdc++-v3/src/libbacktrace/Makefile.am @@ -60,6 +60,7 @@ libstdc___libbacktrace_la_SHORTNAME = $(obj_prefix) libstdc___libbacktrace_la_SOURCES = \ atomic.c \ + backtrace.c \ dwarf.c \ fileline.c \ posix.c \ diff --git a/libstdc++-v3/src/libbacktrace/Makefile.in b/libstdc++-v3/src/libbacktrace/Makefile.in index 7545894..5c6b4dd 100644 --- a/libstdc++-v3/src/libbacktrace/Makefile.in +++ b/libstdc++-v3/src/libbacktrace/Makefile.in @@ -181,10 +181,10 @@ am__uninstall_files_from_dir = { \ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" LTLIBRARIES = $(toolexeclib_LTLIBRARIES) am_libstdc___libbacktrace_la_OBJECTS = $(obj_prefix)-atomic.lo \ - $(obj_prefix)-dwarf.lo $(obj_prefix)-fileline.lo \ - $(obj_prefix)-posix.lo $(obj_prefix)-sort.lo \ - $(obj_prefix)-simple.lo $(obj_prefix)-state.lo \ - $(obj_prefix)-cp-demangle.lo + $(obj_prefix)-backtrace.lo $(obj_prefix)-dwarf.lo \ + $(obj_prefix)-fileline.lo $(obj_prefix)-posix.lo \ + $(obj_prefix)-sort.lo $(obj_prefix)-simple.lo \ + $(obj_prefix)-state.lo $(obj_prefix)-cp-demangle.lo libstdc___libbacktrace_la_OBJECTS = \ $(am_libstdc___libbacktrace_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -507,6 +507,7 @@ obj_prefix = std_stacktrace libstdc___libbacktrace_la_SHORTNAME = $(obj_prefix) libstdc___libbacktrace_la_SOURCES = \ atomic.c \ + backtrace.c \ dwarf.c \ fileline.c \ posix.c \ @@ -647,6 +648,9 @@ distclean-compile: $(obj_prefix)-atomic.lo: atomic.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstdc___libbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(obj_prefix)-atomic.lo `test -f 'atomic.c' || echo '$(srcdir)/'`atomic.c +$(obj_prefix)-backtrace.lo: backtrace.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstdc___libbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(obj_prefix)-backtrace.lo `test -f 'backtrace.c' || echo '$(srcdir)/'`backtrace.c + $(obj_prefix)-dwarf.lo: dwarf.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstdc___libbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(obj_prefix)-dwarf.lo `test -f 'dwarf.c' || echo '$(srcdir)/'`dwarf.c diff --git a/libstdc++-v3/src/libbacktrace/backtrace-rename.h b/libstdc++-v3/src/libbacktrace/backtrace-rename.h index 7a59f16..79bdef6 100644 --- a/libstdc++-v3/src/libbacktrace/backtrace-rename.h +++ b/libstdc++-v3/src/libbacktrace/backtrace-rename.h @@ -4,6 +4,7 @@ #define backtrace_create_state __glibcxx_backtrace_create_state #define backtrace_dwarf_add __glibcxx_backtrace_dwarf_add #define backtrace_free __glibcxx_backtrace_free +#define backtrace_full __glibcxx_backtrace_full #define backtrace_get_view __glibcxx_backtrace_get_view #define backtrace_initialize __glibcxx_backtrace_initialize #define backtrace_open __glibcxx_backtrace_open diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_code/cons/1.cc b/libstdc++-v3/testsuite/19_diagnostics/error_code/cons/1.cc index f454fc2..d48d5c1 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/error_code/cons/1.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/error_code/cons/1.cc @@ -22,23 +22,46 @@ #include <system_error> #include <testsuite_error.h> +namespace adl +{ + struct Error { }; + + const Error err; + + struct category : std::error_category + { + const char* name() const noexcept override { return "adl"; } + std::string message(int) const { return ""; } + }; + + const category cat; + + std::error_code + make_error_code(Error) { return std::error_code(999, cat); } +} + +template<> struct std::is_error_code_enum<adl::Error> : std::true_type { }; + int main() { - // 1 + // 1 error_code() std::error_code e1; VERIFY( e1.value() == 0 ); VERIFY( e1.category() == std::system_category() ); - // 2 + // 2 error_code(int, const error_category&) const __gnu_test::test_category cat; std::error_code e2(e1.value(), cat); VERIFY( e2.value() == e1.value() ); VERIFY( e2.category() == cat ); - // 3 + // 3 error_code(const error_code&) std::error_code e3(std::make_error_code(std::errc::operation_not_supported)); VERIFY( e3.value() == int(std::errc::operation_not_supported) ); VERIFY( e3.category() == std::generic_category() ); - return 0; + // 4 error_code(ErrorCodeEnum) + std::error_code e4(adl::err); + VERIFY( e4.value() == 999 ); + VERIFY( e4.category() == adl::cat ); } diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_condition/cons/1.cc b/libstdc++-v3/testsuite/19_diagnostics/error_condition/cons/1.cc index 1e039c4..c353b02 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/error_condition/cons/1.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/error_condition/cons/1.cc @@ -21,23 +21,48 @@ #include <system_error> #include <testsuite_error.h> +namespace adl +{ + struct Error { }; + + const Error err; + + struct category : std::error_category + { + const char* name() const noexcept override { return "adl"; } + std::string message(int) const { return ""; } + }; + + const category cat; + + std::error_condition + make_error_condition(Error) { return std::error_condition(999, cat); } +} + +template<> struct std::is_error_condition_enum<adl::Error> : std::true_type { }; + void test01() { - // 1 + // 1 error_condition() std::error_condition e1; VERIFY( e1.value() == 0 ); VERIFY( e1.category() == std::generic_category() ); - // 2 + // 2 error_condition(int, const error_category&) const __gnu_test::test_category cat; std::error_condition e2(e1.value(), cat); VERIFY( e2.value() == e1.value() ); VERIFY( e2.category() == cat ); - // 3 + // 3 error_condition(const error_condition&) std::error_condition e3(std::errc::operation_not_supported); VERIFY( e3.value() == int(std::errc::operation_not_supported) ); VERIFY( e3.category() == std::generic_category() ); + + // 4 error_condition(ErrorConditionEnum) + std::error_condition e4(adl::err); + VERIFY( e4.value() == 999 ); + VERIFY( e4.category() == adl::cat ); } int main() diff --git a/libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc b/libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc index af6e72d..c5179b6 100644 --- a/libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc +++ b/libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc @@ -58,3 +58,8 @@ static_assert( std::chrono::round<seconds>(2501ms) == 3s ); static_assert( std::chrono::abs(100ms) == 100ms ); static_assert( std::chrono::abs(-100ms) == 100ms ); + +// LWG 3741. std::chrono::abs(duration) is ill-formed with non-reduced periods +using D1000 = std::chrono::duration<int, std::ratio<1000, 1000>>; +static_assert( std::chrono::abs(D1000(-2)) == D1000(2) ); +static_assert( std::is_same_v<decltype(std::chrono::abs(D1000(-2))), D1000> ); diff --git a/libstdc++-v3/testsuite/20_util/logical_traits/requirements/base_classes.cc b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/base_classes.cc new file mode 100644 index 0000000..9067a3b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/base_classes.cc @@ -0,0 +1,34 @@ +// { dg-do compile { target c++17 } } + +#include <type_traits> + +template<int> struct T : std::true_type { }; +template<int> struct F : std::false_type { }; + +// [meta.logical]/5: The specialization conjunction<B_1, ..., B_n> has a +// public and unambiguous base that is either: +// - the first type B_i in the list true_type, B_1, ..., B_n for which +// bool(B_i::value) is false, or +// - if there is no such B_i, the last type in the list. + +static_assert(std::is_base_of_v<std::true_type, std::conjunction<>>); +static_assert(std::is_base_of_v<T<0>, std::conjunction<T<0>>>); +static_assert(std::is_base_of_v<F<0>, std::conjunction<F<0>>>); +static_assert(std::is_base_of_v<T<1>, std::conjunction<T<0>, T<1>>>); +static_assert(std::is_base_of_v<F<0>, std::conjunction<F<0>, F<1>>>); +static_assert(std::is_base_of_v<F<0>, std::conjunction<T<0>, F<0>, F<1>>>); +static_assert(std::is_base_of_v<F<0>, std::conjunction<T<0>, F<0>, T<1>, F<1>>>); + +// [meta.logical]/10: The specialization disjunction<B_1, ..., B_n> has a +// public and unambiguous base that is either: +// - the first type B_i in the list false_type, B_1, ..., B_n for which +// bool(B_i::value) is true, or +// - if there is no such B_i, the last type in the list. + +static_assert(std::is_base_of_v<std::false_type, std::disjunction<>>); +static_assert(std::is_base_of_v<T<0>, std::disjunction<T<0>>>); +static_assert(std::is_base_of_v<F<0>, std::disjunction<F<0>>>); +static_assert(std::is_base_of_v<T<0>, std::disjunction<T<0>, T<1>>>); +static_assert(std::is_base_of_v<F<1>, std::disjunction<F<0>, F<1>>>); +static_assert(std::is_base_of_v<T<0>, std::disjunction<T<0>, F<0>, F<1>>>); +static_assert(std::is_base_of_v<T<0>, std::disjunction<T<0>, F<0>, T<1>, F<1>>>); diff --git a/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc new file mode 100644 index 0000000..ff90f8a --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc @@ -0,0 +1,55 @@ +// { dg-do compile { target c++17 } } + +#include <type_traits> + +template<class T> struct A { using type = typename T::type; }; +using invalid = A<void>; + +// [meta.logical]/3: For a specialization conjunction<B_1, ..., B_n>, if +// there is a template type argument B_i for which bool(B_i::value) is false, +// then instantiating conjunction<B_1, ..., B_n>::value does not require the +// instantiation of B_j::value for j > i. + +static_assert(!std::conjunction_v<std::false_type, invalid>); +static_assert(!std::conjunction_v<std::false_type, invalid, invalid>); +static_assert(!std::conjunction_v<std::true_type, std::false_type, invalid>); +static_assert(!std::conjunction_v<std::true_type, std::false_type, invalid, invalid>); +static_assert(!std::conjunction_v<std::false_type, + std::conjunction<invalid>, + std::disjunction<invalid>, + std::negation<invalid>>); + +// [meta.logical]/8: For a specialization disjunction<B_1, ..., B_n>, if +// there is a template type argument B_i for which bool(B_i::value) is true, +// then instantiating disjunction<B_1, ..., B_n>::value does not require the +// instantiation of B_j::value for j > i. + +static_assert(std::disjunction_v<std::true_type, invalid>); +static_assert(std::disjunction_v<std::true_type, invalid, invalid>); +static_assert(std::disjunction_v<std::false_type, std::true_type, invalid>); +static_assert(std::disjunction_v<std::false_type, std::true_type, invalid, invalid>); +static_assert(std::disjunction_v<std::true_type, + std::conjunction<invalid>, + std::disjunction<invalid>, + std::negation<invalid>>); + +#if __GLIBCXX__ +// Also test the corresponding internal traits __and_, __or_ and __not_. +static_assert(!std::__and_v<std::false_type, invalid>); +static_assert(!std::__and_v<std::false_type, invalid, invalid>); +static_assert(!std::__and_v<std::true_type, std::false_type, invalid>); +static_assert(!std::__and_v<std::true_type, std::false_type, invalid, invalid>); +static_assert(!std::__and_v<std::false_type, + std::__and_<invalid>, + std::__or_<invalid>, + std::__not_<invalid>>); + +static_assert(std::__or_v<std::true_type, invalid>); +static_assert(std::__or_v<std::true_type, invalid, invalid>); +static_assert(std::__or_v<std::false_type, std::true_type, invalid>); +static_assert(std::__or_v<std::false_type, std::true_type, invalid, invalid>); +static_assert(std::__or_v<std::true_type, + std::__and_<invalid>, + std::__or_<invalid>, + std::__not_<invalid>>); +#endif diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc index 2741510..fd3430c 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc @@ -16,7 +16,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// 20.6.4 function object return types [func.ret] +// C++11 20.8.3.4 reference_wrapper invocation [refwrap.invoke] #include <functional> struct X @@ -27,6 +27,7 @@ struct X void test01() { + // PR libstdc++/48521 std::result_of doesn't work with pointer to member typedef int (X::*mfp)(int); typedef int X::*mp; mfp m = &X::f; diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-3.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-3.cc index e4124c9..c25315b 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-3.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-3.cc @@ -17,7 +17,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// 20.8.3.4 reference_wrapper invocation [refwrap.invoke] +// C++11 20.8.3.4 reference_wrapper invocation [refwrap.invoke] #include <functional> struct ABC @@ -33,4 +33,5 @@ struct Concrete : ABC Concrete c; ABC& abc = c; +// PR libstdc++/57336 Cannot INVOKE a reference_wrapper around an abstract type auto b = std::cref(abc)(); diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-noexcept.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-noexcept.cc new file mode 100644 index 0000000..91b5d09 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-noexcept.cc @@ -0,0 +1,15 @@ +// { dg-do compile { target c++11 } } + +// C++11 20.8.3.4 reference_wrapper invocation [refwrap.invoke] + +#include <functional> + +struct F +{ + int operator()() noexcept(true) { return 1; } + int operator()() const noexcept(false) { return 2; } +}; + +F f; +static_assert( noexcept(std::ref(f)()) ); +static_assert( ! noexcept(std::cref(f)()) ); diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc index cd884fe..b2abc81 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc @@ -17,6 +17,8 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +// C++11 20.8.3.4 reference_wrapper invocation [refwrap.invoke] + #include <functional> #include <type_traits> #include <testsuite_hooks.h> diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc index 6044a37..a326d1b 100644 --- a/libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc +++ b/libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc @@ -503,7 +503,17 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(!std::is_nothrow_constructible<BT, IT&>::value, ""); static_assert(!std::is_nothrow_constructible<BT, const IT &>::value, ""); static_assert(!std::is_nothrow_constructible<BT, std::tuple<int&>>::value, ""); +#if __cplusplus > 202002L + // C++23 extended tuple's constructor overload set as part of P2321R2, after + // which its converting constructors more accurately forward the elements + // from a non-const tuple lvalue and from a const tuple rvalue. In particular + // for the below test we now forward int&& as an rvalue reference instead of + // as an lvalue reference, which means we now select the noexcept B(int&&) + // ctor instead of the non-noexcept B(const int&) ctor. + static_assert(std::is_nothrow_constructible<BT, const std::tuple<int&&>>::value, ""); +#else static_assert(!std::is_nothrow_constructible<BT, const std::tuple<int&&>>::value, ""); +#endif static_assert(test_trait::is_nothrow_convertible<int,BT>::value,""); static_assert(!test_trait::is_nothrow_convertible<const int,BT>::value,""); @@ -515,7 +525,13 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(!test_trait::is_nothrow_convertible<IT&,BT>::value,""); static_assert(!test_trait::is_nothrow_convertible<const IT &,BT>::value,""); static_assert(!test_trait::is_nothrow_convertible<std::tuple<int&>,BT>::value,""); +#if __cplusplus > 202002L + // See the note about P2321R2 above. + static_assert(test_trait::is_nothrow_convertible<const std::tuple<int&&>,BT>::value,""); +#else static_assert(!test_trait::is_nothrow_convertible<const std::tuple<int&&>,BT>::value,""); +#endif + static_assert(!std::is_nothrow_constructible<BT, B>::value, ""); @@ -528,7 +544,12 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(std::is_nothrow_constructible<BT, BT&>::value, ""); static_assert(std::is_nothrow_constructible<BT, const BT &>::value, ""); static_assert(std::is_nothrow_constructible<BT, std::tuple<B&>>::value, ""); +#if __cplusplus > 202002L + // See the note about P2321R2 above. + static_assert(!std::is_nothrow_constructible<BT, const std::tuple<B&&>>::value, ""); +#else static_assert(std::is_nothrow_constructible<BT, const std::tuple<B&&>>::value, ""); +#endif static_assert(!test_trait::is_nothrow_convertible<B,BT>::value,""); static_assert(test_trait::is_nothrow_convertible<const B,BT>::value,""); @@ -540,7 +561,12 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(test_trait::is_nothrow_convertible<BT&,BT>::value,""); static_assert(test_trait::is_nothrow_convertible<const BT &,BT>::value,""); static_assert(test_trait::is_nothrow_convertible<std::tuple<B&>,BT>::value,""); +#if __cplusplus > 202002L + // See the note about P2321R2 above. + static_assert(!test_trait::is_nothrow_convertible<const std::tuple<B&&>,BT>::value,""); +#else static_assert(test_trait::is_nothrow_convertible<const std::tuple<B&&>,BT>::value,""); +#endif /* explicit */ static_assert(std::is_nothrow_constructible<DT, int>::value, ""); @@ -553,7 +579,12 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(!std::is_nothrow_constructible<DT, IT&>::value, ""); static_assert(!std::is_nothrow_constructible<DT, const IT &>::value, ""); static_assert(!std::is_nothrow_constructible<DT, std::tuple<int&>>::value, ""); +#if __cplusplus > 202002L + // See the note about P2321R2 above. + static_assert(std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, ""); +#else static_assert(!std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, ""); +#endif static_assert(!std::is_nothrow_constructible<DT, D>::value, ""); static_assert(std::is_nothrow_constructible<DT,const D>::value, ""); @@ -565,7 +596,12 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(std::is_nothrow_constructible<DT, DT&>::value, ""); static_assert(std::is_nothrow_constructible<DT, const DT &>::value, ""); static_assert(std::is_nothrow_constructible<DT, std::tuple<D&>>::value, ""); +#if __cplusplus > 202002L + // See note about P2321R2 above. + static_assert(!std::is_nothrow_constructible<DT, const std::tuple<D&&>>::value, ""); +#else static_assert(std::is_nothrow_constructible<DT, const std::tuple<D&&>>::value, ""); +#endif static_assert(!test_trait::is_nothrow_convertible<DT,DT>::value,""); static_assert(test_trait::is_nothrow_convertible<const DT,DT>::value,""); @@ -884,7 +920,12 @@ namespace ThrowMoveNothrowConversion static_assert(std::is_nothrow_constructible<DT, IT&>::value, ""); static_assert(std::is_nothrow_constructible<DT, const IT &>::value, ""); static_assert(std::is_nothrow_constructible<DT, std::tuple<int&>>::value, ""); +#if __cplusplus > 202002L + // See the note about P2321R2 above. + static_assert(!std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, ""); +#else static_assert(std::is_nothrow_constructible<DT, const std::tuple<int&&>>::value, ""); +#endif static_assert(test_trait::is_nothrow_convertible<DT,DT>::value,""); static_assert(test_trait::is_nothrow_convertible<D,DT>::value,""); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc index 45af457..1ae4d3d 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc @@ -175,7 +175,7 @@ void test01() sz03 = str02.size(); sz04 = str02.length(); VERIFY( sz03 == sz04 ); - str02.c_str(); + (void) str02.c_str(); sz03 = str02.size(); sz04 = str02.length(); VERIFY( sz03 == sz04 ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc index 244a795..1da273b 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc @@ -74,15 +74,15 @@ void test01() sz01 = str01.size(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); - str01.c_str(); + (void) str01.c_str(); sz01 = str01.size(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); sz01 = str01.length(); - str01.c_str(); + (void) str01.c_str(); str011 = str01 + "_addendum_"; - str01.c_str(); + (void) str01.c_str(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); sz02 = str011.length(); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc index 5cb682e..6f03e34 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc @@ -71,15 +71,15 @@ void test01() sz01 = str01.size(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); - str01.c_str(); + (void) str01.c_str(); sz01 = str01.size(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); sz01 = str01.length(); - str01.c_str(); + (void) str01.c_str(); str011 = str01 + L"_addendum_"; - str01.c_str(); + (void) str01.c_str(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); sz02 = str011.length(); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/self_move.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/self_move.cc index d37fe39..ddd9aea 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/self_move.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/self_move.cc @@ -32,7 +32,7 @@ test(const char* s) String s3 __attribute__((unused)) = s1; s1 = std::move(s1); - s1.begin(); // causes COW string to "leak" + (void) s1.begin(); // causes COW string to "leak" s1 = std::move(s1); String s4 __attribute__((unused)) = s1; diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/1.cc index 7fb4323..5a176c0 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/1.cc @@ -53,7 +53,7 @@ void test01(void) cref cref3 = str01.at(csz01 - 1); VERIFY( cref3 == 'a' ); try { - str01.at(csz01); + (void) str01.at(csz01); VERIFY( false ); // Should not get here, as exception thrown. } catch(std::out_of_range& fail) { @@ -68,7 +68,7 @@ void test01(void) ref ref3 = str02.at(csz02 - 1); VERIFY( ref3 == 'a' ); try { - str02.at(csz02); + (void) str02.at(csz02); VERIFY( false ); // Should not get here, as exception thrown. } catch(std::out_of_range& fail) { diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/21674.cc b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/21674.cc index a5a129b..3ff8d51 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/21674.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/21674.cc @@ -27,5 +27,5 @@ int main() { typedef std::string string_type; string_type s; - s[1]; // abort + (void) s[1]; // abort } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/1.cc index 9bb5dcb..f9a07ab 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/1.cc @@ -53,7 +53,7 @@ void test01(void) cref cref3 = str01.at(csz01 - 1); VERIFY( cref3 == L'a' ); try { - str01.at(csz01); + (void) str01.at(csz01); VERIFY( false ); // Should not get here, as exception thrown. } catch(std::out_of_range& fail) { @@ -68,7 +68,7 @@ void test01(void) ref ref3 = str02.at(csz02 - 1); VERIFY( ref3 == L'a' ); try { - str02.at(csz02); + (void) str02.at(csz02); VERIFY( false ); // Should not get here, as exception thrown. } catch(std::out_of_range& fail) { diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc index 974e6b2..fc023a8 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc @@ -27,5 +27,5 @@ int main() { typedef std::wstring string_type; string_type s; - s[1]; // abort + (void) s[1]; // abort } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc index 45d514b..a9dcd9a 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc @@ -40,6 +40,6 @@ int main() x.replace(0, 3, "foo", 0, 3); x.replace(0, 3, cs, 0, 3); x = "bar"; - x.compare(0, 3, "foo", 0, 3); - x.compare(0, 3, cs, 0, 3); + (void) x.compare(0, 3, "foo", 0, 3); + (void) x.compare(0, 3, cs, 0, 3); } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc index 3cbaf17..6e308ba 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc @@ -29,12 +29,12 @@ int main() s.insert(0, {"abc", 1}); s.replace(0, 1, {"abc", 1}); s.replace(s.begin(), s.begin(), {"abc", 1}); - s.find({"abc", 1}); - s.rfind({"abc", 1}); - s.find_first_of({"abc", 1}); - s.find_last_of({"abc", 1}); - s.find_first_not_of({"abc", 1}); - s.find_last_not_of({"abc", 1}); - s.compare({"abc", 1}); - s.compare(0, 1, {"abc", 1}); + (void) s.find({"abc", 1}); + (void) s.rfind({"abc", 1}); + (void) s.find_first_of({"abc", 1}); + (void) s.find_last_of({"abc", 1}); + (void) s.find_first_not_of({"abc", 1}); + (void) s.find_last_not_of({"abc", 1}); + (void) s.compare({"abc", 1}); + (void) s.compare(0, 1, {"abc", 1}); } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc new file mode 100644 index 0000000..41bb391 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++23 -Wnonnull -O0 -Wno-unused-result" } +// { dg-do compile { target c++23 } } + +#include <string> + +void +test01(const std::string& s) +{ + s.contains((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.contains((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.contains(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char.cc index cfe18e0..3cf8512 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char.cc @@ -20,7 +20,7 @@ // basic_string ends_with -#include <string> +#include <testsuite_string.h> #include <testsuite_hooks.h> void @@ -31,7 +31,7 @@ test01() const char cstr_suf2[] = ".rgb"; const std::string_view sv_suf2(".rgb"); - const std::string s_test("slugs/slimy.jpg"); + const __gnu_test::string s_test("slugs/slimy.jpg"); const auto cstr_in_slugs = s_test.ends_with(cstr_suf); VERIFY( cstr_in_slugs ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc new file mode 100644 index 0000000..ba77f01 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++20 -Wnonnull -O0 -Wno-unused-result" } +// { dg-do compile { target c++20 } } + +#include <testsuite_string.h> + +void +test01(const __gnu_test::string& s) +{ + s.ends_with((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.ends_with((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.ends_with(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc index d27e824..70b522f 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc @@ -20,7 +20,7 @@ // basic_string ends_with -#include <string> +#include <testsuite_string.h> #include <testsuite_hooks.h> void @@ -31,7 +31,7 @@ test01() const wchar_t cstr_suf2[] = L".rgb"; const std::wstring_view sv_suf2(L".rgb"); - const std::wstring s_test(L"slugs/slimy.jpg"); + const __gnu_test::wstring s_test(L"slugs/slimy.jpg"); const auto cstr_in_slugs = s_test.ends_with(cstr_suf); VERIFY( cstr_in_slugs ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char.cc index 5c0b3af..dddf51c 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char.cc @@ -20,7 +20,7 @@ // basic_string begins_with -#include <string> +#include <testsuite_string.h> #include <testsuite_hooks.h> void @@ -31,7 +31,7 @@ test01() const char cstr_dir2[] = "worms/"; const std::string_view sv_dir2("worms/"); - const std::string s_test("slugs/slimy.jpg"); + const __gnu_test::string s_test("slugs/slimy.jpg"); const auto cstr_in_slugs = s_test.starts_with(cstr_dir); VERIFY( cstr_in_slugs ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc new file mode 100644 index 0000000..a023d9e --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++20 -Wnonnull -O0 -Wno-unused-result" } +// { dg-do compile { target c++20 } } + +#include <testsuite_string.h> + +void +test01(const __gnu_test::string& s) +{ + s.starts_with((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.starts_with((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.starts_with(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc index eda7321..747b23a 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc @@ -20,7 +20,7 @@ // basic_string begins_with -#include <string> +#include <testsuite_string.h> #include <testsuite_hooks.h> void @@ -31,7 +31,7 @@ test01() const wchar_t cstr_dir2[] = L"worms/"; const std::wstring_view sv_dir2(L"worms/"); - const std::wstring s_test(L"slugs/slimy.jpg"); + const __gnu_test::wstring s_test(L"slugs/slimy.jpg"); const auto cstr_in_slugs = s_test.starts_with(cstr_dir); VERIFY( cstr_in_slugs ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/1.cc index 704d2f6..be3e41a 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/1.cc @@ -35,12 +35,12 @@ int test01(void) // 2:8-chars_8-chars_ // The following triggers -Wstringop-overread. See PR 103332. str1 = std::string("8-chars_") + "8-chars_"; - str1.c_str(); + (void) str1.c_str(); // printf("1:%s\n", str1.c_str()); VERIFY( str1 == "8-chars_8-chars_" ); str2 = str1 + "7-chars"; // printf("2:%s\n", str1.c_str()); //str1 is gone - str1.c_str(); + (void) str1.c_str(); VERIFY( str1 == "8-chars_8-chars_" ); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/1.cc index 4020950..df3ff7c 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/1.cc @@ -32,11 +32,11 @@ int test01(void) // 1:8-chars_8-chars_ // 2:8-chars_8-chars_ str1 = std::wstring(L"8-chars_") + L"8-chars_"; - str1.c_str(); + (void) str1.c_str(); // wprintf("1:%s\n", str1.c_str()); str2 = str1 + L"7-chars"; // wprintf("2:%s\n", str1.c_str()); //str1 is gone - str1.c_str(); + (void) str1.c_str(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/capacity/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/capacity/1.cc index 0376d91..3d162c6 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/capacity/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/capacity/1.cc @@ -137,7 +137,7 @@ test01() sz03 = str02.size(); sz04 = str02.length(); VERIFY( sz03 == sz04 ); - str02.data(); + (void) str02.data(); sz03 = str02.size(); sz04 = str02.length(); VERIFY( sz03 == sz04 ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/1.cc index 5de62ec..b27e7d7 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/1.cc @@ -49,7 +49,7 @@ test01() VERIFY( cref3 == 'a' ); try { - str01.at(csz01); + (void) str01.at(csz01); VERIFY( false ); // Should not get here, as exception thrown. } catch (std::out_of_range& fail) diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/2.cc index e8f9db2..834d3f6 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/2.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/2.cc @@ -27,5 +27,5 @@ main() { typedef std::string_view string_view_type; string_view_type s; - s[0]; // abort + (void) s[0]; // abort } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc index 9877cd8..e9df872 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc @@ -49,7 +49,7 @@ test01() VERIFY( cref3 == L'a' ); try { - str01.at(csz01); + (void) str01.at(csz01); VERIFY( false ); // Should not get here, as exception thrown. } catch (std::out_of_range& fail) diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc index 23daa7a..840de84 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc @@ -29,5 +29,5 @@ main() { typedef std::wstring_view string_view_type; string_view_type s; - s[0]; // abort + (void) s[0]; // abort } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc new file mode 100644 index 0000000..fafadcc --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++23 -Wnonnull -O0 -Wno-unused-result" } +// { dg-do compile { target c++23 } } + +#include <string_view> + +void +test01(std::string_view s) +{ + s.contains((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.contains((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.contains(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc new file mode 100644 index 0000000..50437bb --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++20 -Wnonnull -O0 -Wno-unused-result" } +// { dg-do compile { target c++20 } } + +#include <string_view> + +void +test01(std::string_view s) +{ + s.ends_with((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.ends_with((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.ends_with(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc new file mode 100644 index 0000000..fedba28a --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++20 -Wnonnull -O0 -Wno-unused-result" } +// { dg-do compile { target c++20 } } + +#include <string_view> + +void +test01(std::string_view s) +{ + s.starts_with((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.starts_with((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.starts_with(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc new file mode 100644 index 0000000..520788d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { xfail *-*-* } } +// { dg-options "-D_GLIBCXX_DEBUG_BACKTRACE -lstdc++_libbacktrace" } +// { dg-require-effective-target stacktrace } + +#include <debug/vector> +#include <debug/checks.h> + +void test01() +{ + __gnu_test::check_assign1<__gnu_debug::vector<int> >(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/25_algorithms/stable_sort/4.cc b/libstdc++-v3/testsuite/25_algorithms/stable_sort/4.cc new file mode 100644 index 0000000..b7bda4e --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/stable_sort/4.cc @@ -0,0 +1,51 @@ +// { dg-options "-pedantic" } +// { dg-do compile } + +#include <algorithm> + +/* This type is reduced from QTypedArrayData::iterator which has an implicit + * conversion to its pointer type and a difference type of int. + * The expression Iter() + ptrdiff_t(0) is ambiguous with -pedantic because it + * could either convert the RHS to int and use Iter::operator+(int) + * or it could convert the LHS to pointer and use built-in pointer arithmetic. + */ +struct Iter +{ + struct value_type { bool operator<(value_type) const; }; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::random_access_iterator_tag iterator_category; + typedef int difference_type; + + reference operator*() const; + pointer operator->() const; + + reference operator[](difference_type) const; + + Iter& operator++(); + Iter& operator--(); + Iter operator++(int); + Iter operator--(int); + + Iter& operator+=(difference_type); + Iter& operator-=(difference_type); + + Iter operator+(difference_type) const; + Iter operator-(difference_type) const; + + difference_type operator-(Iter) const; + + operator pointer() const; // XXX this causes the ambiguity + + bool operator==(Iter) const; + bool operator!=(Iter) const; + + bool operator<(Iter) const; +}; + +Iter operator+(Iter::difference_type, Iter); + +int main() +{ + std::stable_sort(Iter(), Iter()); +} diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc index 1e8c5fd..2296fd1 100644 --- a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc +++ b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc @@ -41,18 +41,18 @@ void test04() // PUT strb_03.str(str_01); //reset - strb_03.str().length(); - strb_03.str().length(); + (void) strb_03.str().length(); + (void) strb_03.str().length(); // streamsize sputn(const char_typs* s, streamsize n) // write up to n chars to out_cur from s, returning number assigned // NB *sputn will happily put '\0' into your stream if you give it a chance* str_tmp = strb_03.str(); - str_tmp.length(); + (void) str_tmp.length(); strb_03.sputn("racadabras", 10);//"abracadabras or what?" - strb_03.str().length(); + (void) strb_03.str().length(); strb_03.sputn(", i wanna reach out and", 10); - strb_03.str().length(); + (void) strb_03.str().length(); str_tmp = strb_02.str(); strb_02.sputn("racadabra", 10); diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc index 6acc0f24..c44a535 100644 --- a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc @@ -41,18 +41,18 @@ void test04() // PUT strb_03.str(str_01); //reset - strb_03.str().length(); - strb_03.str().length(); + (void) strb_03.str().length(); + (void) strb_03.str().length(); // streamsize sputn(const char_typs* s, streamsize n) // write up to n chars to out_cur from s, returning number assigned // NB *sputn will happily put '\0' into your stream if you give it a chance* str_tmp = strb_03.str(); - str_tmp.length(); + (void) str_tmp.length(); strb_03.sputn(L"racadabras", 10);//"abracadabras or what?" - strb_03.str().length(); + (void) strb_03.str().length(); strb_03.sputn(L", i wanna reach out and", 10); - strb_03.str().length(); + (void) strb_03.str().length(); str_tmp = strb_02.str(); strb_02.sputn(L"racadabra", 10); diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/char/1.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/char/1.cc index 2a3a28b..b4cdb17 100644 --- a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/char/1.cc +++ b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/char/1.cc @@ -41,18 +41,18 @@ void test04() // PUT strb_03.str(str_01); //reset - strb_03.str().length(); - strb_03.str().length(); + (void) strb_03.str().length(); + (void) strb_03.str().length(); // streamsize sputn(const char_typs* s, streamsize n) // write up to n chars to out_cur from s, returning number assigned // NB *sputn will happily put '\0' into your stream if you give it a chance* str_tmp = strb_03.str(); - str_tmp.length(); + (void) str_tmp.length(); strb_03.sputn("racadabras", 10);//"abracadabras or what?" - strb_03.str().length(); + (void) strb_03.str().length(); strb_03.sputn(", i wanna reach out and", 10); - strb_03.str().length(); + (void) strb_03.str().length(); str_tmp = strb_02.str(); strb_02.sputn("racadabra", 10); diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc index 5f20e2c..eb0ae5e 100644 --- a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc @@ -41,18 +41,18 @@ void test04() // PUT strb_03.str(str_01); //reset - strb_03.str().length(); - strb_03.str().length(); + (void) strb_03.str().length(); + (void) strb_03.str().length(); // streamsize sputn(const char_typs* s, streamsize n) // write up to n chars to out_cur from s, returning number assigned // NB *sputn will happily put '\0' into your stream if you give it a chance* str_tmp = strb_03.str(); - str_tmp.length(); + (void) str_tmp.length(); strb_03.sputn(L"racadabras", 10);//"abracadabras or what?" - strb_03.str().length(); + (void) strb_03.str().length(); strb_03.sputn(L", i wanna reach out and", 10); - strb_03.str().length(); + (void) strb_03.str().length(); str_tmp = strb_02.str(); strb_02.sputn(L"racadabra", 10); diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc new file mode 100644 index 0000000..9829f79 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc @@ -0,0 +1,110 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include <ranges> +#include <algorithm> +#include <utility> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + static_assert(ranges::empty(std::array{1, 2, 3} | views::adjacent<0>)); + + auto v1 = std::array{1, 2} | views::adjacent<1>; + const auto i0 = v1.begin(), i1 = v1.begin() + 1; + VERIFY( i0 + 1 - 1 == i0 ); + VERIFY( i0 < i1 ); + VERIFY( i1 < v1.end() ); + VERIFY( i1 - i0 == 1 ); + VERIFY( i0 - i1 == -1 ); + VERIFY( v1.end() - i1 == 1 ); + VERIFY( i1 - v1.end() == -1 ); + ranges::iter_swap(i0, i1); + VERIFY( ranges::equal(std::move(v1) | views::keys, (int[]){2, 1}) ); + + int x[] = {1, 2, 3, 4}; + auto v2 = x | views::pairwise; + auto i2 = v2.begin(); + i2 += 2; + i2 -= -1; + VERIFY( i2 == v2.end() ); + VERIFY( ranges::size(v2) == 3 ); + VERIFY( ranges::size(std::as_const(v2)) == 3 ); + VERIFY( ranges::equal(v2 | views::keys, (int[]){1, 2, 3}) ); + VERIFY( ranges::equal(v2 | views::values, (int[]){2, 3, 4}) ); + + int y[] = {1, 2, 3, 4, 5}; + const auto v3 = y | views::adjacent<3>; + VERIFY( ranges::size(v3) == 3 ); + for (unsigned i = 0; i < ranges::size(x); i++) + { + VERIFY( &std::get<0>(v3[i]) == &y[i] + 0 ); + VERIFY( &std::get<1>(v3[i]) == &y[i] + 1 ); + VERIFY( &std::get<2>(v3[i]) == &y[i] + 2 ); + } + + const auto v5 = y | views::adjacent<5>; + VERIFY( ranges::equal(v5, views::single(std::make_tuple(1, 2, 3, 4, 5))) ); + + const auto v6 = y | views::adjacent<6>; + VERIFY( ranges::empty(v6) ); + + const auto v0 = y | views::adjacent<0>; + VERIFY( ranges::empty(v0) ); + + return true; +} + +constexpr bool +test02() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + using __gnu_test::test_random_access_range; + + using ty1 = ranges::adjacent_view<views::all_t<test_forward_range<int>>, 2>; + static_assert(ranges::forward_range<ty1>); + static_assert(!ranges::bidirectional_range<ty1>); + static_assert(!ranges::sized_range<ty1>); + + using ty2 = ranges::adjacent_view<views::all_t<test_random_access_range<int>>, 3>; + static_assert(ranges::random_access_range<ty2>); + static_assert(ranges::sized_range<ty2>); + + return true; +} + +constexpr bool +test03() +{ + auto v = views::iota(0, 4) | views::filter([](auto) { return true; }) | views::pairwise; + using ty = decltype(v); + static_assert(ranges::forward_range<ty>); + static_assert(ranges::common_range<ty>); + static_assert(!ranges::sized_range<ty>); + VERIFY( v.begin() == v.begin() ); + VERIFY( v.begin() != v.end() ); + VERIFY( ranges::next(v.begin(), 3) == v.end() ); + auto it = v.begin(); + ++it; + it++; + VERIFY( ranges::next(it) == v.end() ); + it--; + --it; + VERIFY( it == v.begin() ); + + return true; +} + +int +main() +{ + static_assert(test01()); + static_assert(test02()); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc new file mode 100644 index 0000000..07f20b7 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc @@ -0,0 +1,106 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include <ranges> +#include <algorithm> +#include <utility> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + auto v1 = std::array{1, 2, 3} | views::adjacent_transform<1>(std::identity{}); + VERIFY( ranges::equal(v1, (int[]){1, 2, 3}) ); + const auto i0 = v1.begin(), i1 = v1.begin() + 1; + VERIFY( i0 + 1 - 1 == i0 ); + VERIFY( i0 < i1 ); + VERIFY( i1 < v1.end() ); + VERIFY( i1 - i0 == 1 ); + VERIFY( i0 - i1 == -1 ); + VERIFY( v1.end() - i1 == 2 ); + VERIFY( i1 - v1.end() == -2 ); + ranges::iter_swap(i0, i1); + VERIFY( ranges::equal(std::move(v1), (int[]){2, 1, 3}) ); + + auto v2 = std::array{1, -1, 2, -2} | views::pairwise_transform(std::multiplies{}); + auto i2 = v2.begin(); + i2 += 1; + i2 -= -2; + VERIFY( i2 == v2.end() ); + VERIFY( ranges::size(v2) == 3 ); + VERIFY( ranges::size(std::as_const(v2)) == 3 ); + VERIFY( ranges::equal(v2, (int[]){-1, -2, -4}) ); + + int y[] = {1, 2, 3, 4, 5, 6}; + auto v3 = y | views::adjacent_transform<3>([](auto... xs) { return ranges::max({xs...}); }); + VERIFY( ranges::size(v3) == 4 ); + VERIFY( ranges::equal(v3, (int[]){3, 4, 5, 6}) ); + + const auto v6 = y | views::adjacent_transform<6>([](auto...) { return 0; }); + VERIFY( ranges::equal(v6, (int[]){0}) ); + + const auto v7 = y | views::adjacent_transform<7>([](auto...) { return 0; }); + VERIFY( ranges::empty(v7) ); + + const auto v0 = y | views::adjacent_transform<0>([] { return 0; }); + VERIFY( ranges::empty(v0) ); + + return true; +} + +constexpr bool +test02() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + using __gnu_test::test_random_access_range; + + using ty1 = ranges::adjacent_transform_view<views::all_t<test_forward_range<int>>, + std::plus<>, 2>; + static_assert(ranges::forward_range<ty1>); + static_assert(!ranges::bidirectional_range<ty1>); + static_assert(!ranges::sized_range<ty1>); + + using ty2 = ranges::adjacent_transform_view<views::all_t<test_random_access_range<int>>, + decltype([](int, int, int) { return 0;}), 3>; + static_assert(ranges::random_access_range<ty2>); + static_assert(ranges::sized_range<ty2>); + + return true; +} + +constexpr bool +test03() +{ + auto v = views::iota(0, 4) + | views::filter([](auto) { return true; }) + | views::pairwise_transform(std::plus{}); + using ty = decltype(v); + static_assert(ranges::forward_range<ty>); + static_assert(ranges::common_range<ty>); + static_assert(!ranges::sized_range<ty>); + VERIFY( v.begin() == v.begin() ); + VERIFY( v.begin() != v.end() ); + VERIFY( ranges::next(v.begin(), 3) == v.end() ); + auto it = v.begin(); + ++it; + it++; + VERIFY( ranges::next(it) == v.end() ); + it--; + --it; + VERIFY( it == v.begin() ); + + return true; +} + +int +main() +{ + static_assert(test01()); + static_assert(test02()); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/std/ranges/zip/1.cc b/libstdc++-v3/testsuite/std/ranges/zip/1.cc new file mode 100644 index 0000000..0113efd --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/zip/1.cc @@ -0,0 +1,111 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include <ranges> +#include <algorithm> +#include <utility> +#include <vector> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + static_assert(ranges::empty(views::zip())); + static_assert(ranges::empty(views::empty<int>)); + + auto z1 = views::zip(std::array{1, 2}); + const auto i0 = z1.begin(), i1 = z1.begin() + 1; + VERIFY( i0 + 1 - 1 == i0 ); + VERIFY( i0 < i1 ); + VERIFY( i1 < z1.end() ); + VERIFY( i1 - i0 == 1 ); + VERIFY( i0 - i1 == -1 ); + VERIFY( z1.end() - i1 == 1 ); + VERIFY( i1 - z1.end() == -1 ); + ranges::iter_swap(i0, i1); + VERIFY( ranges::equal(std::move(z1) | views::keys, (int[]){2, 1}) ); + + auto z2 = views::zip(std::array{1, 2}, std::array{3, 4, 5}); + auto i2 = z2.begin(); + i2 += 1; + i2 -= -1; + VERIFY( i2 == z2.end() ); + VERIFY( ranges::size(z2) == 2 ); + VERIFY( ranges::size(std::as_const(z2)) == 2 ); + VERIFY( z2[0].first == 1 && z2[0].second == 3 ); + VERIFY( z2[1].first == 2 && z2[1].second == 4 ); + for (const auto [x, y] : z2) + { + VERIFY( y - x == 2 ); + std::swap(x, y); + } + + int x[2] = {1, 2}, y[2] = {3, 4}, z[2] = {5, 6}; + const auto z3 = views::zip(x, y, z); + VERIFY( ranges::size(z3) == 2 ); + for (int i = 0; i < ranges::size(x); i++) + { + VERIFY( &std::get<0>(z3[i]) == &x[i] ); + VERIFY( &std::get<1>(z3[i]) == &y[i] ); + VERIFY( &std::get<2>(z3[i]) == &z[i] ); + } + + return true; +} + +constexpr bool +test02() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + using __gnu_test::test_random_access_range; + + using ty1 = ranges::zip_view<views::all_t<test_forward_range<int>>, + views::all_t<test_random_access_range<int>>>; + static_assert(ranges::forward_range<ty1>); + static_assert(!ranges::random_access_range<ty1>); + static_assert(!ranges::sized_range<ty1>); + + using ty2 = ranges::zip_view<views::all_t<test_forward_range<int>>, + views::all_t<test_input_range<int>>, + views::all_t<test_forward_range<int>>>; + static_assert(ranges::input_range<ty2>); + static_assert(!ranges::forward_range<ty2>); + static_assert(!ranges::sized_range<ty2>); + + return true; +} + +constexpr bool +test03() +{ + int u[] = {1, 2, 3, 4}, v[] = {4, 5, 6}, w[] = {7, 8, 9, 10}; + auto z = views::zip(u | views::filter([](auto) { return true; }), v, w); + using ty = decltype(z); + static_assert(ranges::forward_range<ty>); + static_assert(!ranges::common_range<ty>); + static_assert(!ranges::sized_range<ty>); + VERIFY( z.begin() == z.begin() ); + VERIFY( z.begin() != z.end() ); + VERIFY( ranges::next(z.begin(), 3) == z.end() ); + auto it = z.begin(); + ++it; + it++; + it--; + --it; + VERIFY( it == z.begin() ); + + return true; +} + +int +main() +{ + static_assert(test01()); + static_assert(test02()); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc b/libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc new file mode 100644 index 0000000..5ea24c57 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc @@ -0,0 +1,108 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include <ranges> +#include <algorithm> +#include <utility> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + static_assert(ranges::empty(views::zip_transform([] { return 0; }))); + + auto z1 = views::zip_transform(std::identity{}, + std::array{1, 2, 3}); + VERIFY( ranges::equal(z1, (int[]){1, 2, 3}) ); + const auto i0 = z1.begin(), i1 = z1.begin() + 1; + VERIFY( i0 + 1 - 1 == i0 ); + VERIFY( i0 < i1 ); + VERIFY( i1 < z1.end() ); + VERIFY( i1 - i0 == 1 ); + VERIFY( i0 - i1 == -1 ); + VERIFY( z1.end() - i1 == 2 ); + VERIFY( i1 - z1.end() == -2 ); + ranges::iter_swap(i0, i1); + VERIFY( ranges::equal(std::move(z1), (int[]){2, 1, 3}) ); + + auto z2 = views::zip_transform(std::multiplies{}, + std::array{-1, 2}, + std::array{3, 4, 5}); + auto i2 = z2.begin(); + i2 += 1; + i2 -= -1; + VERIFY( i2 == z2.end() ); + VERIFY( ranges::size(z2) == 2 ); + VERIFY( ranges::size(std::as_const(z2)) == 2 ); + VERIFY( ranges::equal(z2, (int[]){-3, 8}) ); + + auto z3 = views::zip_transform([] (auto... xs) { return ranges::max({xs...}); }, + std::array{1, 6, 7, 0, 0}, + std::array{2, 5, 9}, + std::array{3, 4, 8, 0}); + VERIFY( ranges::size(z3) == 3 ); + VERIFY( ranges::equal(z3, (int[]){3, 6, 9}) ); + + return true; +} + +constexpr bool +test02() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + using __gnu_test::test_random_access_range; + + using ty1 = ranges::zip_transform_view<std::plus<>, + views::all_t<test_forward_range<int>>, + views::all_t<test_random_access_range<int>>>; + static_assert(ranges::forward_range<ty1>); + static_assert(!ranges::random_access_range<ty1>); + static_assert(!ranges::sized_range<ty1>); + + using ty2 = ranges::zip_transform_view<decltype([](int, int, int) { return 0; }), + views::all_t<test_forward_range<int>>, + views::all_t<test_input_range<int>>, + views::all_t<test_forward_range<int>>>; + static_assert(ranges::input_range<ty2>); + static_assert(!ranges::forward_range<ty2>); + static_assert(!ranges::sized_range<ty2>); + + return true; +} + +constexpr bool +test03() +{ + int u[] = {1, 2, 3, 4}, v[] = {4, 5, 6}; + auto z = views::zip_transform(std::plus{}, + u | views::filter([](auto) { return true; }), + v); + using ty = decltype(z); + static_assert(ranges::forward_range<ty>); + static_assert(!ranges::common_range<ty>); + static_assert(!ranges::sized_range<ty>); + VERIFY( z.begin() == z.begin() ); + VERIFY( z.begin() != z.end() ); + VERIFY( ranges::next(z.begin(), 3) == z.end() ); + auto it = z.begin(); + ++it; + it++; + it--; + --it; + VERIFY( it == z.begin() ); + + return true; +} + +int +main() +{ + static_assert(test01()); + static_assert(test02()); + static_assert(test03()); +} |