Member function pointer - C ++ std :: list sort

How to pass a pointer to a member function in std :: list.sort ()?

Is it possible? Thanks

struct Node { uint32_t ID; char * Value; }; class myClass { private: uint32_t myValueLength; public: list<queueNode *> MyQueue; bool compare(Node * first, Node * second); bool doStuff(); } bool myClass::compare(Node * first, Node * second) { unsigned int ii =0; while (ii < myValueLength) { if (first-> Value[ii] < second-> Value[ii]) { return true; } else if (first-> Value[ii] > second-> Value[ii]) { return false; } ++ii; } return false; } bool myClass::doStuff() { list.sort(compare); } 

I want to use a length variable from a class instead of executing the strlen () function in a comparison function (the value will always be the same length)

Edit: myValueLength was not the only variable I wanted to access from the comparison function. I just simplified it to make the example shorter.

+4
source share
6 answers

When developing grieve's answer, why not use a functor? For instance:.

 struct Functor { bool operator()( char * a, char * b ) { return strcmp(a,b) < 0; } }; 

Then you can simply use:

 Functor f; myList.sort(f); 

You can even use your class as a Functor by defining operator () ...

 class myClass { ... bool operator()( queueNode * a, queueNode * b ) { return compare( a, b ); } void doStuff() { MyQueue.sort(*this); } }; 

A simple code example:

 #include <iostream> #include <list> using namespace std; // Assumes TYPE t; cout << t; is valid. template<class TYPE> inline ostream & operator<< ( ostream & theOstream, const list<TYPE> & theList ) { typename list<TYPE>::const_iterator listIterator = theList.begin(); for ( int i = 0; listIterator != theList.end(); listIterator ++, i ++ ) theOstream << " [" << i << "]: \"" << (*listIterator) << "\"" << endl; return theOstream; } struct Functor { bool operator()( const char * a, const char * b ) { return strcmp(a,b) < 0; } }; int main() { list<char*> l; /* Load up some example test data... */ char s[3]; s[2] = '\0'; for ( s[0]='c'; s[0]>='a'; s[0]-- ) for ( s[1]='c'; s[1]>='a'; s[1]-- ) l.push_back(strdup(s)); /* Show us that test data... */ cout << l << endl; /* Sort list. */ Functor f; l.sort(f); /* Show us what we have now... */ cout << l << endl; } 
+7
source

It is possible. Do you consider using boost :: function?

 list.sort( boost::bind( &myClass::compare, this, _1, _2 ) ); 

Is your compare function data- based? If not, you can simply use the comparison function for static . And then it will be

 list.sort( &myClass::compare ); 

You can add an auxiliary structure for comparison, and then

 list.sort( Comparer( myValueLength ) ); struct Comparer { Comparer( uint32_t myValueLength ): length( myValueLength ) {} bool operator() (Node * first, Node * second) { unsigned int ii =0; while (ii < length) { if (first-> Value[ii] < second-> Value[ii]) { return true; } else if (first-> Value[ii] > second-> Value[ii]) { return false; } ++ii; } return false; } uint32_t length; }; 
+7
source
+3
source

Note that std::list sorts the element according to the operator< defined for that element. You need to change the compare function to use the global operator< defined for Node objects:

 bool operator<(Node const& first, Node const& second) { unsigned int ii =0; while (ii < length) { if (first.Value[ii] < second.Value[ii]) { return true; } else if (first.Value[ii] > second.Value[ii]) { return false; } ++ii; } return false; 

}

The proposed improvement will be:

 bool operator<(Node const& first, Node const& second) { for (size_t ii =0; first.Value[ii] == second.Value[ii]; ++ii) ; // note ; return (first.Value[ii] < second.Value[ii]); } 

If char *Value really represents a C-style string, and you want lexicographic sorting, further improvements are possible:

 bool operator<(Node const& first, Node const& second) { return (strcmp(first.Value, second.Value) < 0); } 

and if they are really strings, I suggest you use std::string , and you can write:

 bool operator<(Node const& first, Node const& second) { return first.Value < second.Value; } 
+1
source

As sorrows and assumptions proposed

just operator overloading () works

Thanks to all who responded

 struct Node { uint32_t ID; char * Value; }; class myClass { private: uint32_t myValueLength; public: list<queueNode *> MyQueue; bool operator()(Node * first, Node * second); bool doStuff(); } bool myClass::operator()(Node * first, Node * second) { unsigned int ii =0; while (ii < myValueLength) { if (first-> Value[ii] < second-> Value[ii]) { return true; } else if (first-> Value[ii] > second-> Value[ii]) { return false; } ++ii; } return false; } bool myClass::doStuff() { list.sort(*this); } 
0
source

Why not make a static comparison function, you no longer need a functor. Then you can just do list.sort (compare);

nevermind ... I just realized that your comparison function uses the data element of the class, so it cannot be static. Use Functor :)

0
source

All Articles