Sort structs depending on non-static value (C++) - 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);
}
);

Related

when I am using this comparator function without static keyword it giving error [duplicate]

trying to compile the following code I get this compile error, what can I do?
ISO C++ forbids taking the address of
an unqualified or parenthesized
non-static member function to form a
pointer to member function.
class MyClass {
int * arr;
// other member variables
MyClass() { arr = new int[someSize]; }
doCompare( const int & i1, const int & i2 ) { // use some member variables }
doSort() { std::sort(arr,arr+someSize, &doCompare); }
};
doCompare must be static. If doCompare needs data from MyClass you could turn MyClass into a comparison functor by changing:
doCompare( const int & i1, const int & i2 ) { // use some member variables }
into
bool operator () ( const int & i1, const int & i2 ) { // use some member variables }
and calling:
doSort() { std::sort(arr, arr+someSize, *this); }
Also, isn't doSort missing a return value?
I think it should be possible to use std::mem_fun and some sort of binding to turn the member function into a free function, but the exact syntax evades me at the moment.
EDIT: Doh, std::sort takes the function by value which may be a problem. To get around this wrap the function inside the class:
class MyClass {
struct Less {
Less(const MyClass& c) : myClass(c) {}
bool operator () ( const int & i1, const int & i2 ) {// use 'myClass'}
MyClass& myClass;
};
doSort() { std::sort(arr, arr+someSize, Less(*this)); }
}
As Andreas Brinck says, doCompare must be static (+1). If you HAVE TO have a state in your comparator function (using the other members of the class) then you'd better use a functor instead of a function (and that will be faster):
class MyClass{
// ...
struct doCompare
{
doCompare( const MyClass& info ) : m_info(info) { } // only if you really need the object state
const MyClass& m_info;
bool operator()( const int & i1, const int & i2 )
{
// comparison code using m_info
}
};
doSort()
{ std::sort( arr, arr+someSize, doCompare(*this) ); }
};
Using a functor is always better, just longer to type (that can be unconvenient but oh well...)
I think you can also use std::bind with the member function but I'm not sure how and that wouldn't be easy to read anyway.
UPDATE 2014: Today we have access to c++11 compilers so you could use a lambda instead, the code would be shorter but have the exact same semantic.
The solution proposed by Rob is now valid C++11 (no need for Boost):
void doSort()
{
using namespace std::placeholders;
std::sort(arr, arr+someSize, std::bind(&MyClass::doCompare, this, _1, _2));
}
Indeed, as mentioned by Klaim, lambdas are an option, a bit more verbose (you have to "repeat" that the arguments are ints):
void doSort()
{
std::sort(arr, arr+someSize, [this](int l, int r) {return doCompare(l, r); });
}
C++14 supports auto here:
void doSort()
{
std::sort(arr, arr+someSize, [this](auto l, auto r) {return doCompare(l, r); });
}
but still, you declared that arguments are passed by copy.
Then the question is "which one is the most efficient". That question was treated by Travis Gockel: Lambda vs Bind. His benchmark program gives on my computer (OS X i7)
Clang 3.5 GCC 4.9
lambda 1001 7000
bind 3716166405 2530142000
bound lambda 2438421993 1700834000
boost bind 2925777511 2529615000
boost bound lambda 2420710412 1683458000
where lambda is a lambda used directly, and lambda bound is a lambda stored in a std::function.
So it appears that lambdas are a better option, which is not too much of a surprise since the compiler is provided with higher level information from which it can make profit.
You can use boost::bind:
void doSort() {
std::sort(arr,arr+someSize, boost::bind(&MyClass::doCompare, this, _1, _2));
}
There is a way to do what you want, but you need to use a small adaptor. As the STL doesn't write it for you, can can write it yourself:
template <class Base, class T>
struct adaptor_t
{
typedef bool (Base::*method_t)(const T& t1, const T& t2));
adaptor_t(Base* b, method_t m)
: base(b), method(m)
{}
adaptor_t(const adaptor_t& copy) : base(copy.base), method(copy.method) {}
bool operator()(const T& t1, const T& t2) const {
return (base->*method)(t1, t2);
}
Base *base;
method_t method;
}
template <class Base, class T>
adaptor_t<Base,T> adapt_method(Base* b, typename adaptor_t<Base,T>::method_t m)
{ return adaptor_t<Base,T>(b,m); }
Then, you can use it:
doSort() { std::sort(arr,arr+someSize, adapt_method(this, &doCompare)); }
The third argument in the calling of std::sort() is not compatible to the function pointer needed by std::sort(). See my answer to another question for a detailed explanation for why a member function signature is different from a regular function signature.
just make your helper function, static which you are going to pass inside the sort function.
for e.g
struct Item
{
int val;
int id;
};
//Compare function for our Item struct
static bool compare(Item a, Item b)
{
return b.val>a.val;
}
Now you can pass this inside your sort function
A very simple way to effectively use a member function is to use operator<. That is, if you have a function called compare, you can call it from operator<. Here is a working example:
class Qaz
{
public:
Qaz(int aX): x(aX) { }
bool operator<(const Qaz& aOther) const
{
return compare(*this,aOther);
}
static bool compare(const Qaz& aP,const Qaz& aQ)
{
return aP.x < aQ.x;
}
int x;
};
Then you don't even need to give the function name to std::sort:
std::vector<Qaz> q;
q.emplace_back(8);
q.emplace_back(1);
q.emplace_back(4);
q.emplace_back(7);
q.emplace_back(6);
q.emplace_back(0);
q.emplace_back(3);
std::sort(q.begin(),q.end());
Updating Graham Asher answer, as you don't need the compare but can use the less operator directly.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Qaz {
public:
Qaz(int aX): x(aX) { }
bool operator<(const Qaz& aOther) const {
return x < aOther.x;
}
int x;
};
int main() {
std::vector<Qaz> q;
q.emplace_back(8);
q.emplace_back(1);
q.emplace_back(4);
q.emplace_back(7);
q.emplace_back(6);
q.emplace_back(0);
q.emplace_back(3);
std::sort(q.begin(),q.end());
for (auto& num : q)
std::cout << num.x << "\n";
char c;
std::cin >> c;
return 0;
}

compare function in lower bound

I have following structure
enum quality { good = 0, bad, uncertain };
struct Value {
int time;
int value;
quality qual;
};
class MyClass {
public:
MyClass() {
InsertValues();
}
void InsertValues();
int GetLocationForTime(int time);
private:
vector<Value> valueContainer;
};
void MyClass::InsertValues() {
for(int num = 0; num < 5; num++) {
Value temp;
temp.time = num;
temp.value = num+1;
temp.qual = num % 2;
valueContainer.push_back(temp);
}
}
int MyClass::GetLocationForTime(int time)
{
// How to use lower bound here.
return 0;
}
In above code I have been thrown with lot of compile errors. I think I am doing wrong here I am new to STL programming and can you please correct me where is the error? Is there better to do this?
Thanks!
The predicate needs to take two parameters and return bool.
As your function is a member function it has the wrong signature.
In addition, you may need to be able to compare Value to int, Value to Value, int to Value and int to int using your functor.
struct CompareValueAndTime
{
bool operator()( const Value& v, int time ) const
{
return v.time < time;
}
bool operator()( const Value& v1, const Value& v2 ) const
{
return v1.time < v2.time;
}
bool operator()( int time1, int time2 ) const
{
return time1 < time2;
}
bool operator()( int time, const Value& v ) const
{
return time < v.time;
}
};
That is rather cumbersome, so let's reduce it:
struct CompareValueAndTime
{
int asTime( const Value& v ) const // or static
{
return v.time;
}
int asTime( int t ) const // or static
{
return t;
}
template< typename T1, typename T2 >
bool operator()( T1 const& t1, T2 const& t2 ) const
{
return asTime(t1) < asTime(t2);
}
};
then:
std::lower_bound(valueContainer.begin(), valueContainer.end(), time,
CompareValueAndTime() );
There are a couple of other errors too, e.g. no semicolon at the end of the class declaration, plus the fact that members of a class are private by default which makes your whole class private in this case. Did you miss a public: before the constructor?
Your function GetLocationForTime doesn't return a value. You need to take the result of lower_bound and subtract begin() from it. The function should also be const.
If the intention of this call is to insert here, then consider the fact that inserting in the middle of a vector is an O(N) operation and therefore vector may be the wrong collection type here.
Note that the lower_bound algorithm only works on pre-sorted collections. If you want to be able to look up on different members without continually resorting, you will want to create indexes on these fields, possibly using boost's multi_index
One error is that the fourth argument to lower_bound (compareValue in your code) cannot be a member function. It can be a functor or a free function. Making it a free function which is a friend of MyClass seems to be the simplest in your case. Also you are missing the return keyword.
class MyClass {
MyClass() { InsertValues(); }
void InsertValues();
int GetLocationForTime(int time);
friend bool compareValue(const Value& lhs, const Value& rhs)
{
return lhs.time < rhs.time;
}
Class keyword must start from lower c - class.
struct Value has wrong type qualtiy instead of quality
I dont see using namespace std to use STL types without it.
vector<value> - wrong type value instead of Value
Etc.
You have to check it first before posting here with such simple errors i think.
And main problem here that comparison function cant be member of class. Use it as free function:
bool compareValue(const Value lhs, const int time) {
return lhs.time < time ;
}
class is the keyword and not "Class":
class MyClass {
And its body should be followed by semicolon ;.
There can be other errors, but you may have to paste them in the question for further help.
You just want to make compareValue() a normal function. The way you have implemented it right now, you need an object of type MyClass around. The way std::lower_bound() will try to call it, it will just pass in two argument, no extra object. If you really want it the function to be a member, you can make it a static member.
That said, there is a performance penalty for using functions directly. You might want to have comparator type with an inline function call operator:
struct MyClassComparator {
bool operator()(MyClass const& m0, MyClass const& m1) const {
return m0.time < m1.time;
}
};
... and use MyClassComparator() as comparator.

Using same function for sorting a vector<X> and custom comparator in set<X>

This might sound like a stupid problem but I wondered for a long time is there a better way that this:
struct X
{
int a;
int b;
};
bool sortComp(const X first, const X second)
{
if (first.a!=second.a)
return (first.a<second.a);
else
return (first.b<second.b);
}
class setComp
{
public:
bool operator() (const X first, const X second) const
{
if (first.a!=second.a)
return (first.a<second.a);
else
return (first.b<second.b);
}
};
int main()
{
vector<X> v;
set<X, setComp> s;
sort(begin(v), end(v),sortComp);
}
As you see I implement the same functionality twice, once for sorting, and once for implicit sorting in the set. Is there a way to avoid code duplication?
Sure, just choose one of both and change the call of the other.
// choosing the function object
sort(begin(v), end(v), setComp()); // create setComp, sort will call operator()
// choosing the function
set<X, bool(*)(const X, const X)> s(sortComp); // pass function pointer
I personally would recommend the functor version.

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.

problem sorting using member function as comparator

trying to compile the following code I get this compile error, what can I do?
ISO C++ forbids taking the address of
an unqualified or parenthesized
non-static member function to form a
pointer to member function.
class MyClass {
int * arr;
// other member variables
MyClass() { arr = new int[someSize]; }
doCompare( const int & i1, const int & i2 ) { // use some member variables }
doSort() { std::sort(arr,arr+someSize, &doCompare); }
};
doCompare must be static. If doCompare needs data from MyClass you could turn MyClass into a comparison functor by changing:
doCompare( const int & i1, const int & i2 ) { // use some member variables }
into
bool operator () ( const int & i1, const int & i2 ) { // use some member variables }
and calling:
doSort() { std::sort(arr, arr+someSize, *this); }
Also, isn't doSort missing a return value?
I think it should be possible to use std::mem_fun and some sort of binding to turn the member function into a free function, but the exact syntax evades me at the moment.
EDIT: Doh, std::sort takes the function by value which may be a problem. To get around this wrap the function inside the class:
class MyClass {
struct Less {
Less(const MyClass& c) : myClass(c) {}
bool operator () ( const int & i1, const int & i2 ) {// use 'myClass'}
MyClass& myClass;
};
doSort() { std::sort(arr, arr+someSize, Less(*this)); }
}
As Andreas Brinck says, doCompare must be static (+1). If you HAVE TO have a state in your comparator function (using the other members of the class) then you'd better use a functor instead of a function (and that will be faster):
class MyClass{
// ...
struct doCompare
{
doCompare( const MyClass& info ) : m_info(info) { } // only if you really need the object state
const MyClass& m_info;
bool operator()( const int & i1, const int & i2 )
{
// comparison code using m_info
}
};
doSort()
{ std::sort( arr, arr+someSize, doCompare(*this) ); }
};
Using a functor is always better, just longer to type (that can be unconvenient but oh well...)
I think you can also use std::bind with the member function but I'm not sure how and that wouldn't be easy to read anyway.
UPDATE 2014: Today we have access to c++11 compilers so you could use a lambda instead, the code would be shorter but have the exact same semantic.
The solution proposed by Rob is now valid C++11 (no need for Boost):
void doSort()
{
using namespace std::placeholders;
std::sort(arr, arr+someSize, std::bind(&MyClass::doCompare, this, _1, _2));
}
Indeed, as mentioned by Klaim, lambdas are an option, a bit more verbose (you have to "repeat" that the arguments are ints):
void doSort()
{
std::sort(arr, arr+someSize, [this](int l, int r) {return doCompare(l, r); });
}
C++14 supports auto here:
void doSort()
{
std::sort(arr, arr+someSize, [this](auto l, auto r) {return doCompare(l, r); });
}
but still, you declared that arguments are passed by copy.
Then the question is "which one is the most efficient". That question was treated by Travis Gockel: Lambda vs Bind. His benchmark program gives on my computer (OS X i7)
Clang 3.5 GCC 4.9
lambda 1001 7000
bind 3716166405 2530142000
bound lambda 2438421993 1700834000
boost bind 2925777511 2529615000
boost bound lambda 2420710412 1683458000
where lambda is a lambda used directly, and lambda bound is a lambda stored in a std::function.
So it appears that lambdas are a better option, which is not too much of a surprise since the compiler is provided with higher level information from which it can make profit.
You can use boost::bind:
void doSort() {
std::sort(arr,arr+someSize, boost::bind(&MyClass::doCompare, this, _1, _2));
}
There is a way to do what you want, but you need to use a small adaptor. As the STL doesn't write it for you, can can write it yourself:
template <class Base, class T>
struct adaptor_t
{
typedef bool (Base::*method_t)(const T& t1, const T& t2));
adaptor_t(Base* b, method_t m)
: base(b), method(m)
{}
adaptor_t(const adaptor_t& copy) : base(copy.base), method(copy.method) {}
bool operator()(const T& t1, const T& t2) const {
return (base->*method)(t1, t2);
}
Base *base;
method_t method;
}
template <class Base, class T>
adaptor_t<Base,T> adapt_method(Base* b, typename adaptor_t<Base,T>::method_t m)
{ return adaptor_t<Base,T>(b,m); }
Then, you can use it:
doSort() { std::sort(arr,arr+someSize, adapt_method(this, &doCompare)); }
The third argument in the calling of std::sort() is not compatible to the function pointer needed by std::sort(). See my answer to another question for a detailed explanation for why a member function signature is different from a regular function signature.
just make your helper function, static which you are going to pass inside the sort function.
for e.g
struct Item
{
int val;
int id;
};
//Compare function for our Item struct
static bool compare(Item a, Item b)
{
return b.val>a.val;
}
Now you can pass this inside your sort function
A very simple way to effectively use a member function is to use operator<. That is, if you have a function called compare, you can call it from operator<. Here is a working example:
class Qaz
{
public:
Qaz(int aX): x(aX) { }
bool operator<(const Qaz& aOther) const
{
return compare(*this,aOther);
}
static bool compare(const Qaz& aP,const Qaz& aQ)
{
return aP.x < aQ.x;
}
int x;
};
Then you don't even need to give the function name to std::sort:
std::vector<Qaz> q;
q.emplace_back(8);
q.emplace_back(1);
q.emplace_back(4);
q.emplace_back(7);
q.emplace_back(6);
q.emplace_back(0);
q.emplace_back(3);
std::sort(q.begin(),q.end());
Updating Graham Asher answer, as you don't need the compare but can use the less operator directly.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Qaz {
public:
Qaz(int aX): x(aX) { }
bool operator<(const Qaz& aOther) const {
return x < aOther.x;
}
int x;
};
int main() {
std::vector<Qaz> q;
q.emplace_back(8);
q.emplace_back(1);
q.emplace_back(4);
q.emplace_back(7);
q.emplace_back(6);
q.emplace_back(0);
q.emplace_back(3);
std::sort(q.begin(),q.end());
for (auto& num : q)
std::cout << num.x << "\n";
char c;
std::cin >> c;
return 0;
}