views:

126

answers:

3

Hi there, this is for an assignment so I will be deliberately general. My question is related to implementation decisions I already made--maybe they weren't good ones.

I have a list of pointers to structs, e.g. list<MyStruct*> bob; At one point I've needed to sort these pointers by one of the data members of their targets and I was able to do that easily with

bool sortbyarrival(const MyStruct* a, const MyStruct* b) {
return a->arrival < b->arrival;
}

And then calling bob.sort(sortbyarrival); Works great.

Now somewhere else I need to sort by a different criterion, which involves a counter in the program. I need something like return counter*a->arrival < counter*b->arrival; But the way I just described is the only way I know how to do a sort, I think, and I don't know how to pass my counter as an additional argument. How can I sort this list of pointers?

ETA: The counter is just a variable in main. So ideally I could call something like bob.sort(sortbyratio, counter); or sort(bob.begin(), bob.end(), sortbyratio, counter);

A: 

Just create an function-object, a class/struct with an overload of operator() that does the right thing for you. In this case, taking into consideration the extra variables. Then, you pass an instance of it to the sort method.


struct my_comparison : binary_function<MyStruct const*, MyStruct const*, bool> 
{
  bool operator()(MyStruct const* a, MyStruct const* b) 
  { 
    return (a->counter * a->arrival) < (b->counter * b->arrival);
  }
};

//Use it this way.
my_comparison comp;

//Set the arrival and counter data in instance comp.
/* ... */

//Now, pass it to the list.
bob.sort(comp);

EDIT: I just noticed that you have a list of pointers so I changed a bit the struct.

ltcmelo
eom
So just create a copy or reference or pointer to it inside MyStruct. Or use another type that contains the counter. Will that work?
ltcmelo
+4  A: 

Similar to ltcmelo's example, but if the objects themselves don't contain the counter:

struct sort_with_counter {
    sort_with_counter(const double d): counter(d) {}

    bool operator()(const MyStruct* a, const MyStruct* b) {
        return(counter*a->arrival < counter*b->arrival);
    }

    const double counter;
};

mylist.sort(sort_with_counter(5.0));

If your counter is an external variable like that though it won't affect the ordering (at least if it's positive - thanks onebyone!) - so this may in fact not be necessary at all (or maybe I misunderstand what you're after?). It's a useful technique in other cases though.

Peter
"it won't affect the ordering" - see the last line of my answer :-)
Steve Jessop
Thanks - I think the point is still important (it would be an odd way of reversing the sort order, and I don't think was what the OP intended) but it's important to be correct nonetheless :)
Peter
Thanks, this worked great for the problem, which I didn't describe very well. Sorry I didn't come back earlier, I was trying to get the whole thing turned in!
eom
+1  A: 

Create a functor, and store the extra value in the functor object:

struct CompareByCounter {
    CompareByCounter(int c) : counter(c) {}
    bool operator()(const MyStruct *lhs, const MyStruct *rhs) {
        return (counter * lhs->arrival) < (counter * rhs->arrival);
    }
private:
    int counter;
};

// sort ascending
bob.sort(CompareByCounter(1));
// sort descending
bob.sort(CompareByCounter(-1));
Steve Jessop