[libcxx-commits] [libcxx] [libc++][RFC] Rewrite CPOs with resolver functions (PR #209104)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Oct 17 03:21:51 PDT 2026
================
@@ -49,18 +51,47 @@ concept __ranges_begin_invocable = !__member_data<_Tp> && __can_borrow<_Tp> && r
{ ranges::begin(__t) } -> contiguous_iterator;
};
-struct __fn {
- template <__member_data _Tp>
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const noexcept(noexcept(__t.data())) {
- return __t.data();
- }
-
- template <__ranges_begin_invocable _Tp>
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
- noexcept(noexcept(std::to_address(ranges::begin(__t)))) {
- return std::to_address(ranges::begin(__t));
+struct __fn : _CPO<[]<class _Ep> consteval noexcept {
+ // [range.prim.data]
+
+ // Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E. Then:
+ using _Tp = remove_reference_t<_Ep>;
+
+ // If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges::data(E) is ill-formed.
+ if constexpr (is_rvalue_reference_v<_Ep> && !enable_borrowed_range<remove_cv_t<_Tp>>) {
+ return;
+
+ // Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type,
+ // ranges::data(E) is ill-formed with no diagnostic required.
+ } else if constexpr (is_array_v<_Tp>) {
+ if constexpr (!requires { sizeof(remove_all_extents_t<_Tp>); }) {
+ return;
+ } else {
+ // This is inlined from ranges::begin
+ return [](_Ep __v) noexcept { return __v + 0; };
+ }
+
+ // Otherwise, if auto(t.data()) is a valid expression of pointer to object type,
+ // ranges::data(E) is expression-equivalent to auto(t.data()).
+ } else if constexpr (requires(_Tp& __t) {
+ { _LIBCPP_AUTO_CAST(__t.data()) } -> __ptr_to_object;
+ }) {
+ return [](_Ep __v) noexcept(noexcept(_LIBCPP_AUTO_CAST(__v.data()))) { return _LIBCPP_AUTO_CAST(__v.data()); };
+
+ // Otherwise, if ranges::begin(t) is a valid expression whose type models contiguous_iterator,
+ // ranges::data(E) is expression-equivalent to to_address(ranges::begin(t)).
+ } else if constexpr (requires(_Tp& __t) {
+ { ranges::begin(__t) } -> contiguous_iterator;
+ }) {
+ return [](_Ep __v) noexcept(noexcept(std::to_address(ranges::begin(__v)))) {
+ return std::to_address(ranges::begin(__v));
+ };
+
+ // Otherwise, ranges::data(E) is ill-formed.
+ } else {
+ return;
----------------
huixie90 wrote:
should we return a diagnostic here? otherwise i would expect the error message is something like void does not have operator()
https://github.com/llvm/llvm-project/pull/209104
More information about the libcxx-commits
mailing list