sorting an STL list of =references= to objects
-
VC++6 on XP Pro greetings all, I've created an STL list object that stores =references= to objects. I've overloaded the less-than operator like numerous examples on the 'net say to do. The following code compiles and executes but does not sort - actually the order does change but not in a sorted order. I'm stumped - there must be some nuance I'm missing.
// sort_example.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <list>
#include <iterator>
#include <vector>
#include <algorithm>using namespace std;
struct pstchip_pin_wor {
string primitive;
string pin_name;
string pin_number;/\* optional constructors \*/ pstchip\_pin\_wor( string aa, string bb, string cc) { primitive = aa; pin\_name = bb; pin\_number = cc; } //overridding operators pstchip\_pin\_wor& pstchip\_pin\_wor::operator = (const pstchip\_pin\_wor &itemToCopy) { this->primitive = itemToCopy.primitive; this->pin\_name = itemToCopy.pin\_name; this->pin\_number = itemToCopy.pin\_number; return \*this; } int pstchip\_pin\_wor::operator == ( const pstchip\_pin\_wor& itemToCompare) const { if( this->primitive == itemToCompare.primitive && this->pin\_name < itemToCompare.pin\_name ) return 1; return 0; } int pstchip\_pin\_wor::operator < ( const pstchip\_pin\_wor& itemToCompare) const { if( this->primitive < itemToCompare.primitive ) return 1; if( this->primitive == itemToCompare.primitive && this->pin\_name < itemToCompare.pin\_name) return 1; return 0; }
};
//main function
int main(int argc, char* argv[]) {int nRetCode = 0;
list<pstchip_pin_wor*> wors_pstchip_pins;
//populate list
wors_pstchip_pins.push_back( new pstchip_pin_wor( "Europe", "Spain", "Madrid" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "North America", "USA", "Washington DC" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "North America", "Canada", "Ottawa" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "Europe", "Germany", "Berlin" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "South America", "Brazil", "Sao Paulo" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "North America", -
VC++6 on XP Pro greetings all, I've created an STL list object that stores =references= to objects. I've overloaded the less-than operator like numerous examples on the 'net say to do. The following code compiles and executes but does not sort - actually the order does change but not in a sorted order. I'm stumped - there must be some nuance I'm missing.
// sort_example.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <list>
#include <iterator>
#include <vector>
#include <algorithm>using namespace std;
struct pstchip_pin_wor {
string primitive;
string pin_name;
string pin_number;/\* optional constructors \*/ pstchip\_pin\_wor( string aa, string bb, string cc) { primitive = aa; pin\_name = bb; pin\_number = cc; } //overridding operators pstchip\_pin\_wor& pstchip\_pin\_wor::operator = (const pstchip\_pin\_wor &itemToCopy) { this->primitive = itemToCopy.primitive; this->pin\_name = itemToCopy.pin\_name; this->pin\_number = itemToCopy.pin\_number; return \*this; } int pstchip\_pin\_wor::operator == ( const pstchip\_pin\_wor& itemToCompare) const { if( this->primitive == itemToCompare.primitive && this->pin\_name < itemToCompare.pin\_name ) return 1; return 0; } int pstchip\_pin\_wor::operator < ( const pstchip\_pin\_wor& itemToCompare) const { if( this->primitive < itemToCompare.primitive ) return 1; if( this->primitive == itemToCompare.primitive && this->pin\_name < itemToCompare.pin\_name) return 1; return 0; }
};
//main function
int main(int argc, char* argv[]) {int nRetCode = 0;
list<pstchip_pin_wor*> wors_pstchip_pins;
//populate list
wors_pstchip_pins.push_back( new pstchip_pin_wor( "Europe", "Spain", "Madrid" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "North America", "USA", "Washington DC" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "North America", "Canada", "Ottawa" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "Europe", "Germany", "Berlin" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "South America", "Brazil", "Sao Paulo" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "North America",I've improved my testcase to use two lists, one a list of structs and the original list of pointers-to-structs and added some code to populate, list, sort, and list again both lists. The list-of-structs sorts correctly while the list-of-pointers-to-structs does not. So it's got to be something with the how the overloaded operators are set up. Any ideas on how to adjust them to work right? [code] // sort_example.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <iomanip> #include <fstream> #include <string> #include <list> #include <iterator> #include <vector> #include <algorithm> using namespace std; struct pstchip_pin_wor { string primitive; string pin_name; string pin_number; /* optional constructors */ pstchip_pin_wor( string aa, string bb, string cc) { primitive = aa; pin_name = bb; pin_number = cc; } //overridding operators pstchip_pin_wor& pstchip_pin_wor::operator = (const pstchip_pin_wor &itemToCopy) { this->primitive = itemToCopy.primitive; this->pin_name = itemToCopy.pin_name; this->pin_number = itemToCopy.pin_number; return *this; } int pstchip_pin_wor::operator == ( const pstchip_pin_wor& itemToCompare) { if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name ) return 1; return 0; } int pstchip_pin_wor::operator < ( const pstchip_pin_wor& itemToCompare) { if( this->primitive < itemToCompare.primitive ) return 1; if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name) return 1; return 0; } }; //main function int main(int argc, char* argv[]) { int nRetCode = 0; list<pstchip_pin_wor> rows_pstchip_pins; list<pstchip_pin_wor*> wors_pstchip_pins; //populate list rows_pstchip_pins.push_back( pstchip_pin_wor( "Europe", "Spain", "Madrid" ) ); rows_pstchip_pins.push_back( pstchip_pin_wor( "North America", "USA", "Washington DC" ) ); rows_pstchip_pins.push_back( pstchip_pin_wor( "North America", "Canada", "Ottawa" ) ); rows_pstchip_pins.push_back( pstchip_pin_wor( "Europe", "Germany", "Berlin" ) ); rows_pstchip_pins.push_back( pstchip_pin_wor( "South America", "Brazil", "Sao Paulo" )
-
I've improved my testcase to use two lists, one a list of structs and the original list of pointers-to-structs and added some code to populate, list, sort, and list again both lists. The list-of-structs sorts correctly while the list-of-pointers-to-structs does not. So it's got to be something with the how the overloaded operators are set up. Any ideas on how to adjust them to work right? [code] // sort_example.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <iomanip> #include <fstream> #include <string> #include <list> #include <iterator> #include <vector> #include <algorithm> using namespace std; struct pstchip_pin_wor { string primitive; string pin_name; string pin_number; /* optional constructors */ pstchip_pin_wor( string aa, string bb, string cc) { primitive = aa; pin_name = bb; pin_number = cc; } //overridding operators pstchip_pin_wor& pstchip_pin_wor::operator = (const pstchip_pin_wor &itemToCopy) { this->primitive = itemToCopy.primitive; this->pin_name = itemToCopy.pin_name; this->pin_number = itemToCopy.pin_number; return *this; } int pstchip_pin_wor::operator == ( const pstchip_pin_wor& itemToCompare) { if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name ) return 1; return 0; } int pstchip_pin_wor::operator < ( const pstchip_pin_wor& itemToCompare) { if( this->primitive < itemToCompare.primitive ) return 1; if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name) return 1; return 0; } }; //main function int main(int argc, char* argv[]) { int nRetCode = 0; list<pstchip_pin_wor> rows_pstchip_pins; list<pstchip_pin_wor*> wors_pstchip_pins; //populate list rows_pstchip_pins.push_back( pstchip_pin_wor( "Europe", "Spain", "Madrid" ) ); rows_pstchip_pins.push_back( pstchip_pin_wor( "North America", "USA", "Washington DC" ) ); rows_pstchip_pins.push_back( pstchip_pin_wor( "North America", "Canada", "Ottawa" ) ); rows_pstchip_pins.push_back( pstchip_pin_wor( "Europe", "Germany", "Berlin" ) ); rows_pstchip_pins.push_back( pstchip_pin_wor( "South America", "Brazil", "Sao Paulo" )
If you really need to maintain a list of pointers, you can add one user-defined function (as global or as static member to the class) that compares two objects with pointers to them as parameters.
static bool less_than(pstchip_pin_wor* elem1, pstchip_pin_wor* elem2)
{
return *elem1 < *elem2;
}Then you use the sort with the user-defined function as parameter.
wors_pstchip_pins.sort(pstchip_pin_wor::less_than);
-
If you really need to maintain a list of pointers, you can add one user-defined function (as global or as static member to the class) that compares two objects with pointers to them as parameters.
static bool less_than(pstchip_pin_wor* elem1, pstchip_pin_wor* elem2)
{
return *elem1 < *elem2;
}Then you use the sort with the user-defined function as parameter.
wors_pstchip_pins.sort(pstchip_pin_wor::less_than);
-
Thank You for your reply! It's GMT -07:00 here so I'll give your suggestion a try on the morrow. Thanks again, kerchunk
I made the changes you suggested but now the code does not compile. Your instructions were clear - did I fat-finger something? [code] // sort_example.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <iomanip> #include <fstream> #include <string> #include <list> #include <iterator> #include <vector> #include <algorithm> using namespace std; struct pstchip_pin_row { string primitive; string pin_name; string pin_number; /* optional constructors */ pstchip_pin_row( string aa, string bb, string cc) { primitive = aa; pin_name = bb; pin_number = cc; } //overridding operators pstchip_pin_row& operator = (const pstchip_pin_row &itemToCopy) { this->primitive = itemToCopy.primitive; this->pin_name = itemToCopy.pin_name; this->pin_number = itemToCopy.pin_number; return *this; } bool operator == ( const pstchip_pin_row& itemToCompare) { if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name ) return true; return false; } bool operator < ( const pstchip_pin_row& itemToCompare) { if( this->primitive < itemToCompare.primitive ) return true; if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name) return true; return false; } }; struct pstchip_pin_wor { string primitive; string pin_name; string pin_number; /* optional constructors */ pstchip_pin_wor( string aa, string bb, string cc) { primitive = aa; pin_name = bb; pin_number = cc; } //overridding operators pstchip_pin_wor& operator = (const pstchip_pin_wor &itemToCopy) { this->primitive = itemToCopy.primitive; this->pin_name = itemToCopy.pin_name; this->pin_number = itemToCopy.pin_number; return *this; } bool operator == ( const pstchip_pin_wor& itemToCompare) { if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name ) return true; return false; } bool operator < ( const pstchip_pin_wor& itemToCompare) { if( this->primitive < itemToCompare.primitive) return true; if(
-
I made the changes you suggested but now the code does not compile. Your instructions were clear - did I fat-finger something? [code] // sort_example.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <iomanip> #include <fstream> #include <string> #include <list> #include <iterator> #include <vector> #include <algorithm> using namespace std; struct pstchip_pin_row { string primitive; string pin_name; string pin_number; /* optional constructors */ pstchip_pin_row( string aa, string bb, string cc) { primitive = aa; pin_name = bb; pin_number = cc; } //overridding operators pstchip_pin_row& operator = (const pstchip_pin_row &itemToCopy) { this->primitive = itemToCopy.primitive; this->pin_name = itemToCopy.pin_name; this->pin_number = itemToCopy.pin_number; return *this; } bool operator == ( const pstchip_pin_row& itemToCompare) { if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name ) return true; return false; } bool operator < ( const pstchip_pin_row& itemToCompare) { if( this->primitive < itemToCompare.primitive ) return true; if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name) return true; return false; } }; struct pstchip_pin_wor { string primitive; string pin_name; string pin_number; /* optional constructors */ pstchip_pin_wor( string aa, string bb, string cc) { primitive = aa; pin_name = bb; pin_number = cc; } //overridding operators pstchip_pin_wor& operator = (const pstchip_pin_wor &itemToCopy) { this->primitive = itemToCopy.primitive; this->pin_name = itemToCopy.pin_name; this->pin_number = itemToCopy.pin_number; return *this; } bool operator == ( const pstchip_pin_wor& itemToCompare) { if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name ) return true; return false; } bool operator < ( const pstchip_pin_wor& itemToCompare) { if( this->primitive < itemToCompare.primitive) return true; if(
You fattened the parameters of compareFunc with const specifiers. It works when you remove them. If you want to define compareFunc with const parameters:
static bool compareFunc( const pstchip_pin_wor* a, const pstchip_pin_wor* b)
then you have to define the operator < as a const member:
bool operator < ( const pstchip_pin_wor& itemToCompare) const
modified on Wednesday, December 2, 2009 5:13 PM
-
You fattened the parameters of compareFunc with const specifiers. It works when you remove them. If you want to define compareFunc with const parameters:
static bool compareFunc( const pstchip_pin_wor* a, const pstchip_pin_wor* b)
then you have to define the operator < as a const member:
bool operator < ( const pstchip_pin_wor& itemToCompare) const
modified on Wednesday, December 2, 2009 5:13 PM
OK I unfattened compareFunc by removing the two 'const's. Under VC++6 the program now throws one compiler error: --------- C:\mystuff\sort_example.cpp(127) : error C2664: 'void __thiscall std::list<struct pstchip_pin_wor *,class std::allocator<struct pstchip_pin_wor *> >::sort(struct std::greater<struct pstchip_pin_wor *> )' : cannot convert parameter 1 from 'bool (__cdecl *)(struct pstchip_pin_wor *,struct pstchip_pin_wor *)' to 'struct std::greater<struct pstchip_pin_wor *>' No constructor could take the source type, or constructor overload resolution was ambiguous Error executing cl.exe. ---------- ??? Do I need to overload the std::greater function? And if so how? Thank You, kerchunk
-
OK I unfattened compareFunc by removing the two 'const's. Under VC++6 the program now throws one compiler error: --------- C:\mystuff\sort_example.cpp(127) : error C2664: 'void __thiscall std::list<struct pstchip_pin_wor *,class std::allocator<struct pstchip_pin_wor *> >::sort(struct std::greater<struct pstchip_pin_wor *> )' : cannot convert parameter 1 from 'bool (__cdecl *)(struct pstchip_pin_wor *,struct pstchip_pin_wor *)' to 'struct std::greater<struct pstchip_pin_wor *>' No constructor could take the source type, or constructor overload resolution was ambiguous Error executing cl.exe. ---------- ??? Do I need to overload the std::greater function? And if so how? Thank You, kerchunk
BUG: The STL list::sort() Function Doesn't Sort a List of Pointers http://support.microsoft.com/default.aspx?scid=kb;EN-US;q265109 The Standard Template Library (STL) list::sort function doesn't sort a list of pointers when a predicate function is defined for sorting. VC6 is a ten-year old compiler now. The bug is not present in VC2008 or MinGW. Your code is implemented below with the workaround described in KB265109. ________________________________________________________________________________________ #include <iostream> #include <string> #include <list> using namespace std; struct pstchip_pin_wor { string primitive; string pin_name; string pin_number; pstchip_pin_wor( string aa, string bb, string cc) { primitive = aa; pin_name = bb; pin_number = cc; } pstchip_pin_wor& pstchip_pin_wor::operator= (const pstchip_pin_wor &itemToCopy) { if(&itemToCopy != this) { this->primitive = itemToCopy.primitive; this->pin_name = itemToCopy.pin_name; this->pin_number = itemToCopy.pin_number; } return *this; } int pstchip_pin_wor::operator == ( const pstchip_pin_wor& itemToCompare) const { if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name ) return 1; return 0; } int pstchip_pin_wor::operator < ( const pstchip_pin_wor&
-
BUG: The STL list::sort() Function Doesn't Sort a List of Pointers http://support.microsoft.com/default.aspx?scid=kb;EN-US;q265109 The Standard Template Library (STL) list::sort function doesn't sort a list of pointers when a predicate function is defined for sorting. VC6 is a ten-year old compiler now. The bug is not present in VC2008 or MinGW. Your code is implemented below with the workaround described in KB265109. ________________________________________________________________________________________ #include <iostream> #include <string> #include <list> using namespace std; struct pstchip_pin_wor { string primitive; string pin_name; string pin_number; pstchip_pin_wor( string aa, string bb, string cc) { primitive = aa; pin_name = bb; pin_number = cc; } pstchip_pin_wor& pstchip_pin_wor::operator= (const pstchip_pin_wor &itemToCopy) { if(&itemToCopy != this) { this->primitive = itemToCopy.primitive; this->pin_name = itemToCopy.pin_name; this->pin_number = itemToCopy.pin_number; } return *this; } int pstchip_pin_wor::operator == ( const pstchip_pin_wor& itemToCompare) const { if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name ) return 1; return 0; } int pstchip_pin_wor::operator < ( const pstchip_pin_wor&