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

Nathaniel Shead <nshead at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |nshead at gcc dot gnu.org

--- Comment #6 from Nathaniel Shead <nshead at gcc dot gnu.org> ---
With the above patch, the original std::ranges::find_if call now gives the
following diagnostic (using experimental-nesting=yes for clarity):

$ g++-16 -std=c++20 -S -fdiagnostics-set-output=text:experimental-nesting=yes
test.cpp
test.cpp: In function ‘int main()’:
test.cpp:8:24: error: no match for call to ‘(const std::ranges::__find_if_fn)
(std::vector<std::unique_ptr<int> >&, main()::<lambda(auto:10)>)’
    8 |   std::ranges::find_if (v, [] (auto i) { return !!i; });
      |   ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/wreien/.local/include/c++/16.0.0/tuple:46,
                 from
/home/wreien/.local/include/c++/16.0.0/bits/uses_allocator_args.h:41,
                 from
/home/wreien/.local/include/c++/16.0.0/bits/memory_resource.h:43,
                 from /home/wreien/.local/include/c++/16.0.0/vector:91,
                 from test.cpp:1:
  • there are 2 candidates
    /home/wreien/.local/include/c++/16.0.0/bits/ranges_util.h:550:10:
      550 |   struct __find_if_fn
          |          ^~~~~~~~~~~~
    • candidate 1: ‘template<class _Iter, class _Sent, class _Proj, class
_Pred>  requires (input_iterator<_Iter>) && (sentinel_for<_Sent, _Iter>) &&
(indirect_unary_predicate<_Pred, typename std::__detail::__projected<_Iter,
_Proj>::__type>) constexpr _Iter std::ranges::__find_if_fn::operator()(_Iter,
_Sent, _Pred, _Proj) const’
      /home/wreien/.local/include/c++/16.0.0/bits/ranges_util.h:556:7:
        556 |       operator()(_Iter __first, _Sent __last,
            |       ^~~~~~~~
      • candidate expects 3 arguments, 2 provided
    • candidate 2: ‘template<class _Range, class _Proj, class _Pred>  requires
(input_range<_Range>) && (indirect_unary_predicate<_Pred, typename
std::__detail::__projected<decltype(std::ranges::__access::__begin((declval<_Container&>)())),
_Proj>::__type>) constexpr std::ranges::borrowed_iterator_t<_Range>
std::ranges::__find_if_fn::operator()(_Range&&, _Pred, _Proj) const’
      /home/wreien/.local/include/c++/16.0.0/bits/ranges_util.h:569:7:
        569 |       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {})
const
            |       ^~~~~~~~
      • template argument deduction/substitution failed:
        • constraints not satisfied
In file included from /home/wreien/.local/include/c++/16.0.0/compare:43,
                 from
/home/wreien/.local/include/c++/16.0.0/bits/stl_pair.h:65,
                 from
/home/wreien/.local/include/c++/16.0.0/bits/stl_algobase.h:64,
                 from /home/wreien/.local/include/c++/16.0.0/vector:64:
          • /home/wreien/.local/include/c++/16.0.0/concepts: In substitution of
‘template<class _Range, class _Proj, class _Pred>  requires
(input_range<_Range>) && (indirect_unary_predicate<_Pred, typename
std::__detail::__projected<decltype(std::ranges::__access::__begin((declval<_Container&>)())),
_Proj>::__type>) constexpr std::ranges::borrowed_iterator_t<_Range>
std::ranges::__find_if_fn::operator()(_Range&&, _Pred, _Proj) const [with
_Range = std::vector<std::unique_ptr<int> >&; _Proj = std::identity; _Pred =
main()::<lambda(auto:10)>]’:
          • required from here
            test.cpp:8:24:
                8 |   std::ranges::find_if (v, [] (auto i) { return !!i; });
                  |   ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          • required for the satisfaction of ‘invocable<_Fn, _Args ...>’ [with
_Fn = main::._anon_122&; _Args = {std::unique_ptr<int, std::default_delete<int>
>&}]
            /home/wreien/.local/include/c++/16.0.0/concepts:362:13:
              362 |     concept invocable = is_invocable_v<_Fn, _Args...>;
                  |             ^~~~~~~~~
          • required for the satisfaction of ‘regular_invocable<_Fn, _Args
...>’ [with _Fn = main::._anon_122&; _Args = {std::unique_ptr<int,
std::default_delete<int> >&}]
            /home/wreien/.local/include/c++/16.0.0/concepts:366:13:
              366 |     concept regular_invocable = invocable<_Fn, _Args...>;
                  |             ^~~~~~~~~~~~~~~~~
          • required for the satisfaction of ‘predicate<_Fn&, typename
std::__detail::__indirect_value<_Iter>::type>’ [with _Fn = main::._anon_122;
_Iter =
std::__detail::__projected<__gnu_cxx::__normal_iterator<std::unique_ptr<int,
std::default_delete<int> >*, std::vector<std::unique_ptr<int,
std::default_delete<int> >, std::allocator<std::unique_ptr<int,
std::default_delete<int> > > > >, std::identity>::__type]
            /home/wreien/.local/include/c++/16.0.0/concepts:370:13:
              370 |     concept predicate = regular_invocable<_Fn, _Args...>
                  |             ^~~~~~~~~
          • required for the satisfaction of ‘indirect_unary_predicate<_Pred,
std::projected<decltype
(std::ranges::__access::__begin(declval<_Container&>())), _Proj> >’ [with _Pred
= main::._anon_122; _Range = std::vector<std::unique_ptr<int,
std::default_delete<int> >, std::allocator<std::unique_ptr<int,
std::default_delete<int> > > >&; _Proj = std::identity]
           
/home/wreien/.local/include/c++/16.0.0/bits/iterator_concepts.h:731:13:
              731 |     concept indirect_unary_predicate =
indirectly_readable<_Iter>
                  |             ^~~~~~~~~~~~~~~~~~~~~~~~
          • the expression ‘is_invocable_v<_Fn, _Args ...> [with _Fn =
main::._anon_122&; _Args = {std::unique_ptr<int, std::default_delete<int> >&}]’
evaluated to ‘false’
            /home/wreien/.local/include/c++/16.0.0/concepts:362:25:
              362 |     concept invocable = is_invocable_v<_Fn, _Args...>;
                  |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          • ‘main()::<lambda(auto:10)>&’ is not invocable by
‘std::unique_ptr<int>&’, because
          • error: use of deleted function ‘std::unique_ptr<_Tp,
_Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp =
std::default_delete<int>]’
In file included from /home/wreien/.local/include/c++/16.0.0/memory:80,
                 from test.cpp:2:
          • declared here
            /home/wreien/.local/include/c++/16.0.0/bits/unique_ptr.h:525:7:
              525 |       unique_ptr(const unique_ptr&) = delete;
                  |       ^~~~~~~~~~
          • use ‘-fdiagnostics-all-candidates’ to display considered candidates
            /home/wreien/.local/include/c++/16.0.0/concepts:362:25:
              362 |     concept invocable = is_invocable_v<_Fn, _Args...>;
                  |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          • initializing argument 1 of ‘main()::<lambda(auto:10)> [with auto:10
= std::unique_ptr<int>]’
            test.cpp:8:28:
                8 |   std::ranges::find_if (v, [] (auto i) { return !!i; });
                  |        

This now includes the additional detail of:

‘main()::<lambda(auto:10)>&’ is not invocable by ‘std::unique_ptr<int>&’,
because
error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const
std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’

which at least now says exactly what went wrong.  The message can still be
improved a lot though; there's a fair bit of extra noise here, still, and the
ordering of the constraints backtrace IMO is confusing.

Reply via email to