I am very new to using the STL list library. From what I have been reading here and other places on the web is that I have to create a compare function to use within the sort member function of list. The reason being that the list node's contain structures. I have to sort the list by a few different variables. Below is the class that controls my list. I am getting two errors.

Error 1) error C3867: 'Standings::compareForSort': function call missing argument list; use '&Standings::compareForSort' to create a pointer to member

Error 2) error C2660: 'std::list<_Ty>::sort' : function does not take 1 arguments

Any help here would be appreciated.

#ifndef STANDINGS_H
#define STANDINGS_H

#include <iostream>
#include <list>
#include <fstream>
#include <iomanip>

using namespace std;

#define NAMELENGTH 20

struct Records
{
	int totalWin;
	int totalLose;
	double winPercentage;
	double gamesBehind;
	int streakWin;
	int streakLose;
	int streakLength;
	int homeWin;
	int homeLose;
	int awayWin;
	int awayLose;
	int interWin;
	int interLose;
	int division;
	char teamName[NAMELENGTH];
	char streakType;

};


class Standings
{
private:
	list<Records> recordsList;
	friend class Team;
public:
	Standings();
	~Standings(){};
	void loadList();
	void saveList();
	void printStandings();
	bool compareForSort (Records&, Records&);
	
};

#endif

#include "standings.h"

Standings::Standings()
{

}	


void Standings::loadList(){
	//Create a variable of ifstream type names loadFile
	ifstream loadFile;                     
	//Open standings txt file
	loadFile.open("standings.txt");		 
	//Temporary object of struct type Record
	Records r;


	//Loop to take from file put into class 
	//and than put class into list
	while(!loadFile.eof()){
		loadFile >> r.teamName
			>> r.totalWin
			>> r.totalLose
			>> r.winPercentage
			>> r.gamesBehind
			>> r.streakWin
			>> r.streakLose
			>> r.streakType
			>> r.streakLength
			>> r.homeWin
			>> r.homeLose
			>> r.awayWin
			>> r.awayLose
			>> r.interWin
			>> r.interLose
			>> r.division;

		//Checks to make sure its not the end of file.
		//If its not the end of the file it inserts 
		//the node at the end of the list
		if(!loadFile.eof())
			recordsList.push_back(r);
	}
	 //closing the text file
	loadFile.close(); 
}

void Standings::saveList()
{
	//Sorts the List before saving to txt
	recordsList.sort(compareForSort);
	//Create a variable of ofstream type names saveFile
	ofstream saveFile;                    
	//Open standings txt file
	saveFile.open("standings.txt");	
	//Create an iterator to keep place of the nodes saved
	list<Records>::iterator i;

	//Loop through each node and save each member to that node
	for ( i=recordsList.begin(); i != recordsList.end(); ++i ) {
		saveFile << right << setw(13) << i->teamName << setw(4) << i->totalWin 
		<< setw(4) << i->totalLose << setw(7) << setprecision(3) << i->winPercentage 
		<< setw(6) << i->gamesBehind << setw(2) << i->streakWin 
		<< setw(2) << i->streakLose  << setw(2) << i->streakType 
		<< setw(2) << i->streakLength  << setw(3)<< i->homeWin 
		<< setw(3) << i->homeLose  << setw(3) << i->awayWin 
		<< setw(3) << i->awayLose  << setw(3)<< i->interWin 
		<< setw(3) << i->interLose  << setw(2) << i->division 
		<< endl;
	}
//Flush and Close txt file
	saveFile.flush();
	saveFile.close();

}

void Standings::printStandings()
{
	list<Records>::iterator i;

	//Looping through each node and printing each variable of each node
	for ( i=recordsList.begin(); i != recordsList.end(); ++i ) 
	{
		cout  << right << setw(13) << i->teamName << setw(4) << i->totalWin 
			<< setw(4) << i->totalLose << right << setw(7) << i->winPercentage 
			<< right << setw(6) << i->gamesBehind << right << setw(2) << i->streakWin 
			<< right << setw(2) << i->streakLose << right << setw(2) << i->streakType 
			<< right << setw(2) << i->streakLength <<right << setw(3)<< i->homeWin 
			<< right << setw(3) << i->homeLose << right << setw(3) << i->awayWin 
			<< right << setw(3) << i->awayLose << right << setw(3)<< i->interWin 
			<< right << setw(3) << i->interLose << right << setw(2) << i->division 
			<< endl;
	}
}


bool Standings::compareForSort(Records& node1, Records& node2)
{
	list<Records>::iterator i;
	for ( i=recordsList.begin(); i != recordsList.end(); ++i ) {
		if((node1.totalWin > node2.totalWin) && (node1.winPercentage > node2.winPercentage) && (node1.division < node2.division))
			return true;
		else 
		return false;
	
	}

}

Line 102 is where I call sort. recordsList is the name of my list, and compareForSort is the name of the function I wrote Though I am sure I need help with that function as well. Maybe I am trying to use std::sort but I thought recordsList.sort(compareForSort) was calling the list specific sort. Btw cplusplus is one of the places I did read about creating the compare function.

shameless bump. Sorry but I could really use some help on this subject. Thank you ahead of time for any help received.

recordsList.sort(compareForSort);

Try this :

recordsList.sort(&Standings::compareForSort);

Edited 7 Years Ago by firstPerson: n/a

edit: sorry, my mistake, I mixed list with sort.

Edited 7 Years Ago by Zjarek: n/a

Ok now I am just getting

xutility(348) : error C2064: term does not evaluate to a function taking 2 arguments

I assume it is talking about the binary predicate function, but everywhere I read the binary predicate in other peoples example has two arguments.
Does it have to do with the fact that The nodes in the list are of struct Records while the list is being created in the standings class? Though the variables in Records are public so I dont see why that would be an issue. Here is the predicate function I have currently

bool Standings::compareForSort(const Records& node1, const Records& node2)
{
return ((node1.totalWin > node2.totalWin) &&  (node1.winPercentage > node2.winPercentage) && (node1.division < node2.division));
			
	
	}

After doing more reading I found that some people use an overloaded < operator. So I attempted this and still getting loads of errors.

error C2676: binary '<' : 'Records' does not define this operator or a conversion to a type acceptable to the predefined operator

Here is my overloaded <

bool Standings::operator <(const Records& node)
{
	list<Records>::iterator i;
	//for ( i=recordsList.begin(); i != recordsList.end(); ++i ) {
		if ((i->totalWin > node.totalWin) && (i->winPercentage > node.winPercentage) && (i->division < node.division))
			 return true;
		else 
		return false;

I am going to continue putting the things I try because I dont want anyone to think I am not trying for myself. So I tried putting the overloaded < operator within my struct Records. No errors. The program is running fine. Except when it is time to sort its not sorting anything. So I guess it could be the logic or syntax within the operator
EDIT: Is there another way to sort a struct list by multiple variable values?

bool operator <(const Records& node)
{
	return ((totalWin > node.totalWin) && (winPercentage > node.winPercentage) && (division < node.division));
}

Edited 7 Years Ago by Afupi: n/a

>>xutility(348) : error C2064: term does not evaluate to a function taking 2 arguments

Which line is this from?

It appears to be where I call recordsList.sort(&Standings::compareForSort);

> h:\documents\cs132\cs132_project2\cs132_project2\standings.cpp(92) : see reference to function template instantiation 'void std::list<_Ty>::sort<bool(__thiscall Standings::* )(const Records &,const Records &)>(_Pr3)' being compiled
1> with
1> [
1> _Ty=Records,
1> _Pr3=bool (__thiscall Standings::* )(const Records &,const Records &)
1> ]
1>c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility(348) : error C2064: term does not evaluate to a function taking 2 arguments

I have the overloaded operator and binary predicate commented out atm so i could work on other parts of the program.

#ifndef STANDINGS_H
#define STANDINGS_H

#include <iostream>
#include <list>
#include <fstream>
#include <iomanip>

using namespace std;

#define NAMELENGTH 20


struct Records
{
	int totalWin;  //Each teams total wins
	int totalLose; //Each teams total loses
	int streakWin;	 //wins in last 10 games
	int streakLose;	 //loses in last 10 games
	int streakLength;	 //Number of wins or loses in 
	//a row
	int homeWin;  //number of games won at home
	int homeLose; //number of games lost at home		
	int awayWin;  //number of wins away
	int awayLose; //number of loses away
	int interWin; //Number of interleague games won
	int interLose;//Number of interleague games lost
	int division; //Which division each team is.
	double winPercentage; //Percentage of wins 
	//compared to loses
	double gamesBehind;	  //Total number of 
	// games played 
	char teamName[NAMELENGTH]; //Team names
	char streakType; //If teams streak is winning or 
	//losing

	/*bool operator <(const Records& node)
	{
		return ((totalWin > node.totalWin) && 
			(winPercentage > node.winPercentage) && 
			(division < node.division));
	}*/

};



class Standings
{
private:

	list<Records> recordsList;	//List variable
	friend class Team;			//Allows private member access
	//to the Team class
public:
	//Constructor
	Standings();
	//Destructor
	~Standings(){};
	//bool operator <(const Records&);

	//Takes in list from txt file
	//and inserts it into the list
	void loadList();
	//Takes in the altered list and 
	//saves to txt file
	void saveList();
	//Prints the list
	void printStandings();
	//Overloaded function to let sort
	//know how to sort list
	//Takes in two objects of the struct 
	//Records
	bool compareForSort (const Records&, const Records&);

};

#endif 

#include "standings.h"

//***********************************************************
// Function Name:Standings
// Purpose: Constructor
//***********************************************************
Standings::Standings()
{

}	
/*
bool Standings::operator <(const Records& node)
{
	list<Records>::iterator i;
	//for ( i=recordsList.begin(); i != recordsList.end(); ++i ) {
		if ((i->totalWin > node.totalWin) && (i->winPercentage > node.winPercentage) && (i->division < node.division))
			 return true;
		else 
		return false;
	
	//}


}*/

//***********************************************************
// Function Name: loadList
// Purpose: To pull in info from a txt file and insert it into
//			a list.
// Parameters: None
// Return Value: None
// Data Members Accessed: struct Records variables
// Data Members Modified: recordsList
// Functions Called: ifstream.open(), list.push_back(),
//					 ifstream.close()
//***********************************************************
void Standings::loadList(){
	//Create a variable of ifstream type names loadFile
	ifstream loadFile;                     
	//Open standings txt file
	loadFile.open("dummy.txt");		 
	//Temporary object of struct type Record
	Records r;


	//Loop to take from file put into class 
	//and than put class into list
	while(!loadFile.eof()){
		loadFile >> r.teamName
			>> r.totalWin
			>> r.totalLose
			>> r.winPercentage
			>> r.gamesBehind
			>> r.streakWin
			>> r.streakLose
			>> r.streakType
			>> r.streakLength
			>> r.homeWin
			>> r.homeLose
			>> r.awayWin
			>> r.awayLose
			>> r.interWin
			>> r.interLose
			>> r.division;

		//Checks to make sure its not the end of file.
		//If its not the end of the file it inserts 
		//the node at the end of the list
		if(!loadFile.eof())
			recordsList.push_back(r);
	}
	 //closing the text file
	loadFile.close(); 
}


//***********************************************************
// Function Name:saveList
// Purpose: To put the updated list back into the original
//			text file
// Parameters:None
// Return Value: None
// Data Members Accessed: struct Records member variables
// Functions Called:list.sort(), ofstream.open(), 
//					ofstream.close(), ofstream.flush(), 
//					setw(), list.begin(), list.end()
//***********************************************************
void Standings::saveList()
{
	//Sorts the List before saving to txt
	//recordsList.sort();
	recordsList.sort(&Standings::compareForSort);
	//Create a variable of ofstream type names saveFile
	ofstream saveFile;                    
	//Open standings txt file
	saveFile.open("dummy.txt");	
	//Create an iterator to keep place of the nodes saved
	list<Records>::iterator i;

	//Loop through each node and save each member to that node
	for ( i=recordsList.begin(); i != recordsList.end(); ++i ) {
		saveFile << right << setw(13) << i->teamName << setw(4) << i->totalWin 
		<< setw(4) << i->totalLose << setw(7) << setprecision(3) << i->winPercentage 
		<< setw(6) << i->gamesBehind << setw(3) << i->streakWin 
		<< setw(3) << i->streakLose  << setw(2) << i->streakType 
		<< setw(3) << i->streakLength  << setw(3)<< i->homeWin 
		<< setw(3) << i->homeLose  << setw(3) << i->awayWin 
		<< setw(3) << i->awayLose  << setw(3)<< i->interWin 
		<< setw(3) << i->interLose  << setw(2) << i->division 
		<< endl;
	}
//Flush and Close txt file
	saveFile.flush();
	saveFile.close();

}

//***********************************************************
// Function Name:printStandings
// Purpose: To output to console all nodes of the created list
// Parameters: None
// Return Value:None
// Data Members Accessed: struct Records member variables
// Data Members Modified: None
// Functions Called:list.begin(), list.end(), setw()
//***********************************************************
void Standings::printStandings()
{
	list<Records>::iterator i;

	//Looping through each node and printing each variable of each node
	for ( i=recordsList.begin(); i != recordsList.end(); ++i ) 
	{
		cout  << right << setw(13) << i->teamName << setw(4) << i->totalWin 
			<< setw(4) << i->totalLose << right << setw(7) << i->winPercentage 
			<< right << setw(6) << i->gamesBehind << right << setw(2) << i->streakWin 
			<< right << setw(2) << i->streakLose << right << setw(2) << i->streakType 
			<< right << setw(2) << i->streakLength <<right << setw(3)<< i->homeWin 
			<< right << setw(3) << i->homeLose << right << setw(3) << i->awayWin 
			<< right << setw(3) << i->awayLose << right << setw(3)<< i->interWin 
			<< right << setw(3) << i->interLose << right << setw(2) << i->division 
			<< endl;
	}
}

//***********************************************************
// Function Name: compareForSort
// Purpose: Binary predicate to sort STL list
// Parameters:
// Return Value:
// Data Members Accessed:
// Data Members Modified:
// Non-Local Variables Used:
// Functions Called:
//***********************************************************
bool Standings::compareForSort(const Records& node1, const Records& node2)
{
	//list<Records>::iterator i;
	//for ( i=recordsList.begin(); i != recordsList.end(); ++i ) {
		//if
			return ((node1.totalWin > node2.totalWin) && (node1.winPercentage > node2.winPercentage) && (node1.division < node2.division));
			//return true;
		//else 
		//return false;
	
	//}


}

So after more consideration I am thinking that my < operator isn't covering enough and that I need to cover more possibilities of what could happen something more like...

friend bool operator < (Records& node1, Records& node2)
{
if (node1.division > node2.division){
   if (node1.winPercentage > node2.winPercentage)
return true;
}
else if (node1.division == node2.division){
   if (node1.winPercentage > node2.winPercentage)
return true;
}else if(node1.division > node2.division){
   if (node1.winPercentage == node2.winPercentage)
return true;
else if (node1.division == node2.division){
   if (node1.winPercentage == node2.winPercentage)
return true;
}
else
return false;
}
This article has been dead for over six months. Start a new discussion instead.