Need help with sorting functions with multiple data types

My goal is to be able to sort an array of objects.
The user will choose what he wants to sort by. (using a single function).
I have tried using a template function in order to accomplish this, but I ran into a few issues.
I'm not sure if a template function would even be the best idea for this project, but it is the only way I found that would make this task possible.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//here we have the class data.
//the user will later select whether he wants to sort by ID, name, quantity, or //price

  class Laptop{ //Laptop (item) class
private:
    string Laptop_ID;
    string Laptop_name;
    int Laptop_quantity; //number of Laptops in stock
    float Laptop_price;
public:
//I have some member function here that allow me to return data from private //variables


//my attempt at writing a bubble sorting function (prototype)
template <typename T>
    void generic_sort(Laptop laptop[],T field, int pos);
};
//Function Definitions

//(The issue I am running into) 
//I try to sort the function by passing the desired field into the function
//field is not a private member variable of TYPE laptop
//I would like to be able to pass the object variable into the function and
  //sort the array of laptop objects based on the given field.

template <typename T>
void Laptop::generic_sort(Laptop laptop[],T field, int pos){//sorts by any field
    T temp;
    bool sorted;
    do{//do until sorted
        sorted = true;//initial value
        for(int i = 0;i<pos;i++){  //sorts in array

            if(laptop[i].field > laptop[i+1].field ) {//condition to check which is greater and if to sort
                sorted = false; //not sorted yet
                cout<<"\nNot Sorted yet";
                //swap values
                temp = laptop[i].field;
                laptop[i].field() = laptop[i + 1].field();
                laptop[i + 1]-.field = temp;
            }
        }
    }while(!sorted);
}



Last edited on
Q. Does C++ Standard Library offer anything for sorting?
A. Yes: sort(), stable_sort(), partial_sort(), nth_element()
For example: http://www.cplusplus.com/reference/algorithm/sort/

Do they use template? Yes. Not for handing out a field, but handing a functor that accesses the public interface.

1
2
3
4
5
6
7
8
9
10
Laptop heap[42];
// fill heap

// sort by ID
std::sort( std::begin(heap), std::end(heap),
           [](auto lhs, auto rhs){ return lhs.ID() < rhs.ID(); } );

// sort by price (descending)
std::sort( std::begin(heap), std::end(heap),
           [](auto lhs, auto rhs){ return lhs.price() > rhs.price(); } );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;


template<typename T, typename S> void mySort( vector<T> &V, S T::*p, bool forward = true )
{
   if ( forward ) sort( V.begin(), V.end(), [p]( T a, T b ){ return a.*p < b.*p; } );
   else           sort( V.begin(), V.end(), [p]( T a, T b ){ return a.*p > b.*p; } );
}


class Laptop
{
public:
   string ID;
   string name;
   int quantity;
   double price;
   friend ostream & operator << ( ostream &out, const Laptop &L )
   {
      return out << L.ID << "  " << setw(12) << L.name << "  " << setw(3) << L.quantity << "   " << setw(10) << L.price;
   }
};


int main()
{
   vector<Laptop> V = { { "ABC", "Dell"      , 10, 440.00 },
                        { "DEF", "Armageddon", 20, 830.50 },
                        { "GEH", "Bother"    ,  5, 299.99 },
                        { "IJK", "Lynx"      , 12, 599.99 } };

   cout << "Original:\n";
   for ( auto &L : V ) cout << L << '\n';


   cout << "\nSorted by name:\n";
   mySort( V, &Laptop::name );
   for ( auto &L : V ) cout << L << '\n';


   cout << "\nSorted backwards by price:\n";
   mySort( V, &Laptop::price, false );
   for ( auto &L : V ) cout << L << '\n';


   cout << "\nSorted by quantity:\n";
   mySort( V, &Laptop::quantity );
   for ( auto &L : V ) cout << L << '\n';
}


Original:
ABC          Dell   10          440
DEF    Armageddon   20        830.5
GEH        Bother    5       299.99
IJK          Lynx   12       599.99

Sorted by name:
DEF    Armageddon   20        830.5
GEH        Bother    5       299.99
ABC          Dell   10          440
IJK          Lynx   12       599.99

Sorted backwards by price:
DEF    Armageddon   20        830.5
IJK          Lynx   12       599.99
ABC          Dell   10          440
GEH        Bother    5       299.99

Sorted by quantity:
GEH        Bother    5       299.99
ABC          Dell   10          440
IJK          Lynx   12       599.99
DEF    Armageddon   20        830.5




If you want the data members of your class to be private then you can point to the relevant getters instead:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;


template<typename T, typename S> void mySort( vector<T> &V, S T::*p, bool forward = true )
{
   if ( forward ) sort( V.begin(), V.end(), [p]( T a, T b ){ return a.*p < b.*p; } );
   else           sort( V.begin(), V.end(), [p]( T a, T b ){ return a.*p > b.*p; } );
}


template<typename T, typename S> void myFSort( vector<T> &V, S (T::*p)(), bool forward = true )
{
   if ( forward ) sort( V.begin(), V.end(), [p]( T a, T b ){ return (a.*p)() < (b.*p)(); } );
   else           sort( V.begin(), V.end(), [p]( T a, T b ){ return (a.*p)() > (b.*p)(); } );
}


class Laptop
{
   string ID;
   string name;
   int quantity;
   double price;
public:
   Laptop( string ID, string name, int quantity, double price ) : ID(ID), name(name), quantity(quantity), price(price) {}
   string getID(){ return ID; }
   string getName(){ return name; }
   int getQuantity(){ return quantity; }
   double getPrice(){ return price; }

   friend ostream & operator << ( ostream &out, const Laptop &L )
   {
      return out << L.ID << "  " << setw(12) << L.name << "  " << setw(3) << L.quantity << "   " << setw(10) << L.price;
   }
};


int main()
{
   vector<Laptop> V = { { "ABC", "Dell"      , 10, 440.00 },
                        { "DEF", "Armageddon", 20, 830.50 },
                        { "GEH", "Bother"    ,  5, 299.99 },
                        { "IJK", "Lynx"      , 12, 599.99 } };

   cout << "Original:\n";
   for ( auto &L : V ) cout << L << '\n';


   cout << "\nSorted by name:\n";
   myFSort( V, &Laptop::getName );
   for ( auto &L : V ) cout << L << '\n';


   cout << "\nSorted backwards by price:\n";
   myFSort( V, &Laptop::getPrice, false );
   for ( auto &L : V ) cout << L << '\n';


   cout << "\nSorted by quantity:\n";
   myFSort( V, &Laptop::getQuantity );
   for ( auto &L : V ) cout << L << '\n';
}

Last edited on
Topic archived. No new replies allowed.