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

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 function cmp()
outside of class sample.
Remove
function cmp() and define operator
overloading of < in struct 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.

Related

Find if structures with same values exist in vector array

I want to check if there are structures with the same values in the vector array. May someone explain to me how should I do this?
struct mineCoordinate{
int x;
int y;
};
std::vector<mineCoordinate> mines; // vector array
if(std::find(mines.begin(), mines.end(), mineCoordinate{userInputX,userInputY}) != mines.end()) {
//do something if true.}
As you can see I tried std::find function, and I think it should work (
this is the answer to most of these questions like mine). The only condition was to compare the same objects
What seems to be missing from your code is a definition of what it means for two of your mineCoordinate objects to be equal. If you add this
bool operator==(const mineCoordinate& a, const mineCoordinate& b)
{
return a.x == b.x && a.y == b.y;
}
then I think it will work too.
You might have thought that this definition is so obvious that it doesn't need to be explicitly defined, but that is not correct.
If you are using C++20, can you default the == operator:
struct mineCoordinate
{
int x;
int y;
bool operator==(const mineCoordinate&) const = default;
};

C++ Can I overload the bracket [] operator to do different things if it on the LHS vs RHS of an assignment?

I am looking to accomplish the following:
int x, y, z;
foo[x] = y; acts like do_this(x,y);
z = foo[x]; acts like z = do_that(x)
I can accomplish the first with a Foo class and a Helper class, where the operator[] returns by value a Helper class constructed with x, and the operator= for the Helper class is defined to run do_this(this->x, y). Like below:
class Foo {
public:
Helper operator[](int x) {
return Helper(x);
}
};
class Helper {
public:
Helper(x) {
this->x = x;
}
void operator=(int y) {
do_this(this->x, y);
}
private:
int x;
};
What I can't figure out is how to accomplish (2). Is there a way to overload the operator[] so that it knows if it was used on the lhs vs the rhs?
Yes - give your Helper class a conversion function to int:
class Helper {
public:
Helper(x){
this->x = x;
}
Helper& operator= (int y) {
do_this(this->x, y);
return *this;
}
operator int() const {
return do_that(this->x);
}
private:
int x;
};
This will also allow other uses like product *= foo[x]; or func_taking_int(foo[x]), etc.
One potential catch is that some uses of auto or function templates would still just keep the type Helper, which might not be what's wanted - so users of Foo should still understand that this proxy sugar is going on. It could also be helpful to have some alternative syntax to explicitly get the int value for cases like that, in either Foo or Helper.
I'm not sure I've understood what you actually want to do, but you are might be able to use the const version of the operator[] vs. the non-const version. For example:
struct Foo {
Z operator [] (int x) const { // this last const is important
return do_that(x);
}
Helper operator [] (int x) {
// as you yourself have written.
}
};
There are more tips and tricks to this, for forwarding arguments perfectly (a.k.a "perfect forwarding",) for being "const correct", and many other small things, but the gist of it is the above.

Sort structs depending on non-static value (C++)

I have an EnemyRhombus class. It is a unit, which can move to different points on the map.
I want to process points, to which it can move, in order of increasing distance to them.
To do it I want to sort the points.
Code 1:
class EnemyRhombus
{
public:
int x,y;
int dist(Point p)
{
int dx=abs(p.x-x);
int dy=abs(p.y-y);
return dx+dy-min(dx,dy);
}
bool points_cmp(Point f, Point s)
{
return dist(f)<dist(s);
}
void move()
{
vector<Point> candidates;
//...
sort(candidates.begin(),candidates.end(),points_cmp);
}
}
does not compile. Prints
[Error] no matching function for call to 'sort(std::vector::iterator, std::vector::iterator, < unresolved overloaded function type>)'
Code 2:
class EnemyRhombus
{
public:
int x,y;
static int dist(Point p, int tx, int ty)
{
int dx=abs(p.x-tx);
int dy=abs(p.y-ty);
return dx+dy-min(dx,dy);
}
template<int X, int Y> static bool points_cmp(Point f, Point s)
{
return dist(f,X,Y)<dist(s,X,Y);
}
void move()
{
vector<Point> candidates;
//...
sort(candidates.begin(),candidates.end(),points_cmp<x,y>);
}
}
produces errors:
[Error] 'EnemyRhombus::x' cannot appear in a constant-expression
[Error] 'EnemyRhombus::y' cannot appear in a constant-expression
How can I solve the problem?
Usage of examples from answers may produce errors and warning, saying that c++ 11 is enabled by default, which is not true (At least, in orwell dev-cpp).
To make them work, one should add -std=c++11 to compiler commands.
(Tools->Compiler Options -> Genera in my case)
You can use a C++11 lambda as well apart from using static/out-of-class functions or use the method suggested by P0W.
std::sort(candidates.begin(),candidates.end(),
[&](Point f, Point s) { return dist(f) < dist(s); }
);
The lambda takes care of the order in which to sort.
std::sort can't use points_cmp because it doesn't have this pointer, as you are trying to pass a pointer to a member function, so
If your compiler support C++11, you can use :
std::sort( candidates.begin(),
candidates.end(),
bind(&EnemyRhombus::points_cmp, this, _1, _2));
Or else make function static or a free function out of class
In case of Code1 c++14 alows to do even better:
std::sort(candidates.begin(), candidates.end(), [this] (auto a, auto b) {
return points_cmp(a, b);
});
You can consider a lambda to sort the vector<Point> in a custom way; the customized sorting order can be specified in the body of the lambda (note that lambdas are available starting from C++11):
void move()
{
std::vector<Point> candidates;
//...
//
// Specify your custom sorting using a lambda:
//
std::sort(candidates.begin(), candidates.end(), [this](Point f, Point s) {
return dist(f) < dist(s);
});
}
Note also that in the lambda you must use the [this] capture syntax, since you are calling the dist() non-static member function inside the body of the lambda.
In addition, if your Point class is not cheap to copy, consider passing it using const& (to avoid useless "deep copies"):
std::sort(candidates.begin(),
candidates.end(),
[this](const Point& f, const Point& s) {
return dist(f) < dist(s);
}
);

How to create a set with my customized comparison in c++

Could someone explain me what is going on in this example here?
They declare the following:
bool fncomp (int lhs, int rhs) {return lhs<rhs;}
And then use as:
bool(*fn_pt)(int,int) = fncomp;
std::set<int,bool(*)(int,int)> sixth (fn_pt)
While the example for the sort method in algorithm library here
can do like this:
bool myfunction (int i,int j) { return (i<j); }
std::sort (myvector.begin()+4, myvector.end(), myfunction);
I also didn't understand the following:
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
this keyword operator (not being followed by an operator as in a op. overload)... what is the meaning of it? Any operator applied there will have that behavior? And this const modifier... what is the effect caused by it?
I was trying to make a set of C-style string as follows:
typedef struct
{
char grid[7];
} wrap;
bool compare(wrap w1, wrap w2)
{
return strcmp(w1.grid, w2.grid) == -1;
}
set <wrap, compare> myset;
I thought I could create a set defining my sorting function in a similar as when I call sort from algorithm library... once it didn't compile I went to the documentation and saw this syntax that got me confused... Do I need to declare a pointer to a function as in the first example i pasted here?
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
Defines a functor by overloading the function call operator. To use a function you can do:
int main() {
std::set <wrap, bool (*)(wrap,wrap)> myset(compare);
return 0;
}
Another alternative is to define the operator as a part of the wrap class:
struct wrap {
char grid[7];
bool operator<(const wrap& rhs) const {
return strcmp(this->grid, rhs.grid) == -1;
}
};
int main() {
wrap a;
std::set <wrap> myset;
myset.insert(a);
return 0;
}
You're almost there... here's a "fixed" version of your code (see it run here at ideone.com):
#include <iostream>
#include <set>
#include <cstring>
using namespace std;
typedef struct
{
char grid[7];
} wrap;
bool compare(wrap w1, wrap w2) // more efficient: ...(const wrap& e1, const wrap# w2)
{
return strcmp(w1.grid, w2.grid) < 0;
}
set <wrap, bool(*)(wrap, wrap)> myset(compare);
int main() {
wrap w1 { "abcdef" };
wrap w2 { "ABCDEF" };
myset.insert(w1);
myset.insert(w2);
std::cout << myset.begin()->grid[0] << '\n';
}
"explain [to] me what is going on in this example"
Well, the crucial line is...
std::set<wrap, bool(*)(wrap, wrap)> myset(compare);
...which uses the second template parameter to specify the type of function that will perform comparisons, then uses the constructor argument to specify the function. The set object will store a pointer to the function, and invoke it when it needs to compare elements.
"the example for the sort method in algorithm library..."
std::sort in algorithm is great for e.g. vectors, which aren't automatically sorted as elements are inserted but can be sorted at any time. std::set though needs to maintain sorted order constantly, as the logic for inserting new elements, finding and erasing existing ones etc. all assumes the existing elements are always sorted. Consequently, you can't apply std::sort() to an existing std::set.
"this keyword operator (not being followed by an operator as in a op. overload)... what is the meaning of it? Any operator applied there will have that behavior? And this const modifier... what is the effect caused by it?
operator()(...) can be invoked on the object using the same notation used to call a function, e.g.:
classcomp my_classcomp;
if (my_classcomp(my_int1, my_int_2))
std::cout << "<\n";
As you can see, my_classcomp is "called" as if it were a function. The const modifier means that the code above works even if my_classcomp is defined as a const classcomp, because the comparison function does not need to modify any member variables of the classcomp object (if there were any data members).
You almost answered your question:
bool compare(wrap w1, wrap w2)
{
return strcmp(w1.grid, w2.grid) == -1;
}
struct wrap_comparer
{
bool operator()(const wrap& _Left, const wrap& _Right) const
{
return strcmp(_Left.grid, _Right.grid) == -1;
}
};
// declares pointer to function
bool(*fn_pt)(wrap,wrap) = compare;
// uses constructor with function pointer argument
std::set<wrap,bool(*)(wrap,wrap)> new_set(fn_pt);
// uses the function directly
std::set<wrap,bool(*)(wrap,wrap)> new_set2(compare);
// uses comparer
std::set<wrap, wrap_comparer> new_set3;
std::sort can use either a function pointer or a function object (http://www.cplusplus.com/reference/algorithm/sort/), as well as std::set constructor.
const modifier after function signature means that function can't modify object state and so can be called on a const object.

How can it be useful to overload the "function call" operator?

I recently discovered that in C++ you can overload the "function call" operator, in a strange way in which you have to write two pair of parenthesis to do so:
class A {
int n;
public:
void operator ()() const;
};
And then use it this way:
A a;
a();
When is this useful?
This can be used to create "functors", objects that act like functions:
class Multiplier {
public:
Multiplier(int m): multiplier(m) {}
int operator()(int x) { return multiplier * x; }
private:
int multiplier;
};
Multiplier m(5);
cout << m(4) << endl;
The above prints 20. The Wikipedia article linked above gives more substantial examples.
There's little more than a syntactic gain in using operator() until you start using templates. But when using templates you can treat real functions and functors (classes acting as functions) the same way.
class scaled_sine
{
explicit scaled_sine( float _m ) : m(_m) {}
float operator()(float x) const { return sin(m*x); }
float m;
};
template<typename T>
float evaluate_at( float x, const T& fn )
{
return fn(x);
}
evaluate_at( 1.0, cos );
evaluate_at( 1.0, scaled_sine(3.0) );
A algorithm implemented using a template doesn't care whether the thing being called is a function or a functor, it cares about the syntax. Either standard ones (e.g. for_each()) or your own. And functors can have state, and do all kinds of things when they are called. Functions can only have state with a static local variable, or global variables.
If you're making a class that encapsulates a function pointer, this might make the usage more obvious.
The compiler can also inline the functor and the function call. It cannot inline a function pointer, however. This way, using the function call operator can significantly improve performance when it is used for example with the standard C++ libary algorithms.
For example for implementing generators:
// generator
struct Generator {
int c = 0;
virtual int operator()() {
return c++;
}
};
int sum(int n) {
Generator g;
int res = 0;
for( int i = 0; i < n; i++ ) {
res += g();
}
return res;
}
I see potential to yet one exotic use:
Suppose you have object of unknown type and have to declare another variable of same type, like this:
auto c=decltype(a*b)(123);
When such pattern used extensively, decltype become very annoying.
This case can occur when using some smart type system that automatically invent type of result of functions and operators based on types of arguments.
Now, if each specialization of each type of that type system equipped with
magic definition of operator() like this:
template<????> class Num<???>{
//specific implementation here
constexpr auto operator()(auto...p){return Num(p...);}
}
decltype() no more needed, you can write simply:
auto c=(a*b)(123);
Because operator() of object redirects to constructor of its own type.