aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2024-08-22 09:24:11 -0400
committerPatrick Palka <ppalka@redhat.com>2024-08-22 09:24:11 -0400
commitb552730faf36f1eae1dc6e73ccc93a016dec5401 (patch)
tree93377445ca094cd9dde66ffae5cdadef7fea61ae
parenta98dd536b1017c2b814a3465206c6c01b2890998 (diff)
downloadgcc-b552730faf36f1eae1dc6e73ccc93a016dec5401.zip
gcc-b552730faf36f1eae1dc6e73ccc93a016dec5401.tar.gz
gcc-b552730faf36f1eae1dc6e73ccc93a016dec5401.tar.bz2
libstdc++: Implement P2609R3 changes to the indirect invocability concepts
This implements the changes of this C++23 paper as a DR against C++20. Note that after the later P2538R1 "ADL-proof std::projected" (which we already implement), we can't use a simple partial specialization to match specializations of the 'projected' alias template. So instead we identify such specializations using a pair of distinguishing member aliases. libstdc++-v3/ChangeLog: * include/bits/iterator_concepts.h (__detail::__indirect_value): Define. (__indirect_value_t): Define as per P2609R3. (iter_common_reference_t): Adjust as per P2609R3. (indirectly_unary_invocable): Likewise. (indirectly_regular_unary_invocable): Likewise. (indirect_unary_predicate): Likewise. (indirect_binary_predicate): Likewise. (indirect_equivalence_relation): Likewise. (indirect_strict_weak_order): Likewise. (__detail::__projected::__type): Define member aliases __projected_Iter and __projected_Proj providing the template arguments of the current specialization. * include/bits/version.def (ranges): Update value. * include/bits/version.h: Regenerate. * testsuite/24_iterators/indirect_callable/p2609r3.cc: New test. * testsuite/std/ranges/version_c++23.cc: Update expected value of __cpp_lib_ranges macro. Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
-rw-r--r--libstdc++-v3/include/bits/iterator_concepts.h61
-rw-r--r--libstdc++-v3/include/bits/version.def2
-rw-r--r--libstdc++-v3/include/bits/version.h4
-rw-r--r--libstdc++-v3/testsuite/24_iterators/indirect_callable/p2609r3.cc27
-rw-r--r--libstdc++-v3/testsuite/std/ranges/version_c++23.cc2
5 files changed, 77 insertions, 19 deletions
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index ce0b8a1..9306b7b 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -552,9 +552,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
concept indirectly_readable
= __detail::__indirectly_readable_impl<remove_cvref_t<_In>>;
+ namespace __detail
+ {
+ template<typename _Tp>
+ struct __indirect_value
+ { using type = iter_value_t<_Tp>&; };
+
+ // __indirect_value<projected<_Iter, _Proj>> is defined later.
+ } // namespace __detail
+
+ template<typename _Tp>
+ using __indirect_value_t = typename __detail::__indirect_value<_Tp>::type;
+
template<indirectly_readable _Tp>
using iter_common_reference_t
- = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>;
+ = common_reference_t<iter_reference_t<_Tp>, __indirect_value_t<_Tp>>;
/// Requirements for writing a value into an iterator's referenced object.
template<typename _Out, typename _Tp>
@@ -710,24 +722,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Fn, typename _Iter>
concept indirectly_unary_invocable = indirectly_readable<_Iter>
- && copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&>
+ && copy_constructible<_Fn> && invocable<_Fn&, __indirect_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>&>,
+ && common_reference_with<invoke_result_t<_Fn&, __indirect_value_t<_Iter>>,
invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
template<typename _Fn, typename _Iter>
concept indirectly_regular_unary_invocable = indirectly_readable<_Iter>
&& copy_constructible<_Fn>
- && regular_invocable<_Fn&, iter_value_t<_Iter>&>
+ && regular_invocable<_Fn&, __indirect_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>&>,
+ && common_reference_with<invoke_result_t<_Fn&, __indirect_value_t<_Iter>>,
invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
template<typename _Fn, typename _Iter>
concept indirect_unary_predicate = indirectly_readable<_Iter>
- && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&>
+ && copy_constructible<_Fn> && predicate<_Fn&, __indirect_value_t<_Iter>>
&& predicate<_Fn&, iter_reference_t<_Iter>>
&& predicate<_Fn&, iter_common_reference_t<_Iter>>;
@@ -735,9 +747,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
concept indirect_binary_predicate
= indirectly_readable<_I1> && indirectly_readable<_I2>
&& copy_constructible<_Fn>
- && predicate<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
- && predicate<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
- && predicate<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
+ && predicate<_Fn&, __indirect_value_t<_I1>, __indirect_value_t<_I2>>
+ && predicate<_Fn&, __indirect_value_t<_I1>, iter_reference_t<_I2>>
+ && predicate<_Fn&, iter_reference_t<_I1>, __indirect_value_t<_I2>>
&& predicate<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
&& predicate<_Fn&, iter_common_reference_t<_I1>,
iter_common_reference_t<_I2>>;
@@ -746,9 +758,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
concept indirect_equivalence_relation
= indirectly_readable<_I1> && indirectly_readable<_I2>
&& copy_constructible<_Fn>
- && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
- && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
- && equivalence_relation<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
+ && equivalence_relation<_Fn&, __indirect_value_t<_I1>, __indirect_value_t<_I2>>
+ && equivalence_relation<_Fn&, __indirect_value_t<_I1>, iter_reference_t<_I2>>
+ && equivalence_relation<_Fn&, iter_reference_t<_I1>, __indirect_value_t<_I2>>
&& equivalence_relation<_Fn&, iter_reference_t<_I1>,
iter_reference_t<_I2>>
&& equivalence_relation<_Fn&, iter_common_reference_t<_I1>,
@@ -758,9 +770,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
concept indirect_strict_weak_order
= indirectly_readable<_I1> && indirectly_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&, __indirect_value_t<_I1>, __indirect_value_t<_I2>>
+ && strict_weak_order<_Fn&, __indirect_value_t<_I1>, iter_reference_t<_I2>>
+ && strict_weak_order<_Fn&, iter_reference_t<_I1>, __indirect_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>>;
@@ -779,6 +791,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>;
indirect_result_t<_Proj&, _Iter> operator*() const; // not defined
+
+ // These are used to identify and obtain the template arguments of a
+ // specialization of the 'projected' alias template below.
+ using __projected_Iter = _Iter;
+ using __projected_Proj = _Proj;
};
};
@@ -790,6 +807,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>;
using difference_type = iter_difference_t<_Iter>;
indirect_result_t<_Proj&, _Iter> operator*() const; // not defined
+
+ using __projected_Iter = _Iter;
+ using __projected_Proj = _Proj;
};
};
} // namespace __detail
@@ -799,6 +819,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
indirectly_regular_unary_invocable<_Iter> _Proj>
using projected = typename __detail::__projected<_Iter, _Proj>::__type;
+ // Matches specializations of the 'projected' alias template.
+ template<typename _Tp>
+ requires same_as<_Tp, projected<typename _Tp::__projected_Iter,
+ typename _Tp::__projected_Proj>>
+ struct __detail::__indirect_value<_Tp>
+ {
+ using _Iter = typename _Tp::__projected_Iter;
+ using _Proj = typename _Tp::__projected_Proj;
+ using type = invoke_result_t<_Proj&, __indirect_value_t<_Iter>>;
+ };
+
// [alg.req], common algorithm requirements
/// [alg.req.ind.move], concept `indirectly_movable`
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 6791c6f..ea82c6f 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1072,7 +1072,7 @@ ftms = {
ftms = {
name = ranges;
values = {
- v = 202211;
+ v = 202302;
cxxmin = 23;
extra_cond = "__glibcxx_concepts";
};
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 0b78cb9..981f0b7 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1205,9 +1205,9 @@
#if !defined(__cpp_lib_ranges)
# if (__cplusplus >= 202100L) && (__glibcxx_concepts)
-# define __glibcxx_ranges 202211L
+# define __glibcxx_ranges 202302L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges)
-# define __cpp_lib_ranges 202211L
+# define __cpp_lib_ranges 202302L
# endif
# elif (__cplusplus >= 202002L) && (__glibcxx_concepts)
# define __glibcxx_ranges 202110L
diff --git a/libstdc++-v3/testsuite/24_iterators/indirect_callable/p2609r3.cc b/libstdc++-v3/testsuite/24_iterators/indirect_callable/p2609r3.cc
new file mode 100644
index 0000000..fe7839d
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/indirect_callable/p2609r3.cc
@@ -0,0 +1,27 @@
+// Verify the P2609R3 "Relaxing Ranges Just A Smidge" changes.
+// { dg-do compile { target c++20 } }
+
+#include <iterator>
+#include <algorithm>
+#include <memory>
+#include <ranges>
+
+int
+main()
+{
+ auto v = std::views::iota(0, 5);
+ auto proj = [](int v) { return std::make_unique<int>(v); };
+ using it = std::projected<std::ranges::iterator_t<decltype(v)>, decltype(proj)>;
+
+ auto f = [](auto) { return false; };
+ static_assert(std::indirectly_unary_invocable<decltype(f), it>);
+ static_assert(std::indirectly_regular_unary_invocable<decltype(f), it>);
+ static_assert(std::indirect_unary_predicate<decltype(f), it>);
+
+ auto g = [](auto, auto) { return false; };
+ static_assert(std::indirect_binary_predicate<decltype(g), it, it>);
+ static_assert(std::indirect_equivalence_relation<decltype(g), it, it>);
+ static_assert(std::indirect_strict_weak_order<decltype(g), it, it>);
+
+ std::ranges::for_each(v, f, proj);
+}
diff --git a/libstdc++-v3/testsuite/std/ranges/version_c++23.cc b/libstdc++-v3/testsuite/std/ranges/version_c++23.cc
index d475d3d..0187115 100644
--- a/libstdc++-v3/testsuite/std/ranges/version_c++23.cc
+++ b/libstdc++-v3/testsuite/std/ranges/version_c++23.cc
@@ -4,7 +4,7 @@
#include <version>
#if __STDC_HOSTED__
-# if __cpp_lib_ranges != 202211L
+# if __cpp_lib_ranges != 202302L
# error "Feature-test macro __cpp_lib_ranges has wrong value in <version>"
# endif
#endif