C++ std::sort with predicate function in Class
I want to sort vector of certain struct with certain order in certain class. I've wrote definition of struct and predicate function in a class and run std::sort in a method of the class with these struct and function. But compilation error has occurred. gcc version is 4.0.1 and OS is Mac OSX. The code is following:
class sample {
public:
struct s {
开发者_开发问答 int x;
int y;
};
bool cmp (struct s a, struct s b) {
if (a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}
int func(void) {
std::vector <struct s> vec;
// ...
sort(vec.begin(), vec.end(), cmp); // compilation error
// ...
return 0;
}
};
int main(void) {
sample *smp = new sample();
smp->func();
return 0;
}
Error message was huge and complex. So this is first two lines of it.
sortSample.cpp: In member function 'int sample::func()':
sortSample.cpp:51: error: argument of type 'bool (sample::)(sample::s, sample::s)' does not match 'bool (sample::*)(sample::s, sample::s)' ...
Instead of above approach, the code could run correctly with following ways.
- Define
struct s
and functioncmp()
outside ofclass sample
. - Remove
function
cmp()
and define operator overloading of<
instruct s
.
Sample code of each approach is bellow.
1)
struct s {
int x;
int y;
};
bool cmp (struct s a, struct s b) {
if (a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}
class sample {
// ...
2)
struct s {
int x;
int y;
bool operator<(const struct s & a) const {
if (x == a.x)
return y < a.y;
else
return x < a.x;
}
};
Can anyone tell a mechanism of this behavior? Why does first approach invokes compilation error?
Thanks.
In the first case cmp
is declared as a member function of the class sample
and hence requires this
pointer for calling it. Since the this
pointer is not available compiler is complaining about it. You can make it work by declaring cmp
as static
function since static functions do not require this pointer for calling. In the second case, since cmp is declared as a stand-alone function again it will behave same as static function. In the third case (with overloaded operator), the sort algorithm will take care of calling the function for each object in the vector and hence it compiles.
Since cmp
is not related to any particular instance of sample, make it a static member function.
The third approach which can be listed in your possibilities is using operator():
bool operator() (const s& a, const s& b) const
{
if (a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}
sort(vec.begin(), vec.end(), *this);
I think defining cmp
outside the class is best, because you should only make a function a member function when you need it to access some private feature in the class, and logically it feels right for it to be there. cmp
is just a utility function that provides your class sample
with functionality for its implementation, but it doesn't actually need to access private members. Furthermore, it's probably not going to be invoked in the context of an object (its only operations work on its parameters; nothing on the this
pointer), nor must it be invoked in the context of a class sample::cmp
. While it may seem like a trivial point, giving functions or code in general unnecessary breadth of access can be the start of the source of many a software bug or design convolution.
The added benefit of doing the above is that your invocation of std::sort
will work, which answers your question.
精彩评论