I want to sort a vector whose member is pair<int, int>. So I write a function to compare two pairs. It works when the function is in the outer space. But it throws an error when I try to write it as a member function. So why the error is thrown?
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <stack>
#include <queue>
using std::pair;
using std::vector;
using std::sort;
using std::endl;
using std::cout;
// bool cmp(const pair<int, int>& p1, const pair<int, int>& p2)
// {
// return p1.second < p2.second;
// }
class test
{
public:
bool cmp(const pair<int, int>& p1, const pair<int, int>& p2)
{
return p1.second < p2.second;
}
void my_sort(vector <pair<int, int>> &data)
{
sort(data.begin(), data.end(), cmp);
}
};
int main()
{
vector <pair<int, int>> data;
for(int i=10; i>=0; i--)
{
data.push_back(pair<int, int>(10-i, i));
}
test a;
a.my_sort(data);
// sort(data.begin(), data.end(), cmp);
for (auto &&i : data)
{
cout << i.first << '\t' << i.second << endl;
}
return 0;
}
CodePudding user response:
So why the error is thrown?
Because cmp
is a non-static memeber function and requires an object to be called on and so cannot be used as the comparison function object in std::sort
.
To solve this you can either make cmp
a static
member function or use a lambda
or implement cmp
outside the class(at global namespace) as shown below:
Method 1
Make cmp
a static
member function.
class test{
//other members
public:
//make cmp static
static bool cmp(const pair<int, int>& p1, const pair<int, int>& p2)
{
return p1.second < p2.second;
}
void my_sort(vector <pair<int, int>> &data)
{
//-----------------------------------------vvvvvvvvv--->cmp doesn't require an object to be called
sort(data.begin(), data.end(), test::cmp);
}
};
Method 2
Make cmp
a free function.
//free function cmp outside class test
bool cmp(const pair<int, int>& p1, const pair<int, int>& p2)
{
return p1.second < p2.second;
}
class test
{
//code here as before
void my_sort(vector <pair<int, int>> &data)
{
//-------------------------------------vvv---->no change here
sort(data.begin(), data.end(), cmp);
}
};
Method 3
You can also use lambda
as shown below:
class test
{
public:
void my_sort(vector <pair<int, int>> &data)
{
//-------------------------------------vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv-->use lambda
sort(data.begin(), data.end(), [](const pair<int, int>& p1, const pair<int, int>& p2)->bool
{
return p1.second < p2.second;
}
);
}
};
CodePudding user response:
In order to use a member function with std::sort the function must be declared as static member function
CodePudding user response:
To call a non-static member function you need to provide an object for which the function will be called.
Just define within the class test
an operator-function and call the function std::sort
within the member function my_sort
the following way
std::sort( std::begin( data ), std::end( data ), *this );
Here is a demonstrative program.
#include <iostream>
#include <utility>
#include <vector>
#include <iterator>
#include <algorithm>
class test
{
public:
bool operator ()( const std::pair<int, int>& p1, const std::pair<int, int>& p2 ) const
{
return p1.second < p2.second;
}
void my_sort( std::vector<std::pair<int, int>> &data ) const
{
std::sort( std::begin( data ), std::end( data ), *this );
}
};
int main()
{
std::vector <std::pair<int, int>> data;
for(int i=10; i>=0; i--)
{
data.push_back( std::pair<int, int>( 10-i, i) );
}
test a;
a.my_sort(data);
for (auto &&i : data)
{
std::cout << i.first << '\t' << i.second << std::endl;
}
}
You can also call the function the following ways
test().my_sort( data );
or
std::sort( std::begin( data ), std::end( data ), test() );
Otherwise declare the member functions as static member functions. For example
#include <iostream>
#include <utility>
#include <vector>
#include <iterator>
#include <algorithm>
class test
{
public:
static bool cmp( const std::pair<int, int>& p1, const std::pair<int, int>& p2 )
{
return p1.second < p2.second;
}
static void my_sort(std::vector <std::pair<int, int>> &data )
{
std::sort( std::begin( data ), std::end( data ), cmp );
}
};
int main()
{
std::vector <std::pair<int, int>> data;
for(int i=10; i>=0; i--)
{
data.push_back( std::pair<int, int>( 10-i, i) );
}
test::my_sort(data);
// std::sort( std::begin( data ), std::end( data ), test::cmp);
for (auto &&i : data)
{
std::cout << i.first << '\t' << i.second << std::endl;
}
}