On Tue, 15 Jun 2021 at 22:33, Jonathan Wakely wrote: > > On Tue, 15 Jun 2021 at 21:32, Tim Song wrote: > > > > CPOs are specified as actual semiregular function objects that can be > > copied and constructed freely, so it seems a bit hostile to make them > > final/non-addressable? (It's debatable whether the type of a CPO is a > > type "specified in the C++ standard library" for which [derivation]/4 > > would apply.) > > I noticed that libstdc++ was failing some libc++ tests, but that was > only for ranges::advance etc and not the CPOs. I guess I got a bit > carried away, and it shouldn't apply to the CPOs, only the > [range.iter.ops] "function templates" (which are not really function > templates).
This reverts the changes to the [range.access] CPOs, and improves some tests slightly. Tested powerpc64le-linux. Pushed to trunk.
commit b9e35ee6d64bc9f82b8fe641aa8ac12a9e259fe8 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Jun 16 12:34:52 2021 libstdc++: Revert final/non-addressable changes to ranges CPOs In r12-1489-g8b93548778a487f31f21e0c6afe7e0bde9711fc4 I made the [range.access] CPO types final and non-addressable. Tim Song pointed out this is wrong. Only the [range.iter.ops] functions should be final and non-addressable. Revert the changes to the [range.access] objects. Signed-off-by: Jonathan Wakely <jwak...@redhat.com> libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (ranges::begin, ranges::end) (ranges::cbegin, ranges::cend, ranges::rbeing, ranges::rend) (ranges::crbegin, ranges::crend, ranges::size, ranges::ssize) (ranges::empty, ranges::data, ranges::cdata): Remove final keywords and deleted operator& overloads. * testsuite/24_iterators/customization_points/iter_move.cc: Use new is_customization_point_object function. * testsuite/24_iterators/customization_points/iter_swap.cc: Likewise. * testsuite/std/concepts/concepts.lang/concept.swappable/swap.cc: Likewise. * testsuite/std/ranges/access/begin.cc: Likewise. * testsuite/std/ranges/access/cbegin.cc: Likewise. * testsuite/std/ranges/access/cdata.cc: Likewise. * testsuite/std/ranges/access/cend.cc: Likewise. * testsuite/std/ranges/access/crbegin.cc: Likewise. * testsuite/std/ranges/access/crend.cc: Likewise. * testsuite/std/ranges/access/data.cc: Likewise. * testsuite/std/ranges/access/empty.cc: Likewise. * testsuite/std/ranges/access/end.cc: Likewise. * testsuite/std/ranges/access/rbegin.cc: Likewise. * testsuite/std/ranges/access/rend.cc: Likewise. * testsuite/std/ranges/access/size.cc: Likewise. * testsuite/std/ranges/access/ssize.cc: Likewise. * testsuite/util/testsuite_iterators.h (is_customization_point_object): New function. diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index e392c370fcd..25af4b742a6 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -91,7 +91,7 @@ namespace ranges using std::ranges::__detail::__maybe_borrowed_range; using std::__detail::__range_iter_t; - struct _Begin final + struct _Begin { private: template<typename _Tp> @@ -106,8 +106,6 @@ namespace ranges return noexcept(__decay_copy(begin(std::declval<_Tp&>()))); } - void operator&() const = delete; - public: template<__maybe_borrowed_range _Tp> requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp> @@ -144,7 +142,7 @@ namespace ranges { __decay_copy(end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>; }; - struct _End final + struct _End { private: template<typename _Tp> @@ -159,8 +157,6 @@ namespace ranges return noexcept(__decay_copy(end(std::declval<_Tp&>()))); } - void operator&() const = delete; - public: template<__maybe_borrowed_range _Tp> requires is_bounded_array_v<remove_reference_t<_Tp>> @@ -193,7 +189,7 @@ namespace ranges return static_cast<const _Tp&&>(__t); } - struct _CBegin final + struct _CBegin { template<typename _Tp> constexpr auto @@ -203,8 +199,6 @@ namespace ranges { return _Begin{}(__cust_access::__as_const<_Tp>(__e)); } - - void operator&() const = delete; }; struct _CEnd final @@ -217,8 +211,6 @@ namespace ranges { return _End{}(__cust_access::__as_const<_Tp>(__e)); } - - void operator&() const = delete; }; template<typename _Tp> @@ -244,7 +236,7 @@ namespace ranges { _End{}(__t) } -> same_as<decltype(_Begin{}(__t))>; }; - struct _RBegin final + struct _RBegin { private: template<typename _Tp> @@ -268,8 +260,6 @@ namespace ranges } } - void operator&() const = delete; - public: template<__maybe_borrowed_range _Tp> requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp> @@ -304,7 +294,7 @@ namespace ranges -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>; }; - struct _REnd final + struct _REnd { private: template<typename _Tp> @@ -328,8 +318,6 @@ namespace ranges } } - void operator&() const = delete; - public: template<__maybe_borrowed_range _Tp> requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp> @@ -346,7 +334,7 @@ namespace ranges } }; - struct _CRBegin final + struct _CRBegin { template<typename _Tp> constexpr auto @@ -356,11 +344,9 @@ namespace ranges { return _RBegin{}(__cust_access::__as_const<_Tp>(__e)); } - - void operator&() const = delete; }; - struct _CREnd final + struct _CREnd { template<typename _Tp> constexpr auto @@ -370,8 +356,6 @@ namespace ranges { return _REnd{}(__cust_access::__as_const<_Tp>(__e)); } - - void operator&() const = delete; }; template<typename _Tp> @@ -402,7 +386,7 @@ namespace ranges __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t)); }; - struct _Size final + struct _Size { private: template<typename _Tp> @@ -420,8 +404,6 @@ namespace ranges - _Begin{}(std::declval<_Tp&>())); } - void operator&() const = delete; - public: template<typename _Tp> requires is_bounded_array_v<remove_reference_t<_Tp>> @@ -440,7 +422,7 @@ namespace ranges } }; - struct _SSize final + struct _SSize { // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3403. Domain of ranges::ssize(E) doesn't match ranges::size(E) @@ -469,8 +451,6 @@ namespace ranges else // Must be one of __max_diff_type or __max_size_type. return __detail::__max_diff_type(__size); } - - void operator&() const = delete; }; template<typename _Tp> @@ -487,7 +467,7 @@ namespace ranges bool(_Begin{}(__t) == _End{}(__t)); }; - struct _Empty final + struct _Empty { private: template<typename _Tp> @@ -503,8 +483,6 @@ namespace ranges == _End{}(std::declval<_Tp&>()))); } - void operator&() const = delete; - public: template<typename _Tp> requires __member_empty<_Tp> || __size0_empty<_Tp> @@ -534,7 +512,7 @@ namespace ranges template<typename _Tp> concept __begin_data = contiguous_iterator<__range_iter_t<_Tp>>; - struct _Data final + struct _Data { private: template<typename _Tp> @@ -547,8 +525,6 @@ namespace ranges return noexcept(_Begin{}(std::declval<_Tp&>())); } - void operator&() const = delete; - public: template<__maybe_borrowed_range _Tp> requires __member_data<_Tp> || __begin_data<_Tp> @@ -562,7 +538,7 @@ namespace ranges } }; - struct _CData final + struct _CData { template<typename _Tp> constexpr auto @@ -572,8 +548,6 @@ namespace ranges { return _Data{}(__cust_access::__as_const<_Tp>(__e)); } - - void operator&() const = delete; }; } // namespace __cust_access diff --git a/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc b/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc index 22030eca9a7..a43448581f3 100644 --- a/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc +++ b/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc @@ -20,6 +20,9 @@ #include <iterator> #include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +static_assert(__gnu_test::is_customization_point_object(std::ranges::iter_move)); struct X { diff --git a/libstdc++-v3/testsuite/24_iterators/customization_points/iter_swap.cc b/libstdc++-v3/testsuite/24_iterators/customization_points/iter_swap.cc index 35802723d60..f170e177d30 100644 --- a/libstdc++-v3/testsuite/24_iterators/customization_points/iter_swap.cc +++ b/libstdc++-v3/testsuite/24_iterators/customization_points/iter_swap.cc @@ -20,6 +20,9 @@ #include <iterator> #include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +static_assert(__gnu_test::is_customization_point_object(std::ranges::iter_swap)); struct X { diff --git a/libstdc++-v3/testsuite/std/concepts/concepts.lang/concept.swappable/swap.cc b/libstdc++-v3/testsuite/std/concepts/concepts.lang/concept.swappable/swap.cc index 4479c26f30b..ea469e953b2 100644 --- a/libstdc++-v3/testsuite/std/concepts/concepts.lang/concept.swappable/swap.cc +++ b/libstdc++-v3/testsuite/std/concepts/concepts.lang/concept.swappable/swap.cc @@ -19,6 +19,10 @@ // { dg-do compile { target c++2a } } #include <concepts> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +static_assert(__gnu_test::is_customization_point_object(std::ranges::swap)); namespace nu { diff --git a/libstdc++-v3/testsuite/std/ranges/access/begin.cc b/libstdc++-v3/testsuite/std/ranges/access/begin.cc index 6ef44ee631c..a08ad37fd34 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/begin.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/begin.cc @@ -22,6 +22,8 @@ #include <testsuite_hooks.h> #include <testsuite_iterators.h> +static_assert(__gnu_test::is_customization_point_object(std::ranges::begin)); + using std::same_as; void diff --git a/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc b/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc index dc06695139e..ed80af589cf 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc @@ -20,6 +20,10 @@ #include <ranges> #include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +static_assert(__gnu_test::is_customization_point_object(std::ranges::cbegin)); + using std::same_as; void diff --git a/libstdc++-v3/testsuite/std/ranges/access/cdata.cc b/libstdc++-v3/testsuite/std/ranges/access/cdata.cc index 2dfb6830789..d51ff1d32eb 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/cdata.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/cdata.cc @@ -20,6 +20,9 @@ #include <ranges> #include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +static_assert(__gnu_test::is_customization_point_object(std::ranges::cdata)); template<typename T> concept has_cdata diff --git a/libstdc++-v3/testsuite/std/ranges/access/cend.cc b/libstdc++-v3/testsuite/std/ranges/access/cend.cc index fcb80f28d3a..3e685ae9ce2 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/cend.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/cend.cc @@ -20,6 +20,9 @@ #include <ranges> #include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +static_assert(__gnu_test::is_customization_point_object(std::ranges::cend)); using std::same_as; diff --git a/libstdc++-v3/testsuite/std/ranges/access/crbegin.cc b/libstdc++-v3/testsuite/std/ranges/access/crbegin.cc index a41234b2dd4..6b02b478a15 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/crbegin.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/crbegin.cc @@ -22,6 +22,8 @@ #include <testsuite_hooks.h> #include <testsuite_iterators.h> +static_assert(__gnu_test::is_customization_point_object(std::ranges::crbegin)); + struct R1 { int i = 0; diff --git a/libstdc++-v3/testsuite/std/ranges/access/crend.cc b/libstdc++-v3/testsuite/std/ranges/access/crend.cc index 8f8b08abd3f..eb010d9d477 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/crend.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/crend.cc @@ -22,6 +22,8 @@ #include <testsuite_hooks.h> #include <testsuite_iterators.h> +static_assert(__gnu_test::is_customization_point_object(std::ranges::crend)); + struct R1 { int i = 0; diff --git a/libstdc++-v3/testsuite/std/ranges/access/data.cc b/libstdc++-v3/testsuite/std/ranges/access/data.cc index 4f16f447f9f..b2083d1890e 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/data.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/data.cc @@ -22,6 +22,8 @@ #include <testsuite_hooks.h> #include <testsuite_iterators.h> +static_assert(__gnu_test::is_customization_point_object(std::ranges::data)); + template<typename T> concept has_data = requires (T&& t) { std::ranges::data(std::forward<T>(t)); }; diff --git a/libstdc++-v3/testsuite/std/ranges/access/empty.cc b/libstdc++-v3/testsuite/std/ranges/access/empty.cc index b2d8b105325..3cad4740124 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/empty.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/empty.cc @@ -22,6 +22,8 @@ #include <testsuite_hooks.h> #include <testsuite_iterators.h> +static_assert(__gnu_test::is_customization_point_object(std::ranges::empty)); + using std::same_as; void diff --git a/libstdc++-v3/testsuite/std/ranges/access/end.cc b/libstdc++-v3/testsuite/std/ranges/access/end.cc index 7bf0dd44bb3..25f21c75afc 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/end.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/end.cc @@ -22,6 +22,8 @@ #include <testsuite_hooks.h> #include <testsuite_iterators.h> +static_assert(__gnu_test::is_customization_point_object(std::ranges::end)); + using std::same_as; void diff --git a/libstdc++-v3/testsuite/std/ranges/access/rbegin.cc b/libstdc++-v3/testsuite/std/ranges/access/rbegin.cc index a166ad74348..0006f89d4c5 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/rbegin.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/rbegin.cc @@ -22,6 +22,8 @@ #include <testsuite_hooks.h> #include <testsuite_iterators.h> +static_assert(__gnu_test::is_customization_point_object(std::ranges::rbegin)); + struct R1 { int i = 0; diff --git a/libstdc++-v3/testsuite/std/ranges/access/rend.cc b/libstdc++-v3/testsuite/std/ranges/access/rend.cc index 4ba5447c74a..0ac86bc8d4b 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/rend.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/rend.cc @@ -22,6 +22,8 @@ #include <testsuite_hooks.h> #include <testsuite_iterators.h> +static_assert(__gnu_test::is_customization_point_object(std::ranges::rend)); + struct R1 { int i = 0; diff --git a/libstdc++-v3/testsuite/std/ranges/access/size.cc b/libstdc++-v3/testsuite/std/ranges/access/size.cc index f25a1cb9ddb..c7e4f78f96a 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/size.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/size.cc @@ -22,6 +22,8 @@ #include <testsuite_hooks.h> #include <testsuite_iterators.h> +static_assert(__gnu_test::is_customization_point_object(std::ranges::size)); + void test01() { diff --git a/libstdc++-v3/testsuite/std/ranges/access/ssize.cc b/libstdc++-v3/testsuite/std/ranges/access/ssize.cc index fdbf245d036..7337f626a25 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/ssize.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/ssize.cc @@ -22,6 +22,8 @@ #include <testsuite_hooks.h> #include <testsuite_iterators.h> +static_assert(__gnu_test::is_customization_point_object(std::ranges::ssize)); + using std::ptrdiff_t; void diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h index 4e668d648f2..6b835ac475e 100644 --- a/libstdc++-v3/testsuite/util/testsuite_iterators.h +++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h @@ -894,6 +894,22 @@ namespace __gnu_test // This is also true for test_container, although only when it has forward // iterators (because output_iterator_wrapper and input_iterator_wrapper are // not default constructible so do not model std::input_or_output_iterator). + + + // Test for basic properties of C++20 16.3.3.6 [customization.point.object]. + template<typename T> + constexpr bool + is_customization_point_object(T& obj) noexcept + { + // A [CPO] is a function object with a literal class type. + static_assert( std::is_class_v<T> || std::is_union_v<T> ); + static_assert( __is_literal_type(T) ); + // The type of a [CPO], ignoring cv-qualifiers, shall model semiregular. + static_assert( std::semiregular<std::remove_cv_t<T>> ); + + return true; + } + #endif // C++20 } // namespace __gnu_test #endif // _TESTSUITE_ITERATORS