Lud*_*ert 2 c++ operator-overloading c++20 std-ranges
在 MyRect.h 中:
\nstruct 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);\nRun Code Online (Sandbox Code Playgroud)\n在 MyRect.cpp 中:
\nbool 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}\nRun 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()) ;\nRun Code Online (Sandbox Code Playgroud)\n使用 g++10 (C++20) binpack.cpp 进行编译。没有问题。
\n如果我更改为:
\nranges::sort(selected_neighboors);\nRun 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\nRun Code Online (Sandbox Code Playgroud)\n
ranges::sort默认用于ranges::less比较MyRect,其定义在[range.cmp]中:
\n\nRun Code Online (Sandbox Code Playgroud)\nstruct 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
\n\nRun Code Online (Sandbox Code Playgroud)\ntemplate<class T, class U>\n constexpr bool operator()(T&& t, U&& u) const;\n约束:
\nT并U满足totally_\xc2\xadordered_\xc2\xadwith。
它operator()要求T并且U必须满足total_ordered_with:
template<class T, class U>\n concept totally_\xc2\xadordered_\xc2\xadwith =\n totally_\xc2\xadordered<T> && totally_\xc2\xadordered<U> && ...\nRun Code Online (Sandbox Code Playgroud)\n这要求T必须满足totally_ordered:
template<class T>\n concept totally_\xc2\xadordered =\n equality_\xc2\xadcomparable<T> && partially-ordered-with<T, T>;\nRun Code Online (Sandbox Code Playgroud)\n这要求T必须满足partially-ordered-with:
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 };\nRun Code Online (Sandbox Code Playgroud)\n这要求完整的关系运算符集必须是格式良好的。
\n由于您没有为 定义合适的operator>,operator<=和其他关系运算符MyRect,因此不满足约束。
您可以添加operator<=>toMyRect使其成为totally_ordered,或使用 unconstrainedstd::less进行比较:
std::vector<MyRect> selected_neighboors;\nranges::sort(selected_neighboors, std::less{});\nRun Code Online (Sandbox Code Playgroud)\n