1

I have a class cl1:

class c1
{
long double * coords;
...
}

I also have a second class cl2:

class cl2
{
vector<cl1*> cl1_vec;
unsigned int d;
...
}

I would like to sort cl1_vec, from cl2, based on coords[d], using the sort function for vectors. So i could have something like

sort(cl2_inst->cl1_vec.begin(),cl2_inst->cl1_vec.end(), ??? );

I tried approches like

sort the 'std::vector' containing classes

C++ std::sort with predicate function in Class

but i couldn't make my way to solving this.

Thanks for any help that comes this way.

The code i've tried:

class cl1 {
    public:
        long double* coords;

        cl1(long double *, unsigned int);
        cl1();
        cl1(const cl1& orig);
        virtual ~cl1();        
};

class cl2 {

    public:

    unsigned int d;

    vector<cl1*> cl1_vec;

    //the srting functions
    static bool compareMyDataPredicate(cl1* lhs, cl1* rhs)
    {
        return (lhs->coords[d] < rhs->coords[d]);
    };
    // declare the functor nested within MyData.
    struct compareMyDataFunctor : public binary_function<my_point*, my_point*, bool>
    {
        bool operator()( cl1* lhs, cl1* rhs)
        {
            return (lhs->coords[d] < rhs->coords[d]);
        }
    };
    ...
    ...
}

then in main

    std::sort(cl2_inst->cl1_vec.begin(),cl2_inst->cl1_vec.end(),cl2::compareMyDataPredicate() );
Community
  • 1
  • 1
0gap
  • 21
  • 7
  • 1
    Please post the code that you tried, and describe what didn't work about it. – Oliver Charlesworth Jun 17 '12 at 12:24
  • I will edit the question and pot the code i 've tried – 0gap Jun 17 '12 at 12:28
  • What do you want to sort ? long double * coords ? What type is cl1? Typo? – Martin Jun 17 '12 at 12:30
  • the cl1 and cl2 are classes defined in separate .hpp and .cpp files. Dots(...) in cl2 are for constructors and functions that didn't post. – 0gap Jun 17 '12 at 12:39
  • I think my problem is with d that i want to use, which is a cl2 member. Coords is a long double array. So the cl1 instances in cl1_vec should be sorted using d as an index for their coords array. – 0gap Jun 17 '12 at 12:46
  • @0gap Since you didnt post the errors, try replacing `cl2::compareMyDataPredicate()` inside sort(..) with `cl2::compareMyDataPredicate`. You shouldn't 'call' the function, just pass a pointer to it. – UltraInstinct Jun 17 '12 at 12:54
  • Oh i'm sorry for this. The errors i get is invalid use of non-static data member ‘cl2::d’ for all 4 calls of d in both compareMyDataPredicate and binary_function – 0gap Jun 17 '12 at 12:57

2 Answers2

1

The error is because you are accessing a non-static member d from a static context of the comparator function. Use the second approach, in the following way:

  • Provide a constructor to that struct, which takes a parameter unsigned int and sets a member to that value.
  • Create an object of type compareMyDataFunctor, and pass in the value of d to the constructor.
  • Use this object for sorting (3rd argument to std::sort)
UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
  • i gave the unswer to LiKao since he provided the code. I wish i could mark two answers. Solution:I pasted the code from LiKao into cl2 and did what you said. Created in main an instance of the struct(cl2::struct) and used it as the 3rd argument. To tell you the truth i'm not such an experienced programmer and had never even heard of functors. Thank you all. It worked. – 0gap Jun 17 '12 at 13:37
0

I am not sure about the problems, because you were not precise enough about what exactly "does not work" means in your case (does not compile, does compile but does not sort etc). In case it does not compile (most likely guess) you did not post the error messages, which also makes finding and explaining the problem very hard.

Here are some guesses based on the code you posted:

Both static function as well as the functor use the member d to decide which column to sort on. However d is an instance variable, so it is not available for anything which is static. Neither the functor nor the static member function would know which of the possible ds to use, as there is one d per instance.

The best way to do this without resorting to C++11 features (lamdas) is to provide a constructor to the functor which takes the d you are planning to use. Something like this:

struct compareMyDataFunctor : public binary_function<cl1*, cl1*, bool>
{
    compareMyDataFunctor( unsigned int d ) : d( d ) {}
    bool operator()( cl1* lhs, cl1* rhs)
    {
        return (lhs->coords[d] < rhs->coords[d]);
    }

    unsigned int d;
};

This should do the trick.

There are some more things wrong with the code you posted though:

  • Arrays should be indexed using type size_t not a unsigned int. Same goes for std::vectors
  • The types in the std::binary_function instantiation do not match the actual types in the method (may be a problem of reducing the code).
  • Do not use using namespace std (I assume you do from the declarations in your code).
  • Functors such as these should take parameters as const-reference, not by value.

That's all I can think of. Next time try to present short, self contained, complete examples, then people will not have to resort to guessing.

LiKao
  • 10,408
  • 6
  • 53
  • 91