感谢C中的解决方案,现在我想使用std :: sort和vector在C++中实现这一点:
typedef struct { double x; double y; double alfa; } pkt;
vector< pkt > wektor;
使用push_back()填充; 比较功能:
int porownaj(const void *p_a, const void *p_b) { pkt *pkt_a = (pkt *) p_a; pkt *pkt_b = (pkt *) p_b; if (pkt_a->alfa > pkt_b->alfa) return 1; if (pkt_a->alfa < pkt_b->alfa) return -1; if (pkt_a->x > pkt_b->x) return 1; if (pkt_a->x < pkt_b->x) return -1; return 0; } sort(wektor.begin(), wektor.end(), porownaj); // this makes loads of errors on compile time
什么是纠正?在这种情况下如何正确使用std :: sort?
std::sort
采用不同的比较函数qsort
.该函数不是返回-1,0或1,而是返回一个bool
值,该值指示第一个元素是否小于第二个元素.
你有两个可能性:operator <
为你的对象实现; 在这种情况下,sort
没有第三个参数的默认调用将起作用; 或者你可以重写你的上述功能来完成同样的事情.
请注意,您必须在参数中使用强类型.
此外,最好不要在这里使用功能.而是使用函数对象.这些受益于内联.
struct pkt_less { bool operator ()(pkt const& a, pkt const& b) const { if (a.alfa < b.alfa) return true; if (a.alfa > b.alfa) return false; if (a.x < b.x) return true; if (a.x > b.x) return false; return false; } }; // Usage: sort(wektor.begin(), wektor.end(), pkt_less());
在C++中,你可以使用类似的函数boost::bind
很好地完成这项工作:
#include#include struct pkt { double x; double y; double alfa; pkt(double x, double y, double alfa) :x(x), y(y), alfa(alfa) { } }; int main() { std::vector p; p.push_back(pkt(10., 0., 20.)); p.push_back(pkt(10, 0., 30.)); p.push_back(pkt(5., 0., 40.)); std::sort(p.begin(), p.end(), boost::bind(&pkt::alfa, _1) < boost::bind(&pkt::alfa, _2) || boost::bind(&pkt::alfa, _1) == boost::bind(&pkt::alfa, _2) && boost::bind(&pkt::x, _1) < boost::bind(&pkt::x, _2)); }
如果你需要多次这样做,你也可以通过创建一个接受成员指针并进行排序的函数对象来解决问题.您可以将它重用于任何类型的对象和成员.首先你如何使用它:
int main() { /* sorting a vector of pkt */ std::vectorp; p.push_back(pkt(10., 0., 20.)); p.push_back(pkt(5., 0., 40.)); std::sort(p.begin(), p.end(), make_cmp(&pkt::x, &pkt::y)); }
这是make_cmp的代码.随意翻录(使用boost::preprocessor
):
#include#include // tweak this to increase the maximal field count #define CMP_MAX 10 #define TYPEDEF_print(z, n, unused) typedef M##n T::* m##n##_type; #define MEMBER_print(z, n, unused) m##n##_type m##n; #define CTORPARAMS_print(z, n, unused) m##n##_type m##n #define CTORINIT_print(z, n, unused) m##n(m##n) #define CMPIF_print(z, n, unused) \ if ((t0.*m##n) < (t1.*m##n)) return true; \ if ((t0.*m##n) > (t1.*m##n)) return false; \ #define PARAM_print(z, n, unused) M##n T::* m##n #define CMP_functor(z, n, unused) \ template \ struct cmp##n { \ BOOST_PP_REPEAT(n, TYPEDEF_print, ~) \ BOOST_PP_REPEAT(n, MEMBER_print, ~) \ cmp##n(BOOST_PP_ENUM(n, CTORPARAMS_print, ~)) \ BOOST_PP_IF(n, :, BOOST_PP_EMPTY()) \ BOOST_PP_ENUM(n, CTORINIT_print, ~) { } \ \ bool operator()(T const& t0, T const& t1) const { \ BOOST_PP_REPEAT(n, CMPIF_print, ~) \ return false; \ } \ }; \ \ template \ cmp##n \ make_cmp(BOOST_PP_ENUM(n, PARAM_print, ~)) \ { \ return cmp##n ( \ BOOST_PP_ENUM_PARAMS(n, m)); \ } BOOST_PP_REPEAT(CMP_MAX, CMP_functor, ~) #undef TYPEDEF_print #undef MEMBER_print #undef CTORPARAMS_print #undef CTORINIT_print #undef CMPIF_print #undef PARAM_print #undef CMP_functor
使用C++ 0x和lambdas Konrad的解决方案如下所示:
sort(wektor.begin(), wektor.end(), [](pkt const& a, pkt const& b) { if (a.alfa < b.alfa) return true; if (a.alfa > b.alfa) return false; if (a.x < b.x) return true; if (a.x > b.x) return false; return false; });