The code:
#include <algorithm>
#include <ranges>
#include <vector>
#include <tuple>
#include <generator>
#include <cstdio>
#include <iostream>
using namespace std;
struct Edge{int from, to;auto operator<=>(const Edge&) const =default;};
enum NeighborDegree{FIRST_NEIGHBOR_DEGREE,SECOND_NEIGHBOR_DEGREE,THIRD_NEIGHBOR_DEGREE};
int main()
{
const vector<Edge> links;
vector<tuple<Edge,NeighborDegree> > multi_degree_neighbors, inter;
ranges::set_intersection(multi_degree_neighbors, multi_degree_neighbors, back_inserter(inter), {}, {}, {});
auto prj1=[](const auto& neighbor)->Edge{const auto& [e,degree]=neighbor;return e;};
ranges::set_intersection(multi_degree_neighbors, links, back_inserter(inter), {}, prj1, {});
}
The error:
prog.cc: In function 'int main()':
prog.cc:17:29: error: no match for call to '(const std::ranges::__set_intersection_fn) (std::vector<std::tuple<Edge, NeighborDegree> >&, std::vector<std::tuple<Edge, NeighborDegree> >&, std::back_insert_iterator<std::vector<std::tuple<Edge, NeighborDegree> > >, <brace-enclosed initializer list>, <brace-enclosed initializer list>, <brace-enclosed initializer list>)'
17 | ranges::set_intersection(multi_degree_neighbors, multi_degree_neighbors, back_inserter(inter), {}, {}, {});
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /opt/wandbox/gcc-head/include/c++/16.0.0/algorithm:65,
from prog.cc:1:
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2751:10: note: there are 2 candidates
2751 | struct __set_intersection_fn
| ^~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2759:7: note: candidate 1: 'template<class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Out, class _Comp, class _Proj1, class _Proj2> requires (input_iterator<_Iter1>) && (sentinel_for<_Sent1, _Iter1>) && (input_iterator<_Iter2>) && (sentinel_for<_Sent2, _Iter2>) && (weakly_incrementable<_Out>) && (mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>) constexpr std::ranges::set_intersection_result<_Iter1, _Iter2, _Out> std::ranges::__set_intersection_fn::operator()(_Iter1, _Sent1, _Iter2, _Sent2, _Out, _Comp, _Proj1, _Proj2) const'
2759 | operator()(_Iter1 __first1, _Sent1 __last1,
| ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2759:7: note: template argument deduction/substitution failed:
prog.cc:17:29: note: couldn't deduce template parameter '_Sent2'
17 | ranges::set_intersection(multi_degree_neighbors, multi_degree_neighbors, back_inserter(inter), {}, {}, {});
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2793:7: note: candidate 2: 'template<class _Range1, class _Range2, class _Out, class _Comp, class _Proj1, class _Proj2> requires (input_range<_Range1>) && (input_range<_Range2>) && (weakly_incrementable<_Out>) && (mergeable<decltype(std::ranges::__access::__begin((declval<_Container&>)())), decltype(std::ranges::__access::__begin((declval<_Range2&>)())), _Out, _Comp, _Proj1, _Proj2>) constexpr std::ranges::set_intersection_result<std::ranges::borrowed_iterator_t<_Range>, std::ranges::borrowed_iterator_t<_Range2>, _Out> std::ranges::__set_intersection_fn::operator()(_Range1&&, _Range2&&, _Out, _Comp, _Proj1, _Proj2) const'
2793 | operator()(_Range1&& __r1, _Range2&& __r2, _Out __result,
| ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2793:7: note: template argument deduction/substitution failed:
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2793:7: note: constraints not satisfied
In file included from /opt/wandbox/gcc-head/include/c++/16.0.0/compare:42,
from /opt/wandbox/gcc-head/include/c++/16.0.0/bits/stl_pair.h:65,
from /opt/wandbox/gcc-head/include/c++/16.0.0/bits/stl_algobase.h:64,
from /opt/wandbox/gcc-head/include/c++/16.0.0/algorithm:62:
/opt/wandbox/gcc-head/include/c++/16.0.0/concepts: In substitution of 'template<class _Range1, class _Range2, class _Out, class _Comp, class _Proj1, class _Proj2> requires (input_range<_Range1>) && (input_range<_Range2>) && (weakly_incrementable<_Out>) && (mergeable<decltype(std::ranges::__access::__begin((declval<_Container&>)())), decltype(std::ranges::__access::__begin((declval<_Range2&>)())), _Out, _Comp, _Proj1, _Proj2>) constexpr std::ranges::set_intersection_result<std::ranges::borrowed_iterator_t<_Range>, std::ranges::borrowed_iterator_t<_Range2>, _Out> std::ranges::__set_intersection_fn::operator()(_Range1&&, _Range2&&, _Out, _Comp, _Proj1, _Proj2) const [with _Range1 = std::vector<std::tuple<Edge, NeighborDegree> >&; _Range2 = std::vector<std::tuple<Edge, NeighborDegree> >&; _Out = std::back_insert_iterator<std::vector<std::tuple<Edge, NeighborDegree> > >; _Comp = std::ranges::less; _Proj1 = std::identity; _Proj2 = std::identity]':
prog.cc:17:29: required from here
17 | ranges::set_intersection(multi_degree_neighbors, multi_degree_neighbors, back_inserter(inter), {}, {}, {});
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/concepts:362:13: required for the satisfaction of 'invocable<_Fn, _Args ...>' [with _Fn = std::ranges::less&; _Args = {std::tuple<Edge, NeighborDegree>&, std::tuple<Edge, NeighborDegree>&}]
/opt/wandbox/gcc-head/include/c++/16.0.0/concepts:366:13: required for the satisfaction of 'regular_invocable<_Fn, _Args ...>' [with _Fn = std::ranges::less&; _Args = {std::tuple<Edge, NeighborDegree>&, std::tuple<Edge, NeighborDegree>&}]
/opt/wandbox/gcc-head/include/c++/16.0.0/concepts:370:13: required for the satisfaction of 'predicate<_Rel, _Tp, _Tp>' [with _Rel = std::ranges::less&; _Tp = std::tuple<Edge, NeighborDegree>&]
/opt/wandbox/gcc-head/include/c++/16.0.0/concepts:375:13: required for the satisfaction of 'relation<_Rel, _Tp, _Up>' [with _Rel = std::ranges::less&; _Tp = std::tuple<Edge, NeighborDegree>&; _Up = std::tuple<Edge, NeighborDegree>&]
/opt/wandbox/gcc-head/include/c++/16.0.0/concepts:385:13: required for the satisfaction of 'strict_weak_order<_Fn&, typename std::__detail::__indirect_value<_Iter>::type, typename std::__detail::__indirect_value<_I2>::type>' [with _Fn = std::ranges::less; _I1 = std::__detail::__projected<__gnu_cxx::__normal_iterator<std::tuple<Edge, NeighborDegree>*, std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > > >, std::identity>::__type; _I2 = std::__detail::__projected<__gnu_cxx::__normal_iterator<std::tuple<Edge, NeighborDegree>*, std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > > >, std::identity>::__type]
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h:789:13: required for the satisfaction of 'indirect_strict_weak_order<_Rel, std::projected<_I1, _P1>, std::projected<_I2, _P2> >' [with _Rel = std::ranges::less; _I1 = __gnu_cxx::__normal_iterator<std::tuple<Edge, NeighborDegree>*, std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > > >; _P1 = std::identity; _I2 = __gnu_cxx::__normal_iterator<std::tuple<Edge, NeighborDegree>*, std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > > >; _P2 = std::identity]
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h:998:13: required for the satisfaction of 'mergeable<decltype (std::ranges::__access::__begin(declval<_Container&>())), decltype (std::ranges::__access::__begin(declval<_Range2&>())), _Out, _Comp, _Proj1, _Proj2>' [with _Range1 = std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > >&; _Range2 = std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > >&; _Out = std::back_insert_iterator<std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > > >; _Comp = std::ranges::less; _Proj1 = std::identity; _Proj2 = std::identity]
/opt/wandbox/gcc-head/include/c++/16.0.0/concepts:362:25: note: the expression 'is_invocable_v<_Fn, _Args ...> [with _Fn = std::ranges::less&; _Args = {std::tuple<Edge, NeighborDegree>&, std::tuple<Edge, NeighborDegree>&}]' evaluated to 'false'
362 | concept invocable = is_invocable_v<_Fn, _Args...>;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:19:29: error: no match for call to '(const std::ranges::__set_intersection_fn) (std::vector<std::tuple<Edge, NeighborDegree> >&, const std::vector<Edge>&, std::back_insert_iterator<std::vector<std::tuple<Edge, NeighborDegree> > >, <brace-enclosed initializer list>, main()::<lambda(const auto:58&)>&, <brace-enclosed initializer list>)'
19 | ranges::set_intersection(multi_degree_neighbors, links, back_inserter(inter), {}, prj1, {});
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2751:10: note: there are 2 candidates
2751 | struct __set_intersection_fn
| ^~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2759:7: note: candidate 1: 'template<class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Out, class _Comp, class _Proj1, class _Proj2> requires (input_iterator<_Iter1>) && (sentinel_for<_Sent1, _Iter1>) && (input_iterator<_Iter2>) && (sentinel_for<_Sent2, _Iter2>) && (weakly_incrementable<_Out>) && (mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>) constexpr std::ranges::set_intersection_result<_Iter1, _Iter2, _Out> std::ranges::__set_intersection_fn::operator()(_Iter1, _Sent1, _Iter2, _Sent2, _Out, _Comp, _Proj1, _Proj2) const'
2759 | operator()(_Iter1 __first1, _Sent1 __last1,
| ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2759:7: note: template argument deduction/substitution failed:
prog.cc:19:29: note: couldn't deduce template parameter '_Sent2'
19 | ranges::set_intersection(multi_degree_neighbors, links, back_inserter(inter), {}, prj1, {});
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2793:7: note: candidate 2: 'template<class _Range1, class _Range2, class _Out, class _Comp, class _Proj1, class _Proj2> requires (input_range<_Range1>) && (input_range<_Range2>) && (weakly_incrementable<_Out>) && (mergeable<decltype(std::ranges::__access::__begin((declval<_Container&>)())), decltype(std::ranges::__access::__begin((declval<_Range2&>)())), _Out, _Comp, _Proj1, _Proj2>) constexpr std::ranges::set_intersection_result<std::ranges::borrowed_iterator_t<_Range>, std::ranges::borrowed_iterator_t<_Range2>, _Out> std::ranges::__set_intersection_fn::operator()(_Range1&&, _Range2&&, _Out, _Comp, _Proj1, _Proj2) const'
2793 | operator()(_Range1&& __r1, _Range2&& __r2, _Out __result,
| ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2793:7: note: template argument deduction/substitution failed:
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/ranges_algo.h:2793:7: note: constraints not satisfied
In file included from /opt/wandbox/gcc-head/include/c++/16.0.0/bits/stl_iterator_base_types.h:73,
from /opt/wandbox/gcc-head/include/c++/16.0.0/bits/stl_algobase.h:65:
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h: In substitution of 'template<class _Range1, class _Range2, class _Out, class _Comp, class _Proj1, class _Proj2> requires (input_range<_Range1>) && (input_range<_Range2>) && (weakly_incrementable<_Out>) && (mergeable<decltype(std::ranges::__access::__begin((declval<_Container&>)())), decltype(std::ranges::__access::__begin((declval<_Range2&>)())), _Out, _Comp, _Proj1, _Proj2>) constexpr std::ranges::set_intersection_result<std::ranges::borrowed_iterator_t<_Range>, std::ranges::borrowed_iterator_t<_Range2>, _Out> std::ranges::__set_intersection_fn::operator()(_Range1&&, _Range2&&, _Out, _Comp, _Proj1, _Proj2) const [with _Range1 = std::vector<std::tuple<Edge, NeighborDegree> >&; _Range2 = const std::vector<Edge>&; _Out = std::back_insert_iterator<std::vector<std::tuple<Edge, NeighborDegree> > >; _Comp = std::ranges::less; _Proj1 = main()::<lambda(const auto:58&)>; _Proj2 = std::identity]':
prog.cc:19:29: required from here
19 | ranges::set_intersection(multi_degree_neighbors, links, back_inserter(inter), {}, prj1, {});
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h:599:13: required for the satisfaction of 'indirectly_writable<_Out, std::iter_reference_t<_Iter> >' [with _Out = std::back_insert_iterator<std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > > >; _In = __gnu_cxx::__normal_iterator<const Edge*, std::vector<Edge, std::allocator<Edge> > >]
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h:874:13: required for the satisfaction of 'indirectly_copyable<_I2, _Out>' [with _I2 = __gnu_cxx::__normal_iterator<const Edge*, std::vector<Edge, std::allocator<Edge> > >; _Out = std::back_insert_iterator<std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > > >]
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h:998:13: required for the satisfaction of 'mergeable<decltype (std::ranges::__access::__begin(declval<_Container&>())), decltype (std::ranges::__access::__begin(declval<_Range2&>())), _Out, _Comp, _Proj1, _Proj2>' [with _Range1 = std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > >&; _Range2 = const std::vector<Edge, std::allocator<Edge> >&; _Out = std::back_insert_iterator<std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > > >; _Comp = std::ranges::less; _Proj1 = main::._anon_221; _Proj2 = std::identity]
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h:599:35: in requirements with '_Out&& __o', '_Tp&& __t' [with _Out = std::back_insert_iterator<std::vector<std::tuple<Edge, NeighborDegree>, std::allocator<std::tuple<Edge, NeighborDegree> > > >; _Tp = const Edge&]
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h:601:14: note: the required expression '*__o =(forward<_Tp>)(__t)' is invalid
601 | *__o = std::forward<_Tp>(__t);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h:602:34: note: the required expression '*(forward<_Out>)(__o)=(forward<_Tp>)(__t)' is invalid
602 | *std::forward<_Out>(__o) = std::forward<_Tp>(__t);
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h:604:11: note: the required expression 'const_cast<const decltype(*(declval<_Iter&>)())&&>(*__o) =(forward<_Tp>)(__t)' is invalid
603 | const_cast<const iter_reference_t<_Out>&&>(*__o)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
604 | = std::forward<_Tp>(__t);
| ^~~~~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-head/include/c++/16.0.0/bits/iterator_concepts.h:606:11: note: the required expression 'const_cast<const decltype(*(declval<_Iter&>)())&&>(*(forward<_Out>)(__o))=(forward<_Tp>)(__t)' is invalid
605 | const_cast<const iter_reference_t<_Out>&&>(*std::forward<_Out>(__o))
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
606 | = std::forward<_Tp>(__t);
| ^~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
This fails because std::ranges::set_intersection
requires the ranges be std::mergeable
, which requires elements from both input ranges be copyable into the output range. This is arguably an overconstraint for intersection (and difference), but it is required for union and symmetric difference. I imagine it was specified this way to be consistent among all these operations.
The reason one might not consider this an overconstraint is that mathematically, it shouldn't matter which input the elements are copied from, when doing set operations.