STL nuances - sort and remove_if

Hi Folks,

I am not able to understand as to when must an STL Predicate Function be implemented as a structure and when as a class?

I have a list of int* declared as -
list <int*> stlMyList;

int a = 10, b = 5, c = 15, d = 0;

stlMyList.push_back (&d);
stlMyList.push_back (&c);
stlMyList.push_back (&a);
stlMyList.push_back (&b);

I would like to -
A. "sort" it on the basis of the integer values (and not pointer values).
B. "remove" all but c from the list

Now, to remove all but "c", I call -
stlMyList.remove_if (bind2nd <not_equal_to <int*> >(not_equal_to <int*> (), (int*)&c));

where the remove_if predicate is defined as -
typedef int* PINT;

class AreNotEqual: public std::not_equal_to <int*>
{
bool operator () (const PINT & x, const PINT & y) const
{
return (*x) == (*y);
}
};

and to sort, I do this -
stlMyList.sort (std::greater <PINT> ());

where the sort predicate is defined as -
template <>
struct std::greater<int*>
{
bool operator()(const int* lhs, const int* rhs) const
{
return *lhs > *rhs;
}
};

So far, so good!

But, should I want the sort predicate defined as a class inheriting greater <int*> - the sort does not work!

So, this compiles, but, does not work -
typedef int* PINT;

class IsGreater : public std::greater<PINT>
{
bool operator() (const PINT & lhs, const PINT & rhs) const
{
return (*lhs) > (*rhs);
}
};

In fact, it is not even called!

1. What's amiss?
2. Where am I wrong?
3. Is it not correct to use a "class" for a sort predicate? :rolleyes:
4. Conversely, could I use struct for the remove_if predicate?

Thanks,
Sid!
[1948 byte] By [Siddhartha] at [2007-11-19 6:39:31]
# 1 Re: STL nuances - sort and remove_if
Interesting. Make the () operator public.

Kuphryn
kuphryn at 2007-11-11 0:30:18 >
# 2 Re: STL nuances - sort and remove_if
Interesting. Make the () operator public.

Promising point. :)

Unfortunately, similar result! :rolleyes:
Siddhartha at 2007-11-11 0:31:29 >
# 3 Re: STL nuances - sort and remove_if
Hi Folks,
I am not able to understand as to when must an STL Predicate Function be implemented as a structure and when as a class?In C++, there is no difference between a struct and a class except for

1) the default access specification for the members (struct is public, class it's private)

2) default inheritance access specification (when deriving from a base struct, the base struct is defaulted to public inheritance. When deriving from a base class, the base class is defaulted to private inheritance.

So I don't know why you distinguish between a struct and a class when they are essentially the same thing.
I have a list of int* declared as -
Hopefully that is only for an exercise. There is no reason whatsoever to have a list<int *> when all you need is list<int>.
But, should I want the sort predicate defined as a class inheriting greater <int*> - the sort does not work!You see that both of those examples are different, much more than the difference between "struct" and "class" (as I stated above, there is essentially no difference in C++ between the two).

So, this compiles, but, does not work -
typedef int* PINT;

class IsGreater : public std::greater<PINT>
{
bool operator() (const PINT & lhs, const PINT & rhs) const
{
return (*lhs) > (*rhs);
}
};

1) The operator() is private. How can it be accessed?

2) The equivalent is this using struct:

typedef int* PINT;

struct IsGreater : public std::greater<PINT>
{
private:
bool operator() (const PINT & lhs, const PINT & rhs) const
{
return (*lhs) > (*rhs);
}
};
Regards,

Paul McKenzie
Paul McKenzie at 2007-11-11 0:32:28 >
# 4 Re: STL nuances - sort and remove_if
In C++, there is no difference between a struct and a class except for

1) the default access specification for the members (struct is public, class it's private)

2) default inheritance access specification (when deriving from a base struct, the base struct is defaulted to public inheritance. When deriving from a base class, the base class is defaulted to private inheritance.

So I don't know why you distinguish between a struct and a class when they are essentially the same thing.
Hopefully that is only for an exercise. There is no reason whatsoever to have a list<int *> when all you need is list<int>.

1. The operator when declared as public still makes no difference (already mentioned in a reply to kuphryn
2. Yes, I believe too that there is no difference between class and struct. But, cannot explain the difference in behaviour.
3. Experiement on list <int*> is a proof-test for a concept that is to be applied to sorting list of any object, with the list being that of object-references.
Siddhartha at 2007-11-11 0:33:29 >
# 5 Re: STL nuances - sort and remove_if
2. Yes, I believe too that there is no difference between class and struct. But, cannot explain the difference in behaviour.Look at the struct and class that I posted, and take a look at the struct and class that you are saying behaves differently. The ones that you posted are different.

template <>
struct std::greater<int*>
//...
typedef int* PINT;
class IsGreater : public std::greater<PINT>
//...
Why do you say these are the same? They are clearly different. The struct and class I posted are exactly the same thing. Therefore if you took my struct, it should also cause an error if the class version causes an error.

So again, the problem is *not* class vs. struct. I will use your "struct" example that works, and use "class".

template <>
class std::greater<int*>
{
public:
bool operator()(const int* lhs, const int* rhs) const
{
return *lhs > *rhs;
}
};

That is equivalent to your struct example, not the class that you posted.

Anyway, wasn't your list::sort on pointers question answered here:

http://www.dev-archive.com/forum/showthread.php?t=330771&highlight=list+sort

?

Regards,

Paul McKenzie
Paul McKenzie at 2007-11-11 0:34:27 >
# 6 Re: STL nuances - sort and remove_if
The problem is that the std::list that ships with VC++ version 5 and 6
has non-standard predicated versions of sort , merge. I have version
5, so the following corresponds to that version of VC++. They probably
hold for version 6 also.

This is what is in the <list> header for VC++

typedef greater<_Ty> _Pr3;

void merge(_Myt& _X, _Pr3 _Pr) { /* body * }

void sort(_Pr3 _Pred) { /* body * }

Notice that the predicate type is greater<_Ty>. (That is why you
need to publically inherit from std::greater). Also notice that it
is passed by VALUE. Object Slicing will occur (you lose the
characteristics of the derived class). Even if the predicate was
passed by reference, it would not help. Operator () is not virtual in
std::greater , so the operator () in the base class (std::greater)
would be called, not the operator() in the derived class (IsGreater).

The predicate version of those functions should be templated.
Something like :

template <typename _Pr3_new>
void merge(_Myt& _X, _Pr3_new _Pr) { /* body */ }

template <typename _Pr3_new>
void sort(_Pr3_new _Pred) { /* body * }
Philip Nicoletti at 2007-11-11 0:35:26 >
# 7 Re: STL nuances - sort and remove_if
Look at the struct and class that I posted, and take a look at the struct and class that you are saying behaves differently. The ones that you posted are different.

1. My question is not about sorting a list.
2. Yes, this struct and class are different, no doubt. Perhaps, I threw in a Red Herring there.

I need an explanation as to why sort can have a struct/class as a predicate without inheriting, whilst the remove_if needs a class that inherits from std::not_equal_to <int*>

Or to express it differently again - why can the predicate to remove_if not be
struct std::not_equal_to <int*>
{
bool operator () (const PINT & x, const PINT & y) const
{
return (*x) == (*y);
}
};

instead of

class AreNotEqual: public std::not_equal_to <int*>
{
bool operator () (const PINT & x, const PINT & y) const
{
return (*x) == (*y);
}
};
Siddhartha at 2007-11-11 0:36:34 >
# 8 Re: STL nuances - sort and remove_if
Operator () is not virtual in
std::greater , so the operator () in the base class (std::greater)
would be called, not the operator() in the derived class (IsGreater).

Yes, dude!

Perhaps, in here lies the key!

Thanks for that interesting analysis. Let me know if you can enlighten me any more on the last post.

Thanks,
Sid! :wave:
Siddhartha at 2007-11-11 0:37:34 >