Home > Mobile >  why it throws an error when I pass a member function to sort()
why it throws an error when I pass a member function to sort()

Time:05-17

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);
       }
};

Demo 1

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);
    }
};

Demo 2

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;
            
        }
        );
    }
};

Demo 3

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;
    }
}
  • Related