https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94049

Daniel Krügler <daniel.kruegler at googlemail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |daniel.kruegler@googlemail.
                   |                            |com

--- Comment #1 from Daniel Krügler <daniel.kruegler at googlemail dot com> ---
(In reply to Antony Polukhin from comment #0)
> Consider the following code:
> 
> #include <algorithm>
> void foo0() {
>     int t = 0;
>     std::ranges::begin(t);
> }
> 
> 
> Diagnostics for it is mostly unreadable and points to the internals of
> libstdc++ https://godbolt.org/z/c-RwuY .
> 
> This could be significantly improved. Right now the `requires` clause on
> `std::ranges::__cust_access::_Begin::operator()` duplicates the body of the
> function. So instead of such duplication all the requirements could be just
> asserted in the body:
> 
> 
> template<typename _Tp>
> constexpr auto
> operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) {
>       static_assert(__maybe_borrowed_range<_Tp>, "Not a borrowed range or
> lvalue");
>   if constexpr (is_array_v<remove_reference_t<_Tp>>) {
>     ...
>   } else if constexpr (__member_begin<_Tp>)
>     return __t.begin();
>   else if constexpr (__adl_begin<_Tp>)
>     return begin(__t);
>   else
>     static_assert(!sizeof(_Tp), "_Tp should have either a member begin() or
> an begin(_Tp&) should be in the namespace of _Tp");
> }
> 
> 
> This gives a much better diagnostics: https://godbolt.org/z/kmLGb7
> All the CPOs could be improved in that manner

Maybe, but that would make them non-conforming and they would not the advantage
of being usable in SFINAE conditions:

#include <ranges>
#include <utility>
#include <vector>

template<class T, class U = decltype(std::ranges::begin(std::declval<T&>()))>
void test(T) {} // #1

void test(...){} // #2

int main() {
    std::vector<int> v;
    test(v); // OK, calls #1
    int i = 0;
    test(i); // OK, but calls #2
}

Note that [customization.point.object] p4 says:

"The type T of a customization point object shall model invocable<const T&,
Args...> (18.7.2) when the types in Args... meet the requirements specified in
that customization point object’s definition. When the types of Args... do not
meet the customization point object’s requirements, T shall not have a function
call operator that participates in overload resolution."

Reply via email to