fork download
  1. #include <functional>
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <utility>
  5. #include <string>
  6. #include <vector>
  7.  
  8. template <class type>
  9. using compare = std::function<bool(const type&, const type&)>;
  10. template<
  11. class classT
  12. >
  13. struct field_comparer {
  14. using type = classT;
  15. bool operator() (const type& a, const type& b) {
  16. return functor (a, b);
  17. }
  18. field_comparer():functor(nullptr) {}
  19. field_comparer(const compare<type>& f):functor(f) {}
  20. field_comparer(const compare<type>&& f):functor(std::move(f)) {}
  21. //field_comparer(const field_comparer<type>& f):functor(f.functor) {}
  22. //field_comparer(const field_comparer<type>&& f):functor(std::move(f.functor)) {}
  23.  
  24. template<class T>
  25. field_comparer<T> operator=(const field_comparer<T>& f) { functor.assign(f.functor); }
  26. template<class T>
  27. field_comparer<T> operator=(const field_comparer<T>&& f){ functor.assign(std::move(f.functor)); }
  28. compare<type> functor;
  29. };
  30.  
  31. template<
  32. class classT,
  33. class memberT
  34. >
  35. struct some:public field_comparer<classT> {
  36. using type = classT;
  37. using member_type = memberT;
  38. using member_ptr = member_type type::*;
  39. using compare = std::function<bool(const member_type&, const member_type&)>;
  40. some(member_ptr mem, compare func)
  41. :member(mem), comp(func){
  42. this->field_comparer<type>::functor = std::bind(&some<type, member_type>::call, this,
  43. std::placeholders::_1, std::placeholders::_2);
  44. }
  45. some(some<classT, memberT> const& l)
  46. :field_comparer<type>(l.functor),
  47. member(l.member), comp(l.comp){}
  48. some(some<classT, memberT> const&& l)
  49. :field_comparer<type>(l.functor),
  50. member(std::move(l.member)), comp(std::move(l.comp)){}
  51. bool call(const type& a, const type& b) {
  52. return comp(a.*member, b.*member);
  53. }
  54. private:
  55. member_ptr member;
  56. compare comp;
  57. };
  58. template<
  59. class classT,
  60. class memberT,
  61. class cmpT = std::less<memberT>
  62. >
  63. field_comparer<classT> make_comparer(
  64. memberT classT::*member,
  65. cmpT cmp = cmpT()
  66. ) {
  67. return std::move(some<classT, memberT>(member, cmp));
  68. }
  69.  
  70. struct test_idx {
  71. char one;
  72. int two;
  73. std::string three;
  74. test_idx* four;
  75. };
  76. int main() {
  77. using namespace std;
  78. vector<test_idx> a{
  79. {'a', 100500, "hello", nullptr},
  80. {'z', 42, "a hell", (test_idx*)(0xdead)}
  81. };
  82.  
  83. auto print = [&a]() ->void
  84. {
  85. for(auto& i: a)
  86. cout << '{'
  87. << i.one << ", "
  88. << i.two << ", "
  89. << i.three << ", "
  90. << i.four << "} ";
  91. cout << endl;
  92. };
  93. vector<field_comparer<test_idx>>
  94. one_idx{
  95. make_comparer(&test_idx::one),
  96. make_comparer(&test_idx::two),
  97. make_comparer(&test_idx::three),
  98. make_comparer(&test_idx::four)
  99. };
  100. print();
  101. for(auto& cmp: one_idx) {
  102. std::sort(a.begin(), a.end(), cmp);
  103. print();
  104. }
  105. return 0;
  106. }
  107.  
Success #stdin #stdout 0s 3448KB
stdin
Standard input is empty
stdout
{a, 100500, hello, 0} {z, 42, a hell, 0xdead} 
{a, 100500, hello, 0} {z, 42, a hell, 0xdead} 
{z, 42, a hell, 0xdead} {a, 100500, hello, 0} 
{z, 42, a hell, 0xdead} {a, 100500, hello, 0} 
{a, 100500, hello, 0} {z, 42, a hell, 0xdead}