aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-10-29 17:44:18 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2019-10-29 17:44:18 +0000
commit6d0dff49ca1539e14647c04cc1bb035ef4c2780b (patch)
treee438e2b4a9d49f1cc15e751a889a0ed890cfd287 /libstdc++-v3/include
parent9921ac3db381106b66b70d8bf99136b265ec07c3 (diff)
downloadgcc-6d0dff49ca1539e14647c04cc1bb035ef4c2780b.zip
gcc-6d0dff49ca1539e14647c04cc1bb035ef4c2780b.tar.gz
gcc-6d0dff49ca1539e14647c04cc1bb035ef4c2780b.tar.bz2
Add iterator concepts and range access customization points for C++20
This adds most of the new C++20 features to <iterator>, as well as a few initial pieces of <ranges> (but no actual <ranges> header just yet). * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. * include/bits/iterator_concepts.h: New header. (contiguous_iterator_tag, iter_reference_t, ranges::iter_move) (iter_rvalue_reference_t, incrementable_traits, iter_difference_t) (readable_traits, iter_value_t, readable, iter_common_reference_t) (writable, waekly_incrementable, incrementable) (input_or_output_iterator, sentinel_for, disable_sized_sentinel) (sized_sentinel_for, input_iterator, output_iterator) (forward_iterator, bidirectional_iterator, random_access_iterator) (contiguous_iterator, indirectly_unary_invocable) (indirectly_regular_unary_invocable, indirect_unary_predicate) (indirect_relation, indirect_strict_weak_order, indirect_result_t) (projected, indirectly_movable, indirectly_movable_storable) (indirectly_copyable, indirectly_copyable_storable, ranges::iter_swap) (indirectly_swappable, indirectly_comparable, permutable, mergeable) (sortable, unreachable_sentinel_t, unreachable_sentinel) (default_sentinel_t, default_sentinel): Define. (__detail::__cpp17_iterator, __detail::__cpp17_input_iterator) (__detail::__cpp17_fwd_iterator, __detail::__cpp17_bidi_iterator) (__detail::__cpp17_randacc_iterator): Define. (__iterator_traits): Define constrained specializations. * include/bits/move.h (move): Only use old concept check for C++98. * include/bits/range_access.h (ranges::disable_sized_range) (ranges::begin, ranges::end, ranges::cbegin, ranges::cend) (ranges::rbegin, ranges::rend, ranges::crbegin, ranges::crend) (ranges::size, ranges::empty, ranges::data, ranges::cdata): Define new customization points for C++20. (ranges::range, ranges::sized_range): Define new concepts for C++20. (ranges::advance, ranges::distance, ranges::next, ranges::prev): Define new functions for C++20. (__adl_end, __adl_cdata, __adl_cbegin, __adl_cend, __adl_rbegin) (__adl_rend, __adl_crbegin, __adl_crend, __adl_cdata, __adl_size) (__adl_empty): Remove. * include/bits/stl_iterator.h (disable_sized_sentinel): Specialize for reverse_iterator. * include/bits/stl_iterator_base_types.h (contiguous_iterator_tag): Define new struct for C++20. (iterator_traits<_Tp*>): Constrain partial specialization in C++20. * include/std/concepts (__is_class_or_enum): Move to __detail namespace. * testsuite/20_util/forward/c_neg.cc: Adjust dg-error line number. * testsuite/20_util/forward/f_neg.cc: Likewise. * testsuite/24_iterators/associated_types/incrementable.traits.cc: New test. * testsuite/24_iterators/associated_types/readable.traits.cc: New test. * testsuite/24_iterators/contiguous/concept.cc: New test. * testsuite/24_iterators/contiguous/tag.cc: New test. * testsuite/24_iterators/customization_points/iter_move.cc: New test. * testsuite/24_iterators/customization_points/iter_swap.cc: New test. * testsuite/24_iterators/headers/iterator/synopsis_c++20.cc: New test. * testsuite/24_iterators/range_operations/advance.cc: New test. * testsuite/24_iterators/range_operations/distance.cc: New test. * testsuite/24_iterators/range_operations/next.cc: New test. * testsuite/24_iterators/range_operations/prev.cc: New test. * testsuite/26_numerics/adjacent_difference/requirements/ explicit_instantiation/2.cc: Rename types that conflict with C++20 concepts. * testsuite/26_numerics/adjacent_difference/requirements/ explicit_instantiation/pod.cc: Likewise. * testsuite/26_numerics/partial_sum/requirements/ explicit_instantiation/2.cc: Likewise. * testsuite/26_numerics/partial_sum/requirements/ explicit_instantiation/pod.cc: Likewise. * testsuite/experimental/iterator/requirements.cc: Likewise. * testsuite/std/ranges/access/begin.cc: New test. * testsuite/std/ranges/access/cbegin.cc: New test. * testsuite/std/ranges/access/cdata.cc: New test. * testsuite/std/ranges/access/cend.cc: New test. * testsuite/std/ranges/access/crbegin.cc: New test. * testsuite/std/ranges/access/crend.cc: New test. * testsuite/std/ranges/access/data.cc: New test. * testsuite/std/ranges/access/empty.cc: New test. * testsuite/std/ranges/access/end.cc: New test. * testsuite/std/ranges/access/rbegin.cc: New test. * testsuite/std/ranges/access/rend.cc: New test. * testsuite/std/ranges/access/size.cc: New test. * testsuite/util/testsuite_iterators.h (contiguous_iterator_wrapper) (test_range, test_sized_range): New test utilities. From-SVN: r277579
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r--libstdc++-v3/include/Makefile.am1
-rw-r--r--libstdc++-v3/include/Makefile.in1
-rw-r--r--libstdc++-v3/include/bits/iterator_concepts.h828
-rw-r--r--libstdc++-v3/include/bits/move.h7
-rw-r--r--libstdc++-v3/include/bits/range_access.h750
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h16
-rw-r--r--libstdc++-v3/include/bits/stl_iterator_base_types.h37
-rw-r--r--libstdc++-v3/include/std/concepts15
8 files changed, 1596 insertions, 59 deletions
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 9ff12f1..401c87a 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -129,6 +129,7 @@ bits_headers = \
${bits_srcdir}/invoke.h \
${bits_srcdir}/ios_base.h \
${bits_srcdir}/istream.tcc \
+ ${bits_srcdir}/iterator_concepts.h \
${bits_srcdir}/list.tcc \
${bits_srcdir}/locale_classes.h \
${bits_srcdir}/locale_classes.tcc \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 5dce01f..e0a7496 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -473,6 +473,7 @@ bits_headers = \
${bits_srcdir}/invoke.h \
${bits_srcdir}/ios_base.h \
${bits_srcdir}/istream.tcc \
+ ${bits_srcdir}/iterator_concepts.h \
${bits_srcdir}/list.tcc \
${bits_srcdir}/locale_classes.h \
${bits_srcdir}/locale_classes.tcc \
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
new file mode 100644
index 0000000..323689e
--- /dev/null
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -0,0 +1,828 @@
+// Concepts and traits for use with iterators -*- C++ -*-
+
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/iterator_concepts.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{iterator}
+ */
+
+#ifndef _ITERATOR_CONCEPTS_H
+#define _ITERATOR_CONCEPTS_H 1
+
+#pragma GCC system_header
+
+#include <concepts>
+#include <bits/ptr_traits.h> // to_address
+#include <bits/range_cmp.h> // identity, ranges::less
+
+#if __cpp_lib_concepts
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ struct input_iterator_tag;
+ struct output_iterator_tag;
+ struct forward_iterator_tag;
+ struct bidirectional_iterator_tag;
+ struct random_access_iterator_tag;
+ struct contiguous_iterator_tag;
+
+ template<typename _Iterator>
+ struct iterator_traits;
+
+ template<typename _Tp> requires is_object_v<_Tp>
+ struct iterator_traits<_Tp*>;
+
+ template<typename _Iterator, typename>
+ struct __iterator_traits;
+
+ namespace __detail
+ {
+ template<typename _Tp>
+ using __with_ref = _Tp&;
+
+ template<typename _Tp>
+ concept __can_reference = requires { typename __with_ref<_Tp>; };
+
+ template<typename _Tp>
+ concept __dereferenceable = requires(_Tp& __t)
+ {
+ { *__t } -> __can_reference;
+ };
+
+ // FIXME: needed due to PR c++/67704
+ template<__detail::__dereferenceable _Tp>
+ struct __iter_ref
+ {
+ using type = decltype(*std::declval<_Tp&>());
+ };
+ } // namespace __detail
+
+ template<typename _Tp>
+ using iter_reference_t = typename __detail::__iter_ref<_Tp>::type;
+
+ namespace ranges
+ {
+ namespace __cust_imove
+ {
+ template<typename _Tp>
+ concept __adl_imove
+ = (std::__detail::__class_or_enum<remove_reference_t<_Tp>>)
+ && requires(_Tp&& __t) { iter_move(static_cast<_Tp&&>(__t)); };
+
+ struct _IMove
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__adl_imove<_Tp>)
+ return noexcept(iter_move(std::declval<_Tp>()));
+ else
+ return noexcept(*std::declval<_Tp>());
+ }
+
+ public:
+ template<typename _Tp>
+ requires __adl_imove<_Tp> || requires(_Tp& __e) { *__e; }
+ constexpr decltype(auto)
+ operator()(_Tp&& __e) const
+ noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__adl_imove<_Tp>)
+ return iter_move(static_cast<_Tp&&>(__e));
+ else if constexpr (is_reference_v<iter_reference_t<_Tp>>)
+ return std::move(*__e);
+ else
+ return *__e;
+ }
+ };
+ } // namespace __cust_imove
+
+ inline namespace __cust
+ {
+ inline constexpr __cust_imove::_IMove iter_move{};
+ } // inline namespace __cust
+ } // namespace ranges
+
+ namespace __detail
+ {
+ // FIXME: needed due to PR c++/67704
+ template<__detail::__dereferenceable _Tp>
+ struct __iter_rvalue_ref
+ { };
+
+ template<__detail::__dereferenceable _Tp>
+ requires requires(_Tp& __t)
+ {
+ { ranges::iter_move(__t) } -> __detail::__can_reference;
+ }
+ struct __iter_rvalue_ref<_Tp>
+ { using type = decltype(ranges::iter_move(std::declval<_Tp&>())); };
+
+ } // namespace __detail
+
+ template<typename _Tp>
+ using iter_rvalue_reference_t
+ = typename __detail::__iter_rvalue_ref<_Tp>::type;
+
+ template<typename> struct incrementable_traits { };
+
+ template<typename _Tp> requires is_object_v<_Tp>
+ struct incrementable_traits<_Tp*>
+ { using difference_type = ptrdiff_t; };
+
+ template<typename _Iter>
+ struct incrementable_traits<const _Iter>
+ : incrementable_traits<_Iter> { };
+
+ template<typename _Tp> requires requires { typename _Tp::difference_type; }
+ struct incrementable_traits<_Tp>
+ { using difference_type = typename _Tp::difference_type; };
+
+ template<typename _Tp>
+ requires (!requires { typename _Tp::difference_type; }
+ && requires(const _Tp& __a, const _Tp& __b)
+ {
+ requires (!is_void_v<remove_pointer_t<_Tp>>); // PR c++/78173
+ { __a - __b } -> integral;
+ })
+ struct incrementable_traits<_Tp>
+ {
+ using difference_type
+ = make_signed_t<decltype(std::declval<_Tp>() - std::declval<_Tp>())>;
+ };
+
+ namespace __detail
+ {
+ // An iterator such that iterator_traits<_Iter> names a specialization
+ // generated from the primary template.
+ template<typename _Iter>
+ concept __primary_traits_iter
+ = __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>);
+
+ template<typename _Iter, typename _Tp>
+ struct __iter_traits_impl
+ { using type = iterator_traits<_Iter>; };
+
+ template<typename _Iter, typename _Tp>
+ requires __primary_traits_iter<_Iter>
+ struct __iter_traits_impl<_Iter, _Tp>
+ { using type = _Tp; };
+
+ // ITER_TRAITS
+ template<typename _Iter, typename _Tp = _Iter>
+ using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type;
+ } // namespace __detail
+
+ template<typename _Tp>
+ using iter_difference_t = typename
+ __detail::__iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type;
+
+ namespace __detail
+ {
+ template<typename> struct __cond_value_type { };
+
+ template<typename _Tp> requires is_object_v<_Tp>
+ struct __cond_value_type<_Tp>
+ { using value_type = remove_cv_t<_Tp>; };
+ } // namespace __detail
+
+ template<typename> struct readable_traits { };
+
+ template<typename _Tp>
+ struct readable_traits<_Tp*>
+ : __detail::__cond_value_type<_Tp>
+ { };
+
+ template<typename _Iter> requires is_array_v<_Iter>
+ struct readable_traits<_Iter>
+ { using value_type = remove_cv_t<remove_extent_t<_Iter>>; };
+
+ template<typename _Iter>
+ struct readable_traits<const _Iter>
+ : readable_traits<_Iter>
+ { };
+
+ template<typename _Tp> requires requires { typename _Tp::value_type; }
+ struct readable_traits<_Tp>
+ : __detail::__cond_value_type<typename _Tp::value_type>
+ { };
+
+ template<typename _Tp> requires requires { typename _Tp::element_type; }
+ struct readable_traits<_Tp>
+ : __detail::__cond_value_type<typename _Tp::element_type>
+ { };
+
+ template<typename _Tp>
+ using iter_value_t = typename
+ __detail::__iter_traits<_Tp, readable_traits<_Tp>>::value_type;
+
+ namespace __detail
+ {
+ template<typename _Iter>
+ concept __cpp17_iterator = copyable<_Iter>
+ && requires(_Iter __it)
+ {
+ { *__it } -> __can_reference;
+ { ++__it } -> same_as<_Iter&>;
+ { *__it++ } -> __can_reference;
+ };
+
+ template<typename _Iter>
+ concept __cpp17_input_iterator = __cpp17_iterator<_Iter>
+ && equality_comparable<_Iter>
+ && requires(_Iter __it)
+ {
+ typename incrementable_traits<_Iter>::difference_type;
+ typename readable_traits<_Iter>::value_type;
+ typename common_reference_t<iter_reference_t<_Iter>&&,
+ typename readable_traits<_Iter>::value_type&>;
+ typename common_reference_t<decltype(*__it++)&&,
+ typename readable_traits<_Iter>::value_type&>;
+ requires signed_integral<typename incrementable_traits<_Iter>::difference_type>;
+ };
+
+ template<typename _Iter>
+ concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter>
+ && constructible_from<_Iter>
+ && is_lvalue_reference_v<iter_reference_t<_Iter>>
+ && same_as<remove_cvref_t<iter_reference_t<_Iter>>,
+ typename readable_traits<_Iter>::value_type>
+ && requires(_Iter __it)
+ {
+ { __it++ } -> convertible_to<const _Iter&>;
+ { *__it++ } -> same_as<iter_reference_t<_Iter>>;
+ };
+
+ template<typename _Iter>
+ concept __cpp17_bidi_iterator = __cpp17_fwd_iterator<_Iter>
+ && requires(_Iter __it)
+ {
+ { --__it } -> same_as<_Iter&>;
+ { __it-- } -> convertible_to<const _Iter&>;
+ { *__it-- } -> same_as<iter_reference_t<_Iter>>;
+ };
+
+ template<typename _Iter>
+ concept __cpp17_randacc_iterator = __cpp17_bidi_iterator<_Iter>
+ && totally_ordered<_Iter>
+ && requires(_Iter __it,
+ typename incrementable_traits<_Iter>::difference_type __n)
+ {
+ { __it += __n } -> same_as<_Iter&>;
+ { __it -= __n } -> same_as<_Iter&>;
+ { __it + __n } -> same_as<_Iter>;
+ { __n + __it } -> same_as<_Iter>;
+ { __it - __n } -> same_as<_Iter>;
+ { __it - __it } -> same_as<decltype(__n)>;
+ { __it[__n] } -> convertible_to<iter_reference_t<_Iter>>;
+ };
+
+ template<typename _Iter>
+ concept __iter_with_nested_types = requires {
+ typename _Iter::iterator_category;
+ typename _Iter::value_type;
+ typename _Iter::difference_type;
+ typename _Iter::reference;
+ };
+
+ // FIXME: needed due to PR c++/92102
+ template<typename _Iter>
+ concept __iter_without_nested_types = !__iter_with_nested_types<_Iter>;
+
+ template<typename _Iter, bool __use_arrow = false>
+ struct __ptr
+ { using type = void; };
+
+ template<typename _Iter> requires requires { typename _Iter::pointer; }
+ struct __ptr<_Iter, true>
+ { using type = typename _Iter::pointer; };
+
+ template<typename _Iter> requires requires { typename _Iter::pointer; }
+ struct __ptr<_Iter, false>
+ { using type = typename _Iter::pointer; };
+
+ template<typename _Iter>
+ requires (!requires { typename _Iter::pointer; }
+ && requires(_Iter& __it) { __it.operator->(); })
+ struct __ptr<_Iter, true>
+ { using type = decltype(std::declval<_Iter&>().operator->()); };
+
+ template<typename _Iter>
+ struct __ref
+ { using type = iter_reference_t<_Iter>; };
+
+ template<typename _Iter> requires requires { typename _Iter::reference; }
+ struct __ref<_Iter>
+ { using type = typename _Iter::reference; };
+
+ template<typename _Iter>
+ struct __cat
+ { using type = input_iterator_tag; };
+
+ template<typename _Iter>
+ requires requires { typename _Iter::iterator_category; }
+ struct __cat<_Iter>
+ { using type = typename _Iter::iterator_category; };
+
+ template<typename _Iter>
+ requires (!requires { typename _Iter::iterator_category; }
+ && __detail::__cpp17_randacc_iterator<_Iter>)
+ struct __cat<_Iter>
+ { using type = random_access_iterator_tag; };
+
+ template<typename _Iter>
+ requires (!requires { typename _Iter::iterator_category; }
+ && __detail::__cpp17_bidi_iterator<_Iter>)
+ struct __cat<_Iter>
+ { using type = bidirectional_iterator_tag; };
+
+ template<typename _Iter>
+ requires (!requires { typename _Iter::iterator_category; }
+ && __detail::__cpp17_fwd_iterator<_Iter>)
+ struct __cat<_Iter>
+ { using type = forward_iterator_tag; };
+
+ template<typename _Iter>
+ struct __diff
+ { using type = void; };
+
+ template<typename _Iter>
+ requires requires {
+ typename incrementable_traits<_Iter>::difference_type;
+ }
+ struct __diff<_Iter>
+ {
+ using type = typename incrementable_traits<_Iter>::difference_type;
+ };
+
+ } // namespace __detail
+
+ template<typename _Iterator>
+ requires __detail::__iter_with_nested_types<_Iterator>
+ struct __iterator_traits<_Iterator, void>
+ {
+ using iterator_category = typename _Iterator::iterator_category;
+ using value_type = typename _Iterator::value_type;
+ using difference_type = typename _Iterator::difference_type;
+ using pointer = typename __detail::__ptr<_Iterator>::type;
+ using reference = typename _Iterator::reference;
+ };
+
+ template<typename _Iterator>
+ requires __detail::__iter_without_nested_types<_Iterator>
+ && __detail::__cpp17_input_iterator<_Iterator>
+ struct __iterator_traits<_Iterator, void>
+ {
+ using iterator_category = typename __detail::__cat<_Iterator>::type;
+ using value_type
+ = typename readable_traits<_Iterator>::value_type;
+ using difference_type
+ = typename incrementable_traits<_Iterator>::difference_type;
+ using pointer = typename __detail::__ptr<_Iterator, true>::type;
+ using reference = typename __detail::__ref<_Iterator>::type;
+ };
+
+ template<typename _Iterator>
+ requires __detail::__iter_without_nested_types<_Iterator>
+ && __detail::__cpp17_iterator<_Iterator>
+ struct __iterator_traits<_Iterator, void>
+ {
+ using iterator_category = output_iterator_tag;
+ using value_type = void;
+ using difference_type = typename __detail::__diff<_Iterator>::type;
+ using pointer = void;
+ using reference = void;
+ };
+
+ namespace __detail
+ {
+ template<typename _Iter>
+ struct __iter_concept_impl
+ { };
+
+ template<typename _Iter>
+ requires requires { typename __iter_traits<_Iter>::iterator_concept; }
+ struct __iter_concept_impl<_Iter>
+ { using type = typename __iter_traits<_Iter>::iterator_concept; };
+
+ template<typename _Iter>
+ requires (!requires { typename __iter_traits<_Iter>::iterator_concept; }
+ && requires { typename __iter_traits<_Iter>::iterator_category; })
+ struct __iter_concept_impl<_Iter>
+ { using type = typename __iter_traits<_Iter>::iterator_category; };
+
+ template<typename _Iter>
+ requires (!requires { typename __iter_traits<_Iter>::iterator_concept; }
+ && !requires { typename __iter_traits<_Iter>::iterator_category; }
+ && __primary_traits_iter<_Iter>)
+ struct __iter_concept_impl<_Iter>
+ { using type = random_access_iterator_tag; };
+
+ // ITER_TRAITS
+ template<typename _Iter>
+ using __iter_concept = typename __iter_concept_impl<_Iter>::type;
+ } // namespace __detail
+
+ /// Requirements for types that are readable by applying operator*.
+ template<typename _In>
+ concept readable = requires
+ {
+ typename iter_value_t<_In>;
+ typename iter_reference_t<_In>;
+ typename iter_rvalue_reference_t<_In>;
+ }
+ && common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&>
+ && common_reference_with<iter_reference_t<_In>&&,
+ iter_rvalue_reference_t<_In>&&>
+ && common_reference_with<iter_rvalue_reference_t<_In>&&,
+ const iter_value_t<_In>&>;
+
+ namespace __detail
+ {
+ // FIXME: needed due to PR c++/67704
+ template<readable _Tp>
+ struct __iter_common_ref
+ : common_reference<iter_reference_t<_Tp>, iter_value_t<_Tp>&>
+ { };
+
+ // FIXME: needed due to PR c++/67704
+ template<typename _Fn, typename... _Is>
+ struct __indirect_result
+ { };
+
+ template<typename _Fn, typename... _Is>
+ requires (readable<_Is> && ...)
+ && invocable<_Fn, iter_reference_t<_Is>...>
+ struct __indirect_result<_Fn, _Is...>
+ : invoke_result<_Fn, iter_reference_t<_Is>...>
+ { };
+ } // namespace __detail
+
+ template<typename _Tp>
+ using iter_common_reference_t
+ = typename __detail::__iter_common_ref<_Tp>::type;
+
+ /// Requirements for writing a value into an iterator's referenced object.
+ template<typename _Out, typename _Tp>
+ concept writable = requires(_Out&& __o, _Tp&& __t)
+ {
+ *__o = std::forward<_Tp>(__t);
+ *std::forward<_Out>(__o) = std::forward<_Tp>(__t);
+ const_cast<const iter_reference_t<_Out>&&>(*__o)
+ = std::forward<_Tp>(__t);
+ const_cast<const iter_reference_t<_Out>&&>(*std::forward<_Out>(__o))
+ = std::forward<_Tp>(__t);
+ };
+
+ /// Requirements on types that can be incremented with ++.
+ template<typename _Iter>
+ concept weakly_incrementable = default_constructible<_Iter>
+ && movable<_Iter>
+ && requires(_Iter __i)
+ {
+ typename iter_difference_t<_Iter>;
+ requires signed_integral<iter_difference_t<_Iter>>;
+ { ++__i } -> same_as<_Iter&>;
+ __i++;
+ };
+
+ template<typename _Iter>
+ concept incrementable = regular<_Iter> && weakly_incrementable<_Iter>
+ && requires(_Iter __i) { { __i++ } -> same_as<_Iter>; };
+
+ template<typename _Iter>
+ concept input_or_output_iterator
+ = requires(_Iter __i) { { *__i } -> __detail::__can_reference; }
+ && weakly_incrementable<_Iter>;
+
+ template<typename _Sent, typename _Iter>
+ concept sentinel_for = semiregular<_Sent>
+ && input_or_output_iterator<_Iter>
+ && __detail::__weakly_eq_cmp_with<_Sent, _Iter>;
+
+ template<typename _Sent, typename _Iter>
+ inline constexpr bool disable_sized_sentinel = false;
+
+ template<typename _Sent, typename _Iter>
+ concept sized_sentinel_for = sentinel_for<_Sent, _Iter>
+ && !disable_sized_sentinel<remove_cv_t<_Sent>, remove_cv_t<_Iter>>
+ && requires(const _Iter& __i, const _Sent& __s)
+ {
+ { __s - __i } -> same_as<iter_difference_t<_Iter>>;
+ { __i - __s } -> same_as<iter_difference_t<_Iter>>;
+ };
+
+ template<typename _Iter>
+ concept input_iterator = input_or_output_iterator<_Iter>
+ && readable<_Iter>
+ && requires { typename __detail::__iter_concept<_Iter>; }
+ && derived_from<__detail::__iter_concept<_Iter>, input_iterator_tag>;
+
+ template<typename _Iter, typename _Tp>
+ concept output_iterator = input_or_output_iterator<_Iter>
+ && writable<_Iter, _Tp>
+ && requires(_Iter __i, _Tp&& __t) { *__i++ = std::forward<_Tp>(__t); };
+
+ template<typename _Iter>
+ concept forward_iterator = input_iterator<_Iter>
+ && derived_from<__detail::__iter_concept<_Iter>, forward_iterator_tag>
+ && incrementable<_Iter> && sentinel_for<_Iter, _Iter>;
+
+ template<typename _Iter>
+ concept bidirectional_iterator = forward_iterator<_Iter>
+ && derived_from<__detail::__iter_concept<_Iter>,
+ bidirectional_iterator_tag>
+ && requires(_Iter __i)
+ {
+ { --__i } -> same_as<_Iter&>;
+ { __i-- } -> same_as<_Iter>;
+ };
+
+ template<typename _Iter>
+ concept random_access_iterator = bidirectional_iterator<_Iter>
+ && derived_from<__detail::__iter_concept<_Iter>,
+ random_access_iterator_tag>
+ && totally_ordered<_Iter> && sized_sentinel_for<_Iter, _Iter>
+ && requires(_Iter __i, const _Iter __j,
+ const iter_difference_t<_Iter> __n)
+ {
+ { __i += __n } -> same_as<_Iter&>;
+ { __j + __n } -> same_as<_Iter>;
+ { __n + __j } -> same_as<_Iter>;
+ { __i -= __n } -> same_as<_Iter&>;
+ { __j - __n } -> same_as<_Iter>;
+ { __j[__n] } -> same_as<iter_reference_t<_Iter>>;
+ };
+
+ template<typename _Iter>
+ concept contiguous_iterator = random_access_iterator<_Iter>
+ && derived_from<__detail::__iter_concept<_Iter>, contiguous_iterator_tag>
+ && is_lvalue_reference_v<iter_reference_t<_Iter>>
+ && same_as<iter_value_t<_Iter>, remove_cvref_t<iter_reference_t<_Iter>>>
+ && requires(const _Iter& __i)
+ {
+ { std::to_address(__i) }
+ -> same_as<add_pointer_t<iter_reference_t<_Iter>>>;
+ };
+
+ // [indirectcallable], indirect callable requirements
+
+ // [indirectcallable.indirectinvocable], indirect callables
+
+ template<typename _Fn, typename _Iter>
+ concept indirectly_unary_invocable = readable<_Iter>
+ && copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&>
+ && invocable<_Fn&, iter_reference_t<_Iter>>
+ && invocable<_Fn&, iter_common_reference_t<_Iter>>
+ && common_reference_with<invoke_result_t<_Fn&, iter_value_t<_Iter>&>,
+ invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
+
+ template<typename _Fn, typename _Iter>
+ concept indirectly_regular_unary_invocable = readable<_Iter>
+ && copy_constructible<_Fn>
+ && regular_invocable<_Fn&, iter_value_t<_Iter>&>
+ && regular_invocable<_Fn&, iter_reference_t<_Iter>>
+ && regular_invocable<_Fn&, iter_common_reference_t<_Iter>>
+ && common_reference_with<invoke_result_t<_Fn&, iter_value_t<_Iter>&>,
+ invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
+
+ template<typename _Fn, typename _Iter>
+ concept indirect_unary_predicate = readable<_Iter>
+ && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&>
+ && predicate<_Fn&, iter_reference_t<_Iter>>
+ && predicate<_Fn&, iter_common_reference_t<_Iter>>;
+
+ template<typename _Fn, typename _I1, typename _I2 = _I1>
+ concept indirect_relation = readable<_I1> && readable<_I2>
+ && copy_constructible<_Fn>
+ && relation<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
+ && relation<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
+ && relation<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
+ && relation<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
+ && relation<_Fn&, iter_common_reference_t<_I1>,
+ iter_common_reference_t<_I2>>;
+
+ template<typename _Fn, typename _I1, typename _I2 = _I1>
+ concept indirect_strict_weak_order = readable<_I1> && readable<_I2>
+ && copy_constructible<_Fn>
+ && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
+ && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
+ && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
+ && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
+ && strict_weak_order<_Fn&, iter_common_reference_t<_I1>,
+ iter_common_reference_t<_I2>>;
+
+ template<typename _Fn, typename... _Is>
+ using indirect_result_t = typename
+ __detail::__indirect_result<_Fn, iter_reference_t<_Is>...>::type;
+
+ /// [projected], projected
+ template<readable _Iter, indirectly_regular_unary_invocable<_Iter> _Proj>
+ struct projected
+ {
+ using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>;
+ indirect_result_t<_Proj&, _Iter> operator*() const; // not defined
+ };
+
+ template<weakly_incrementable _Iter, typename _Proj>
+ struct incrementable_traits<projected<_Iter, _Proj>>
+ { using difference_type = iter_difference_t<_Iter>; };
+
+ // [alg.req], common algorithm requirements
+
+ /// [alg.req.ind.move], concept `indirectly_movable`
+
+ template<typename _In, typename _Out>
+ concept indirectly_movable = readable<_In>
+ && writable<_Out, iter_rvalue_reference_t<_In>>;
+
+ template<typename _In, typename _Out>
+ concept indirectly_movable_storable = indirectly_movable<_In, _Out>
+ && writable<_Out, iter_value_t<_In>> && movable<iter_value_t<_In>>
+ && constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>>
+ && assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>;
+
+ /// [alg.req.ind.copy], concept `indirectly_copyable`
+ template<typename _In, typename _Out>
+ concept indirectly_copyable = readable<_In>
+ && writable<_Out, iter_reference_t<_In>>;
+
+ template<typename _In, typename _Out>
+ concept indirectly_copyable_storable = indirectly_copyable<_In, _Out>
+ && writable<_Out, const iter_value_t<_In>&>
+ && copyable<iter_value_t<_In>>
+ && constructible_from<iter_value_t<_In>, iter_reference_t<_In>>
+ && assignable_from<iter_value_t<_In>&, iter_reference_t<_In>>;
+
+namespace ranges
+{
+ namespace __cust_iswap
+ {
+ template<typename _It1, typename _It2>
+ void iter_swap(_It1&, _It2&) = delete;
+
+ template<typename _Tp, typename _Up>
+ concept __adl_iswap
+ = (std::__detail::__class_or_enum<remove_reference_t<_Tp>>
+ || std::__detail::__class_or_enum<remove_reference_t<_Up>>)
+ && requires(_Tp&& __t, _Up&& __u) {
+ iter_swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
+ };
+
+ template<typename _Xp, typename _Yp>
+ constexpr iter_value_t<remove_reference_t<_Xp>>
+ __iter_exchange_move(_Xp&& __x, _Yp&& __y)
+ noexcept(noexcept(iter_value_t<remove_reference_t<_Xp>>(iter_move(__x)))
+ && noexcept(*__x = iter_move(__y)))
+ {
+ iter_value_t<remove_reference_t<_Xp>> __old_value(iter_move(__x));
+ *__x = iter_move(__y);
+ return __old_value;
+ }
+
+ struct _IterSwap
+ {
+ private:
+ template<typename _Tp, typename _Up>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__adl_iswap<_Tp, _Up>)
+ return noexcept(iter_swap(std::declval<_Tp>(),
+ std::declval<_Up>()));
+ else if constexpr (readable<_Tp> && readable<_Up>
+ && swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
+ return noexcept(ranges::swap(*std::declval<_Tp>(),
+ *std::declval<_Up>()));
+ else
+ return noexcept(*std::declval<_Tp>()
+ = __iter_exchange_move(std::declval<_Up>(),
+ std::declval<_Tp>()));
+ }
+
+ public:
+ template<typename _Tp, typename _Up>
+ requires __adl_iswap<_Tp, _Up>
+ || (readable<_Tp> && readable<_Up>
+ && swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
+ || (indirectly_movable_storable<_Tp, _Up>
+ && indirectly_movable_storable<_Up, _Tp>)
+ constexpr void
+ operator()(_Tp&& __e1, _Up&& __e2) const
+ noexcept(_S_noexcept<_Tp, _Up>())
+ {
+ if constexpr (__adl_iswap<_Tp, _Up>)
+ iter_swap(static_cast<_Tp&&>(__e1), static_cast<_Up&&>(__e2));
+ else if constexpr (readable<_Tp> && readable<_Up>
+ && swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
+ ranges::swap(*__e1, *__e2);
+ else
+ *__e1 = __iter_exchange_move(__e2, __e1);
+ }
+ };
+ } // namespace __cust_iswap
+
+ inline namespace __cust
+ {
+ inline constexpr __cust_iswap::_IterSwap iter_swap{};
+ } // inline namespace __cust
+
+} // namespace ranges
+
+ /// [alg.req.ind.swap], concept `indirectly_swappable`
+ template<typename _I1, typename _I2 = _I1>
+ concept indirectly_swappable = readable<_I1> && readable<_I2>
+ && requires(_I1& __i1, _I2& __i2)
+ {
+ ranges::iter_swap(__i1, __i1);
+ ranges::iter_swap(__i2, __i2);
+ ranges::iter_swap(__i1, __i2);
+ ranges::iter_swap(__i2, __i1);
+ };
+
+ /// [alg.req.ind.cmp], concept `indirectly_comparable`
+ template<typename _I1, typename _I2, typename _Rel, typename _P1 = identity,
+ typename _P2 = identity>
+ concept indirectly_comparable
+ = indirect_relation<_Rel, projected<_I1, _P1>, projected<_I2, _P2>>;
+
+ /// [alg.req.permutable], concept `permutable`
+ template<typename _Iter>
+ concept permutable = forward_iterator<_Iter>
+ && indirectly_movable_storable<_Iter, _Iter>
+ && indirectly_swappable<_Iter, _Iter>;
+
+ /// [alg.req.mergeable], concept `mergeable`
+ template<typename _I1, typename _I2, typename _Out,
+ typename _Rel = ranges::less, typename _P1 = identity,
+ typename _P2 = identity>
+ concept mergeable = input_iterator<_I1> && input_iterator<_I2>
+ && weakly_incrementable<_Out> && indirectly_copyable<_I1, _Out>
+ && indirectly_copyable<_I2, _Out>
+ && indirect_strict_weak_order<_Rel, projected<_I1, _P1>,
+ projected<_I2, _P2>>;
+
+ /// [alg.req.sortable], concept `sortable`
+ template<typename _Iter, typename _Rel = ranges::less,
+ typename _Proj = identity>
+ concept sortable = permutable<_Iter>
+ && indirect_strict_weak_order<_Rel, projected<_Iter, _Proj>>;
+
+ struct unreachable_sentinel_t
+ {
+ template<weakly_incrementable _It>
+ friend constexpr bool
+ operator==(unreachable_sentinel_t, const _It&) noexcept
+ { return false; }
+
+#ifndef __cpp_lib_three_way_comparison
+ template<weakly_incrementable _It>
+ friend constexpr bool
+ operator!=(unreachable_sentinel_t, const _It&) noexcept
+ { return true; }
+
+ template<weakly_incrementable _It>
+ friend constexpr bool
+ operator==(const _It&, unreachable_sentinel_t) noexcept
+ { return false; }
+
+ template<weakly_incrementable _It>
+ friend constexpr bool
+ operator!=(const _It&, unreachable_sentinel_t) noexcept
+ { return true; }
+#endif
+ };
+
+ inline constexpr unreachable_sentinel_t unreachable_sentinel{};
+
+ struct default_sentinel_t { };
+ inline constexpr default_sentinel_t default_sentinel{};
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20 library concepts
+#endif // _ITERATOR_CONCEPTS_H
diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h
index d7c7068..5d6541d 100644
--- a/libstdc++-v3/include/bits/move.h
+++ b/libstdc++-v3/include/bits/move.h
@@ -31,7 +31,9 @@
#define _MOVE_H 1
#include <bits/c++config.h>
-#include <bits/concept_check.h>
+#if __cplusplus < 201103L
+# include <bits/concept_check.h>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -188,9 +190,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NOEXCEPT_IF(__and_<is_nothrow_move_constructible<_Tp>,
is_nothrow_move_assignable<_Tp>>::value)
{
+#if __cplusplus < 201103L
// concept requirements
__glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
-
+#endif
_Tp __tmp = _GLIBCXX_MOVE(__a);
__a = _GLIBCXX_MOVE(__b);
__b = _GLIBCXX_MOVE(__tmp);
diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h
index bc137d7..3b6ed9a 100644
--- a/libstdc++-v3/include/bits/range_access.h
+++ b/libstdc++-v3/include/bits/range_access.h
@@ -34,6 +34,8 @@
#if __cplusplus >= 201103L
#include <initializer_list>
+#include <bits/iterator_concepts.h>
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -344,60 +346,722 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _Container>
constexpr auto
- __adl_end(_Container& __cont) noexcept(noexcept(end(__cont)))
- { return end(__cont); }
+ __adl_data(_Container& __cont) noexcept(noexcept(data(__cont)))
+ { return data(__cont); }
- template <typename _Container>
- constexpr auto
- __adl_cbegin(_Container& __cont) noexcept(noexcept(cbegin(__cont)))
- { return cbegin(__cont); }
+namespace ranges
+{
+ template<typename>
+ inline constexpr bool disable_sized_range = false;
- template <typename _Container>
- constexpr auto
- __adl_cend(_Container& __cont) noexcept(noexcept(cend(__cont)))
- { return cend(__cont); }
+ namespace __detail
+ {
+ using __max_diff_type = long long;
+ using __max_size_type = unsigned long long;
- template <typename _Container>
- constexpr auto
- __adl_rbegin(_Container& __cont) noexcept(noexcept(rbegin(__cont)))
- { return rbegin(__cont); }
+ template<typename _Tp>
+ concept __is_integer_like = integral<_Tp>
+ || same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>;
- template <typename _Container>
- constexpr auto
- __adl_rend(_Container& __cont) noexcept(noexcept(rend(__cont)))
- { return rend(__cont); }
+ template<typename _Tp>
+ concept __is_signed_integer_like = signed_integral<_Tp>
+ || same_as<_Tp, __max_diff_type>;
- template <typename _Container>
- constexpr auto
- __adl_crbegin(_Container& __cont) noexcept(noexcept(crbegin(__cont)))
- { return crbegin(__cont); }
+ template<integral _Tp>
+ constexpr make_unsigned_t<_Tp>
+ __to_unsigned_like(_Tp __t) noexcept
+ { return __t; }
+ } // namespace __detail
- template <typename _Container>
- constexpr auto
- __adl_crend(_Container& __cont) noexcept(noexcept(crend(__cont)))
- { return crend(__cont); }
+ namespace __cust_access
+ {
+ template<typename _Tp>
+ constexpr decay_t<_Tp>
+ __decay_copy(_Tp&& __t)
+ noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>)
+ { return std::forward<_Tp>(__t); }
- template <typename _Container>
- constexpr auto
- __adl_data(_Container& __cont) noexcept(noexcept(data(__cont)))
- { return data(__cont); }
+ template<typename _Tp>
+ concept __member_begin = is_lvalue_reference_v<_Tp>
+ && requires(_Tp __t)
+ { { __decay_copy(__t.begin()) } -> input_or_output_iterator; };
- template <typename _Container>
- constexpr auto
- __adl_cdata(_Container& __cont) noexcept(noexcept(cdata(__cont)))
- { return cdata(__cont); }
+ template<typename _Tp> void begin(_Tp&&) = delete;
+ template<typename _Tp> void begin(initializer_list<_Tp>&&) = delete;
- template <typename _Container>
- constexpr auto
- __adl_size(_Container& __cont) noexcept(noexcept(size(__cont)))
- { return size(__cont); }
+ template<typename _Tp>
+ concept __adl_begin = requires(_Tp&& __t)
+ {
+ { __decay_copy(begin(std::forward<_Tp>(__t))) }
+ -> input_or_output_iterator;
+ };
- template <typename _Container>
- constexpr auto
- __adl_empty(_Container& __cont) noexcept(noexcept(empty(__cont)))
- { return empty(__cont); }
-#endif // C++20
+ template<typename _Tp>
+ concept __complete_type = requires(_Tp* __p) { __p + 1; };
+
+ struct _Begin
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_begin<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp>().begin()));
+ else
+ return noexcept(__decay_copy(begin(std::declval<_Tp>())));
+ }
+
+ public:
+ template<__complete_type _Tp, size_t _Nm>
+ constexpr _Tp*
+ operator()(_Tp (&__e)[_Nm]) const noexcept
+ { return __e; }
+
+ template<typename _Tp> requires __member_begin<_Tp> || __adl_begin<_Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_begin<_Tp>)
+ return __e.begin();
+ else
+ return begin(std::forward<_Tp>(__e));
+ }
+ };
+
+ template<typename _Tp>
+ concept __member_end = is_lvalue_reference_v<_Tp>
+ && requires(_Tp __t)
+ {
+ { __decay_copy(__t.end()) }
+ -> sentinel_for<decltype(_Begin{}(__t))>;
+ };
+
+ template<typename _Tp> void end(_Tp&&) = delete;
+ template<typename _Tp> void end(initializer_list<_Tp>&&) = delete;
+ template<typename _Tp>
+ concept __adl_end = requires(_Tp&& __t)
+ {
+ { __decay_copy(end(std::forward<_Tp>(__t))) }
+ -> sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
+ };
+
+ struct _End
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_end<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp>().end()));
+ else
+ return noexcept(__decay_copy(end(std::declval<_Tp>())));
+ }
+
+ public:
+ template<__complete_type _Tp, size_t _Nm>
+ constexpr _Tp*
+ operator()(_Tp (&__e)[_Nm]) const noexcept
+ { return __e + _Nm; }
+
+ template<typename _Tp> requires __member_end<_Tp> || __adl_end<_Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_end<_Tp>)
+ return __e.end();
+ else
+ return end(std::forward<_Tp>(__e));
+ }
+ };
+
+ template<typename _Tp>
+ constexpr decltype(auto)
+ __as_const(_Tp&& __t) noexcept
+ {
+ if constexpr (is_lvalue_reference_v<_Tp>)
+ return static_cast<const remove_reference_t<_Tp>&>(__t);
+ else
+ return static_cast<const _Tp&&>(__t);
+ }
+
+ struct _CBegin
+ {
+ template<typename _Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_Begin{}(__cust_access::__as_const((_Tp&&)__e))))
+ requires requires { _Begin{}(__cust_access::__as_const((_Tp&&)__e)); }
+ {
+ return _Begin{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
+ }
+ };
+
+ struct _CEnd
+ {
+ template<typename _Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_End{}(__cust_access::__as_const((_Tp&&)__e))))
+ requires requires { _End{}(__cust_access::__as_const((_Tp&&)__e)); }
+ {
+ return _End{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
+ }
+ };
+
+ template<typename _Tp>
+ concept __member_rbegin = is_lvalue_reference_v<_Tp>
+ && requires(_Tp __t)
+ { { __decay_copy(__t.rbegin()) } -> input_or_output_iterator; };
+
+ template<typename _Tp> void rbegin(_Tp&&) = delete;
+
+ template<typename _Tp>
+ concept __adl_rbegin = requires(_Tp&& __t)
+ {
+ { __decay_copy(rbegin(std::forward<_Tp>(__t))) }
+ -> input_or_output_iterator;
+ };
+
+ template<typename _Tp>
+ concept __reversable = requires(_Tp&& __t)
+ {
+ { _Begin{}(std::forward<_Tp>(__t)) } -> bidirectional_iterator;
+ { _End{}(std::forward<_Tp>(__t)) }
+ -> same_as<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
+ };
+
+ struct _RBegin
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_rbegin<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp>().rbegin()));
+ else if constexpr (__adl_rbegin<_Tp>)
+ return noexcept(__decay_copy(rbegin(std::declval<_Tp>())));
+ else if constexpr (noexcept(_End{}(std::declval<_Tp>())))
+ {
+ using _It = decltype(_End{}(std::declval<_Tp>()));
+ // std::reverse_iterator copy-initializes its member.
+ return is_nothrow_copy_constructible_v<_It>;
+ }
+ else
+ return false;
+ }
+
+ public:
+ template<typename _Tp>
+ requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_rbegin<_Tp>)
+ return __e.rbegin();
+ else if constexpr (__adl_rbegin<_Tp>)
+ return rbegin(std::forward<_Tp>(__e));
+ else
+ return std::make_reverse_iterator(_End{}(std::forward<_Tp>(__e)));
+ }
+ };
+
+ template<typename _Tp>
+ concept __member_rend = is_lvalue_reference_v<_Tp>
+ && requires(_Tp __t)
+ {
+ { __decay_copy(__t.rend()) }
+ -> sentinel_for<decltype(_RBegin{}(__t))>;
+ };
+
+ template<typename _Tp> void rend(_Tp&&) = delete;
+
+ template<typename _Tp>
+ concept __adl_rend = requires(_Tp&& __t)
+ {
+ { __decay_copy(rend(std::forward<_Tp>(__t))) }
+ -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
+ };
+
+ struct _REnd
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_rend<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp>().rend()));
+ else if constexpr (__adl_rend<_Tp>)
+ return noexcept(__decay_copy(rend(std::declval<_Tp>())));
+ else if constexpr (noexcept(_Begin{}(std::declval<_Tp>())))
+ {
+ using _It = decltype(_Begin{}(std::declval<_Tp>()));
+ // std::reverse_iterator copy-initializes its member.
+ return is_nothrow_copy_constructible_v<_It>;
+ }
+ else
+ return false;
+ }
+
+ public:
+ template<typename _Tp>
+ requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_rend<_Tp>)
+ return __e.rend();
+ else if constexpr (__adl_rend<_Tp>)
+ return rend(std::forward<_Tp>(__e));
+ else
+ return std::make_reverse_iterator(_Begin{}(std::forward<_Tp>(__e)));
+ }
+ };
+
+ struct _CRBegin
+ {
+ template<typename _Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_RBegin{}(__cust_access::__as_const((_Tp&&)__e))))
+ requires requires { _RBegin{}(__cust_access::__as_const((_Tp&&)__e)); }
+ {
+ return _RBegin{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
+ }
+ };
+
+ struct _CREnd
+ {
+ template<typename _Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_REnd{}(__cust_access::__as_const((_Tp&&)__e))))
+ requires requires { _REnd{}(__cust_access::__as_const((_Tp&&)__e)); }
+ {
+ return _REnd{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
+ }
+ };
+
+ template<typename _Tp>
+ concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>>
+ && requires(_Tp&& __t)
+ {
+ { __decay_copy(std::forward<_Tp>(__t).size()) }
+ -> __detail::__is_integer_like;
+ };
+
+ template<typename _Tp> void size(_Tp&&) = delete;
+
+ template<typename _Tp>
+ concept __adl_size = !disable_sized_range<remove_cvref_t<_Tp>>
+ && requires(_Tp&& __t)
+ {
+ { __decay_copy(size(std::forward<_Tp>(__t))) }
+ -> __detail::__is_integer_like;
+ };
+
+ // FIXME: needed due to PR c++/92268
+ template<forward_iterator _It, sized_sentinel_for<_It> _End>
+ requires requires (_It __it, _End __end)
+ { { __end - __it } -> __detail::__is_integer_like; }
+ void
+ __subtractable_fwd_iter(_It, _End)
+ { }
+
+ template<typename _Tp>
+ concept __sizable = requires(_Tp&& __t)
+ {
+ __subtractable_fwd_iter(_Begin{}(std::forward<_Tp>(__t)),
+ _End{}(std::forward<_Tp>(__t)));
+ };
+
+ struct _Size
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_size<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp>().size()));
+ else if constexpr (__adl_size<_Tp>)
+ return noexcept(__decay_copy(size(std::declval<_Tp>())));
+ else if constexpr (__sizable<_Tp>)
+ return noexcept(_End{}(std::declval<_Tp>())
+ - _Begin{}(std::declval<_Tp>()));
+ }
+
+ public:
+ template<__complete_type _Tp, size_t _Nm>
+ constexpr size_t
+ operator()(_Tp (&__e)[_Nm]) const noexcept
+ { return _Nm; }
+
+ template<typename _Tp>
+ requires __member_size<_Tp> || __adl_size<_Tp> || __sizable<_Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_size<_Tp>)
+ return std::forward<_Tp>(__e).size();
+ else if constexpr (__adl_size<_Tp>)
+ return size(std::forward<_Tp>(__e));
+ else if constexpr (__sizable<_Tp>)
+ return __detail::__to_unsigned_like(
+ _End{}(std::forward<_Tp>(__e))
+ - _Begin{}(std::forward<_Tp>(__e)));
+ }
+ };
+
+ template<typename _Tp>
+ concept __member_empty = requires(_Tp&& __t)
+ { bool(std::forward<_Tp>(__t).empty()); };
+
+ template<typename _Tp>
+ concept __size0_empty = requires(_Tp&& __t)
+ { _Size{}(std::forward<_Tp>(__t)) == 0; };
+
+ template<typename _Tp>
+ concept __eq_iter_empty = requires(_Tp&& __t)
+ {
+ { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator;
+ bool(_Begin{}(std::forward<_Tp>(__t))
+ == _End{}(std::forward<_Tp>(__t)));
+ };
+
+ struct _Empty
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_empty<_Tp>)
+ return noexcept(std::declval<_Tp>().empty());
+ else if constexpr (__size0_empty<_Tp>)
+ return noexcept(_Size{}(std::declval<_Tp>()) == 0);
+ else
+ return noexcept(bool(_Begin{}(std::declval<_Tp>())
+ == _End{}(std::declval<_Tp>())));
+ }
+
+ public:
+ template<typename _Tp>
+ requires __member_empty<_Tp> || __size0_empty<_Tp>
+ || __eq_iter_empty<_Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_empty<_Tp>)
+ return bool(std::forward<_Tp>(__e).empty());
+ else if constexpr (__size0_empty<_Tp>)
+ return _Size{}(std::forward<_Tp>(__e)) == 0;
+ else
+ return bool(_Begin{}(std::forward<_Tp>(__e))
+ == _End{}(std::forward<_Tp>(__e)));
+ }
+ };
+
+ template<typename _Tp>
+ concept __pointer_to_object = is_pointer_v<_Tp>
+ && is_object_v<remove_pointer_t<_Tp>>;
+
+ template<typename _Tp>
+ concept __member_data = is_lvalue_reference_v<_Tp>
+ && requires(_Tp __t) { { __t.data() } -> __pointer_to_object; };
+
+ template<typename _Tp>
+ concept __begin_data = requires(_Tp&& __t)
+ { { _Begin{}(std::forward<_Tp>(__t)) } -> contiguous_iterator; };
+
+ struct _Data
+ {
+ private:
+ template<typename _Tp>
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (__member_data<_Tp>)
+ return noexcept(__decay_copy(std::declval<_Tp>().data()));
+ else
+ return noexcept(_Begin{}(std::declval<_Tp>()));
+ }
+
+ public:
+ template<typename _Tp> requires __member_data<_Tp> || __begin_data<_Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
+ {
+ if constexpr (__member_data<_Tp>)
+ return __e.data();
+ else
+ return std::to_address(_Begin{}(std::forward<_Tp>(__e)));
+ }
+ };
+
+ struct _CData
+ {
+ template<typename _Tp>
+ constexpr auto
+ operator()(_Tp&& __e) const
+ noexcept(noexcept(_Data{}(__cust_access::__as_const((_Tp&&)__e))))
+ requires requires { _Data{}(__cust_access::__as_const((_Tp&&)__e)); }
+ {
+ return _Data{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
+ }
+ };
+
+ } // namespace __cust_access
+
+ inline namespace __cust
+ {
+ inline constexpr __cust_access::_Begin begin{};
+ inline constexpr __cust_access::_End end{};
+ inline constexpr __cust_access::_CBegin cbegin{};
+ inline constexpr __cust_access::_CEnd cend{};
+ inline constexpr __cust_access::_RBegin rbegin{};
+ inline constexpr __cust_access::_REnd rend{};
+ inline constexpr __cust_access::_CRBegin crbegin{};
+ inline constexpr __cust_access::_CREnd crend{};
+ inline constexpr __cust_access::_Size size{};
+ inline constexpr __cust_access::_Empty empty{};
+ inline constexpr __cust_access::_Data data{};
+ inline constexpr __cust_access::_CData cdata{};
+ }
+
+ namespace __detail
+ {
+ template<typename _Tp>
+ concept __range_impl = requires(_Tp&& __t) {
+ ranges::begin(std::forward<_Tp>(__t));
+ ranges::end(std::forward<_Tp>(__t));
+ };
+
+ } // namespace __detail
+
+ /// [range.range] The range concept.
+ template<typename _Tp>
+ concept range = __detail::__range_impl<_Tp&>;
+
+ /// [range.sized] The sized_range concept.
+ template<typename _Tp>
+ concept sized_range = range<_Tp>
+ && requires(_Tp& __t) { ranges::size(__t); };
+
+ // [range.iter.ops] range iterator operations
+
+ template<input_or_output_iterator _It>
+ constexpr void
+ advance(_It& __it, iter_difference_t<_It> __n)
+ {
+ if constexpr (random_access_iterator<_It>)
+ __it += __n;
+ else if constexpr (bidirectional_iterator<_It>)
+ {
+ if (__n > 0)
+ {
+ do
+ {
+ ++__it;
+ }
+ while (--__n);
+ }
+ else if (__n < 0)
+ {
+ do
+ {
+ --__it;
+ }
+ while (++__n);
+ }
+ }
+ else
+ {
+#ifdef __cpp_lib_is_constant_evaluated
+ if (std::is_constant_evaluated() && __n < 0)
+ throw "attempt to decrement a non-bidirectional iterator";
+#endif
+ __glibcxx_assert(__n >= 0);
+ while (__n-- > 0)
+ ++__it;
+ }
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr void
+ advance(_It& __it, _Sent __bound)
+ {
+ if constexpr (assignable_from<_It&, _Sent>)
+ __it = std::move(__bound);
+ else if constexpr (sized_sentinel_for<_Sent, _It>)
+ ranges::advance(__it, __bound - __it);
+ else
+ {
+ while (__it != __bound)
+ ++__it;
+ }
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr iter_difference_t<_It>
+ advance(_It& __it, iter_difference_t<_It> __n, _Sent __bound)
+ {
+ if constexpr (sized_sentinel_for<_Sent, _It>)
+ {
+ const auto __diff = __bound - __it;
+#ifdef __cpp_lib_is_constant_evaluated
+ if (std::is_constant_evaluated()
+ && !(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0)))
+ throw "inconsistent directions for distance and bound";
+#endif
+ // n and bound must not lead in opposite directions:
+ __glibcxx_assert(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0));
+ const auto __absdiff = __diff < 0 ? -__diff : __diff;
+ const auto __absn = __n < 0 ? -__n : __n;;
+ if (__absn >= __absdiff)
+ {
+ ranges::advance(__it, __bound);
+ return __n - __diff;
+ }
+ else
+ {
+ ranges::advance(__it, __n);
+ return 0;
+ }
+ }
+ else if (__it == __bound || __n == 0)
+ return iter_difference_t<_It>(0);
+ else if (__n > 0)
+ {
+ iter_difference_t<_It> __m = 0;
+ do
+ {
+ ++__it;
+ ++__m;
+ }
+ while (__m != __n && __it != __bound);
+ return __n - __m;
+ }
+ else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>)
+ {
+ iter_difference_t<_It> __m = 0;
+ do
+ {
+ --__it;
+ --__m;
+ }
+ while (__m != __n && __it != __bound);
+ return __n - __m;
+ }
+ else
+ {
+#ifdef __cpp_lib_is_constant_evaluated
+ if (std::is_constant_evaluated() && __n < 0)
+ throw "attempt to decrement a non-bidirectional iterator";
+#endif
+ __glibcxx_assert(__n >= 0);
+ return __n;
+ }
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr iter_difference_t<_It>
+ distance(_It __first, _Sent __last)
+ {
+ if constexpr (sized_sentinel_for<_Sent, _It>)
+ return __last - __first;
+ else
+ {
+ iter_difference_t<_It> __n = 0;
+ while (__first != __last)
+ {
+ ++__first;
+ ++__n;
+ }
+ return __n;
+ }
+ }
+
+ template<range _Range>
+ using iterator_t = decltype(ranges::begin(std::declval<_Range&>()));
+
+ template<range _Range>
+ using range_difference_t = iter_difference_t<iterator_t<_Range>>;
+
+ template<range _Range>
+ constexpr range_difference_t<_Range>
+ distance(_Range&& __r)
+ {
+ if constexpr (sized_range<_Range>)
+ return static_cast<range_difference_t<_Range>>(ranges::size(__r));
+ else
+ return ranges::distance(ranges::begin(__r), ranges::end(__r));
+ }
+
+ template<input_or_output_iterator _It>
+ constexpr _It
+ next(_It __x)
+ {
+ ++__x;
+ return __x;
+ }
+
+ template<input_or_output_iterator _It>
+ constexpr _It
+ next(_It __x, iter_difference_t<_It> __n)
+ {
+ ranges::advance(__x, __n);
+ return __x;
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr _It
+ next(_It __x, _Sent __bound)
+ {
+ ranges::advance(__x, __bound);
+ return __x;
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr _It
+ next(_It __x, iter_difference_t<_It> __n, _Sent __bound)
+ {
+ ranges::advance(__x, __n, __bound);
+ return __x;
+ }
+
+ template<bidirectional_iterator _It>
+ constexpr _It
+ prev(_It __x)
+ {
+ --__x;
+ return __x;
+ }
+
+ template<bidirectional_iterator _It>
+ constexpr _It
+ prev(_It __x, iter_difference_t<_It> __n)
+ {
+ ranges::advance(__x, -__n);
+ return __x;
+ }
+
+ template<bidirectional_iterator _It>
+ constexpr _It
+ prev(_It __x, iter_difference_t<_It> __n, _It __bound)
+ {
+ ranges::advance(__x, -__n, __bound);
+ return __x;
+ }
+
+} // namespace ranges
+#endif // C++20
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index 420fea6..9660875 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -431,7 +431,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__make_reverse_iterator(_Iterator __i)
{ return reverse_iterator<_Iterator>(__i); }
-# if __cplusplus > 201103L
+# if __cplusplus >= 201402L
# define __cpp_lib_make_reverse_iterator 201402
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -441,10 +441,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator>
make_reverse_iterator(_Iterator __i)
{ return reverse_iterator<_Iterator>(__i); }
-# endif
-#endif
-#if __cplusplus >= 201103L
+# if __cplusplus > 201703L
+ template<typename _Iterator1, typename _Iterator2>
+ requires (!sized_sentinel_for<_Iterator1, _Iterator2>)
+ inline constexpr bool disable_sized_sentinel<reverse_iterator<_Iterator1>,
+ reverse_iterator<_Iterator2>>
+ = true;
+# endif // C++20
+# endif // C++14
+
template<typename _Iterator>
_GLIBCXX20_CONSTEXPR
auto
@@ -463,7 +469,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__miter_base(reverse_iterator<_Iterator> __it)
-> decltype(__make_reverse_iterator(__miter_base(__it.base())))
{ return __make_reverse_iterator(__miter_base(__it.base())); }
-#endif
+#endif // C++11
// 24.4.2.2.1 back_insert_iterator
/**
diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h
index 951e704..3fad586 100644
--- a/libstdc++-v3/include/bits/stl_iterator_base_types.h
+++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h
@@ -67,6 +67,10 @@
# include <type_traits> // For __void_t, is_convertible
#endif
+#if __cplusplus > 201703L && __cpp_concepts
+# include <bits/iterator_concepts.h>
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -101,6 +105,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Random-access iterators support a superset of bidirectional
/// iterator operations.
struct random_access_iterator_tag : public bidirectional_iterator_tag { };
+
+#if __cplusplus > 201703L
+ /// Contiguous iterators point to objects stored contiguously in memory.
+ struct contiguous_iterator_tag : public random_access_iterator_tag { };
+#endif
//@}
/**
@@ -137,12 +146,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* argument. Specialized versions for pointers and pointers-to-const
* provide tighter, more correct semantics.
*/
+ template<typename _Iterator>
+ struct iterator_traits;
+
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2408. SFINAE-friendly common_type/iterator_traits is missing in C++14
template<typename _Iterator, typename = __void_t<>>
struct __iterator_traits { };
+#if ! __cpp_lib_concepts
+
template<typename _Iterator>
struct __iterator_traits<_Iterator,
__void_t<typename _Iterator::iterator_category,
@@ -157,11 +171,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
+#endif // ! concepts
template<typename _Iterator>
struct iterator_traits
: public __iterator_traits<_Iterator> { };
-#else
+
+#else // ! C++11
template<typename _Iterator>
struct iterator_traits
{
@@ -171,8 +187,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
-#endif
+#endif // C++11
+#if __cplusplus > 201703L
+ /// Partial specialization for object pointer types.
+ template<typename _Tp>
+#if __cpp_concepts
+ requires is_object_v<_Tp>
+#endif
+ struct iterator_traits<_Tp*>
+ {
+ using iterator_concept = contiguous_iterator_tag;
+ using iterator_category = random_access_iterator_tag;
+ using value_type = remove_cv_t<_Tp>;
+ using difference_type = ptrdiff_t;
+ using pointer = _Tp*;
+ using reference = _Tp&;
+ };
+#else
/// Partial specialization for pointer types.
template<typename _Tp>
struct iterator_traits<_Tp*>
@@ -194,6 +226,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef const _Tp* pointer;
typedef const _Tp& reference;
};
+#endif
/**
* This function is not a part of the C++ standard but is syntactic
diff --git a/libstdc++-v3/include/std/concepts b/libstdc++-v3/include/std/concepts
index 6d740eb..68cbba9 100644
--- a/libstdc++-v3/include/std/concepts
+++ b/libstdc++-v3/include/std/concepts
@@ -114,6 +114,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
template<typename _Tp>
using __cref = const remove_reference_t<_Tp>&;
+
+ template<typename _Tp>
+ concept __class_or_enum
+ = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
} // namespace __detail
/// [concept.assignable], concept assignable_from
@@ -159,14 +163,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
template<typename _Tp> void swap(_Tp&, _Tp&) = delete;
- template<typename _Tp>
- concept __class_or_enum
- = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
-
template<typename _Tp, typename _Up>
concept __adl_swap
- = (__class_or_enum<remove_cvref_t<_Tp>>
- || __class_or_enum<remove_cvref_t<_Up>>)
+ = (__detail::__class_or_enum<remove_reference_t<_Tp>>
+ || __detail::__class_or_enum<remove_reference_t<_Up>>)
&& requires(_Tp&& __t, _Up&& __u) {
swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
};
@@ -175,7 +175,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
template<typename _Tp, typename _Up>
requires __adl_swap<_Tp, _Up>
- constexpr void operator()(_Tp&& __t, _Up&& __u) const
+ constexpr void
+ operator()(_Tp&& __t, _Up&& __u) const
noexcept(noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())))
{ swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); }