user547616
user547616

Reputation: 51

sort by using a member of an object in c++

I'd like to use sort() to do the following

I'd like to std::sort P such that the lexicographic order among suffixes of T are preserved i.e., for any i < j we have that T[P[i]...n] is lex smaller than T[P[j]...n].

I'm able to do it when char[] T is a global variable by defining

bool myfunction (int i,int j) { 
  int m = i, l = j;
  while(m<n and l <n) {
      if(T[m] != T[l]) return (T[m]<T[l]);
      m++; l++;
  }
  return (m<l);
}

and calling std::sort(P, P+n, myfuction)

I'm in truble when T is a member of an object (and sort is called by a method of that object).

How can I define myfunction so that T is visible? Should it be member of that object? If yes, how? Thank you very much.

Edit: bool instead of int

Upvotes: 2

Views: 306

Answers (3)

Steve Jessop
Steve Jessop

Reputation: 279255

You probably need a functor object:

struct myfunctor {
    const char *T;
    size_t n;
    myfunctor(const char *T, size_t n) : T(T), n(n) {}
    bool operator()(int i, int j) {
        // stuff using T and n
    }
    // Optionally, something along these lines, I haven't tested it
    template <size_t N> myfunctor(const char (&x)[N]) : T(&x[0]), n(N) {}
    template <size_t N> myfunctor(char (&x)[N]) : T(&x[0]), n(N) {}
};

SomeObjectContainingT x;
std::sort(P, P+n, myfunctor(x.T, x.n));

Or if x.T is an actual array rather than just a pointer, the template constructors will capture the array size from the type, no need for a second parameter:

std::sort(P, P+n, myfunctor(x.T));

Edit: sorry, missed that T is private. I think you have two issues here, scope and accessibility. The functor solves the scope problem, now for the accessibility.

If you want external functions to access T, x must provide a means to access it. For example, it could return the functor object:

class SomeObjectContaining T {
    char T[23];
  public:
    myfunctor comparator() { return myfunctor(T); }
};

std::sort(P, P+n, x.comparator());

Or you could mess about with friend: define your functor class as a friend of SomeObjectContainingT, then pass the object to its constructor rather than the array.

Upvotes: 1

dbrank0
dbrank0

Reputation: 9476

As you guessed, one way to do it is by defining yourfunction() as a public member of that class.

Example:

#include <algorithm>
#include <vector>

using namespace std;

class T
{
private:
    int value;
public:
    T()
    {
        value = rand() % 100;
    }

    static bool Compare(const T &a, const T &b)
    {
        return a.value < b.value;
    }
};

int main(int argc, char** argv)
{
    vector<T> data;

    //add some data
    for (int i=0; i<10; i++)
        data.push_back(T());

    //sort using static method that can access private attributes
    std::sort(data.begin(), data.end(), T::Compare);
}

Upvotes: 2

If sort represents std::sort, the function that you are using as predicate is wrong for a couple of reasons, the first of which is that the returned type from the function should be a bool and not an int.

The next thing that is wrong is that the predicate is required to be consistent, that is, given two inputs a and b the result of predicate( a, b ) must be either true or false and always the same. If that condition is not met, the result of calling sort will be undefined, possibly including an infinite loop.

The approach (rather than the predicate itself) is probably not good either, as the number of times that the predicate will be called depends on the input data, and the results of the different calls to the predicate (until the algorithm thinks, that according to your partial order, the sequence is sorted).

Upvotes: 1

Related Questions