range::sort 无法编译

Lud*_*ert 2 c++ operator-overloading c++20 std-ranges

在 MyRect.h 中:

\n
struct MyRect\n{\n    MyRect(std::initializer_list<int> i);\n    MyRect();\n    int16_t m_left=0, m_right=0, m_top=0, m_bottom=0 ;\n    int16_t no_sequence=0 ;\n    int16_t i=-1 ;\n    bool selected=false ;\n} ;\n\nbool operator==(const MyRect& r1, const MyRect& r2) ;\nbool operator<(const MyRect& r1, const MyRect& r2);\n
Run Code Online (Sandbox Code Playgroud)\n

在 MyRect.cpp 中:

\n
bool operator==(const MyRect& r1, const MyRect& r2)\n{\n    return r1.m_left==r2.m_left &&\n        r1.m_right==r2.m_right &&\n        r1.m_top==r2.m_top &&\n        r1.m_bottom==r2.m_bottom ;\n}\nbool operator<(const MyRect& r1, const MyRect& r2)\n{\n    if (r1.m_left != r2.m_left)\n        return r1.m_left < r2.m_left;\n    if (r1.m_right != r2.m_right)\n        return r1.m_right < r2.m_right;\n    if (r1.m_top != r2.m_top)\n        return r1.m_top < r2.m_top;\n    if (r1.m_bottom != r2.m_bottom)\n        return r1.m_bottom < r2.m_bottom;\n    //if we got here, r1==r2\n    return false;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在 binpack.cpp 中:

\n
#include "MyRect.h"\n...\nvector<MyRect> selected_neighboors ;\nstd::sort(selected_neighboors.begin(), selected_neighboors.end()) ;\n
Run Code Online (Sandbox Code Playgroud)\n

使用 g++10 (C++20) binpack.cpp 进行编译。没有问题。

\n

如果我更改为:

\n
ranges::sort(selected_neighboors);\n
Run Code Online (Sandbox Code Playgroud)\n

它不再编译。

\n
/home/edouda/linkedboxdraw/binpack.cpp: In function \xe2\x80\x98void collapse(std::vector<MyRect>&)\xe2\x80\x99:\n/home/edouda/linkedboxdraw/binpack.cpp:617:36: error: no match for call to \xe2\x80\x98(const std::ranges::__sort_fn) (std::vector<MyRect>&)\xe2\x80\x99\n  617 |    ranges::sort(selected_neighboors) ;\n      |                                    ^\nIn file included from /usr/include/c++/10/algorithm:64,\n                 from /home/edouda/linkedboxdraw/MyRect.h:14,\n                 from /home/edouda/linkedboxdraw/binpack.h:12,\n                 from /home/edouda/linkedboxdraw/binpack.cpp:8:\n/usr/include/c++/10/bits/ranges_algo.h:2019:7: note: candidate: \xe2\x80\x98template<class _Iter, class _Sent, class _Comp, class _Proj>  requires (random_access_iterator<_Iter>) && (sentinel_for<_Sent, _Iter>) && (sortable<_Iter, _Comp, _Proj>) constexpr _Iter std::ranges::__sort_fn::operator()(_Iter, _Sent, _Comp, _Proj) const\xe2\x80\x99\n 2019 |       operator()(_Iter __first, _Sent __last,\n      |       ^~~~~~~~\n/usr/include/c++/10/bits/ranges_algo.h:2019:7: note:   template argument deduction/substitution failed:\n/home/edouda/linkedboxdraw/binpack.cpp:617:36: note:   candidate expects 4 arguments, 1 provided\n  617 |    ranges::sort(selected_neighboors) ;\n      |                                    ^\nIn file included from /usr/include/c++/10/algorithm:64,\n                 from /home/edouda/linkedboxdraw/MyRect.h:14,\n                 from /home/edouda/linkedboxdraw/binpack.h:12,\n                 from /home/edouda/linkedboxdraw/binpack.cpp:8:\n/usr/include/c++/10/bits/ranges_algo.h:2032:7: note: candidate: \xe2\x80\x98constexpr std::ranges::borrowed_iterator_t<_Range> std::ranges::__sort_fn::operator()(_Range&&, _Comp, _Proj) const [with _Range = std::vector<MyRect>&; _Comp = std::ranges::less; _Proj = std::identity; std::ranges::borrowed_iterator_t<_Range> = std::conditional<true, __gnu_cxx::__normal_iterator<MyRect*, std::vector<MyRect> >, std::ranges::dangling>::type]\xe2\x80\x99\n 2032 |       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const\n      |       ^~~~~~~~\n/usr/include/c++/10/bits/ranges_algo.h:2032:7: note: constraints not satisfied\nIn file included from /usr/include/c++/10/compare:39,\n                 from /usr/include/c++/10/bits/stl_pair.h:65,\n                 from /usr/include/c++/10/bits/stl_algobase.h:64,\n                 from /usr/include/c++/10/vector:60,\n                 from /home/edouda/linkedboxdraw/MyRect.h:12,\n                 from /home/edouda/linkedboxdraw/binpack.h:12,\n                 from /home/edouda/linkedboxdraw/binpack.cpp:8:\n/usr/include/c++/10/concepts: In instantiation of \xe2\x80\x98constexpr std::ranges::borrowed_iterator_t<_Range> std::ranges::__sort_fn::operator()(_Range&&, _Comp, _Proj) const [with _Range = std::vector<MyRect>&; _Comp = std::ranges::less; _Proj = std::identity; std::ranges::borrowed_iterator_t<_Range> = std::conditional<true, __gnu_cxx::__normal_iterator<MyRect*, std::vector<MyRect> >, std::ranges::dangling>::type]\xe2\x80\x99:\n/home/edouda/linkedboxdraw/binpack.cpp:617:36:   required from here\n/usr/include/c++/10/concepts:338:13:   required for the satisfaction of \xe2\x80\x98invocable<_Fn, _Args ...>\xe2\x80\x99 [with _Fn = std::ranges::less&; _Args = {value_type<MyRect>&, value_type<MyRect>&}]\n/usr/include/c++/10/concepts:342:13:   required for the satisfaction of \xe2\x80\x98regular_invocable<_Fn, _Args ...>\xe2\x80\x99 [with _Fn = std::ranges::less&; _Args = {value_type<MyRect>&, value_type<MyRect>&}]\n/usr/include/c++/10/concepts:346:13:   required for the satisfaction of \xe2\x80\x98predicate<_Rel, _Tp, _Tp>\xe2\x80\x99 [with _Rel = std::ranges::less&; _Tp = MyRect&]\n/usr/include/c++/10/concepts:351:13:   required for the satisfaction of \xe2\x80\x98relation<_Rel, _Tp, _Up>\xe2\x80\x99 [with _Rel = std::ranges::less&; _Tp = MyRect&; _Up = MyRect&]\n/usr/include/c++/10/concepts:361:13:   required for the satisfaction of \xe2\x80\x98strict_weak_order<_Fn&, typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Arg>::type>::type, std::indirectly_readable_traits<typename std::remove_cv<typename std::remove_reference<_Arg>::type>::type> >::type::value_type&, typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Arg>::type>::type, std::indirectly_readable_traits<typename std::remove_cv<typename std::remove_reference<_Arg>::type>::type> >::type::value_type&>\xe2\x80\x99 [with _Fn = std::ranges::less; _Arg = std::projected<__gnu_cxx::__normal_iterator<MyRect*, std::vector<MyRect, std::allocator<MyRect> > >, std::identity>; _Arg = std::projected<__gnu_cxx::__normal_iterator<MyRect*, std::vector<MyRect, std::allocator<MyRect> > >, std::identity>]\n/usr/include/c++/10/bits/iterator_concepts.h:690:13:   required for the satisfaction of \xe2\x80\x98indirect_strict_weak_order<_Rel, std::projected<_Iter, _Proj>, std::projected<_Iter, _Proj> >\xe2\x80\x99 [with _Rel = std::ranges::less; _Iter = __gnu_cxx::__normal_iterator<MyRect*, std::vector<MyRect, std::allocator<MyRect> > >; _Proj = std::identity]\n/usr/include/c++/10/bits/iterator_concepts.h:865:13:   required for the satisfaction of \xe2\x80\x98sortable<decltype (std::__detail::__ranges_begin(declval<_Container&>())), _Comp, _Proj>\xe2\x80\x99 [with _Container = std::vector<MyRect, std::allocator<MyRect> >&; _Comp = std::ranges::less; _Proj = std::identity]\n/usr/include/c++/10/concepts:338:25: note: the expression \xe2\x80\x98is_invocable_v<_Fn, _Args ...> [with _Fn = std::ranges::less&; _Args = {value_type<MyRect>&, value_type<MyRect>&}]\xe2\x80\x99 evaluated to \xe2\x80\x98false\xe2\x80\x99\n  338 |     concept invocable = is_invocable_v<_Fn, _Args...>;\n      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nmake[2]: *** [CMakeFiles/latuile.dir/build.make:76: CMakeFiles/latuile.dir/binpack.cpp.o] Error 1\nmake[1]: *** [CMakeFiles/Makefile2:78: CMakeFiles/latuile.dir/all] Error 2\nmake: *** [Makefile:95: all] Error 2\n
Run Code Online (Sandbox Code Playgroud)\n

康桓瑋*_*康桓瑋 5

ranges::sort默认用于ranges::less比较MyRect,其定义在[range.cmp]中:

\n
\n
struct ranges::less {\n  template<class T, class U>\n    constexpr bool operator()(T&& t, U&& u) const;\n\n  using is_transparent = unspecified;\n};\n
Run Code Online (Sandbox Code Playgroud)\n
\n
\n
template<class T, class U>\n  constexpr bool operator()(T&& t, U&& u) const;\n
Run Code Online (Sandbox Code Playgroud)\n

约束TU满足totally_\xc2\xadordered_\xc2\xadwith

\n
\n

operator()要求T并且U必须满足total_ordered_with

\n
template<class T, class U>\n  concept totally_\xc2\xadordered_\xc2\xadwith =\n    totally_\xc2\xadordered<T> && totally_\xc2\xadordered<U> && ...\n
Run Code Online (Sandbox Code Playgroud)\n

这要求T必须满足totally_ordered

\n
template<class T>\n  concept totally_\xc2\xadordered =\n    equality_\xc2\xadcomparable<T> && partially-ordered-with<T, T>;\n
Run Code Online (Sandbox Code Playgroud)\n

这要求T必须满足partially-ordered-with

\n
template<class T, class U>\n  concept partially-ordered-with =      // exposition only\n    requires(const remove_reference_t<T>& t, const remove_reference_t<U>& u) {\n      { t <  u } -> boolean-testable;\n      { t >  u } -> boolean-testable;\n      { t <= u } -> boolean-testable;\n      { t >= u } -> boolean-testable;\n      { u <  t } -> boolean-testable;\n      { u >  t } -> boolean-testable;\n      { u <= t } -> boolean-testable;\n      { u >= t } -> boolean-testable;\n    };\n
Run Code Online (Sandbox Code Playgroud)\n

这要求完整的关系运算符集必须是格式良好的。

\n

由于您没有为 定义合适的operator>,operator<=和其他关系运算符MyRect,因此不满足约束。

\n

您可以添加operator<=>toMyRect使其成为totally_ordered,或使用 unconstrainedstd::less进行比较:

\n
std::vector<MyRect> selected_neighboors;\nranges::sort(selected_neighboors, std::less{});\n
Run Code Online (Sandbox Code Playgroud)\n