I'm trying to understand what the code below says:
struct compare_pq;
struct compare_pq {
bool operator() (Events *& a, Events *& b);
};
std::priority_queue<Events *, std::vector<Events *>, compare_pq> eventList;
i looked at what priority_queue is and how its declared but can't quit understand what compare_pq is doing in the priority_queue eventList. Also what does operator() do since i've never seen *& before and empty operator overloading operator()!
any help would be appreciated. Thank you
operator() is the function-call operator. It allows you to use an object of the class type as if it were a function, e.g.,
compare_pq my_comparator;
bool result = my_comparator(a, b);
Objects of class types that overload operator() are frequently called function objects or functors.
The third template parameter of std::priority_queue is for the comparison function. By default, the priority queue sorts its elements using std::less, which applies operator< to two elements. You can use any function (or function object) that takes two elements and returns a boolean indicating whether the first is smaller than the second. "Smaller" in this case is a relative term: the top() of the priority queue is the "largest" element currently in the queue.
In this case, you need to use a custom comparison function because the priority queue is storing pointers, so by default it would sort the elements by pointer value. The custom comparator (probably) dereferences the pointers and performs some comparison on the pointed-to objects.
Events*& is just a reference to a pointer to an Events object. It really doesn't need to be passed by reference. Since it's just a pointer, it can be passed by value (e.g., Events*). If you do choose for some reason to use a reference it should be a const reference.
*& is a reference to a pointer. It works like any other kind of reference. In less sophisticated C++ code you might see a double pointer (**) used.
compare_pq is a functor used to compare Event pointers. In this case, priority_queue would likely be instantiating a compare_pq whenever a comparison is needed.
Event * a = new Event();
Event * b = a;
compare_pq foo;
bool result = foo(a, b);
operator() is not empty. You're looking at a declaration. It must be defined somewhere else if it is to be instantiated.
I'll try to answer the question why a functor is used. It's just a guess of course, as I'm not the author of the code, but I saw discussions about it at least a few times and the consensus seems to be, that functors enable or at least make it easier to inline the comparison code.
Functors are structs (or classes) and in general are more flexible than regular functions because they can have some members, that store some state, which can be used by operator(). In this case this advantage isn't used, so the functor was most probably used to enable (or help) in inlining or just because the author was used to this common pattern.
Why would it help in inlining? Let's look at a simple example. Lets take std::sort
template <class RandomAccessIterator, class Compare>
void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );
Imagine You want to sort std::vector<int> and You want to provide Your custom comparators.
struct MyStructComp1
{
bool operator()(int lhs, int rhs) const { /*...*/}
};
struct MyStructComp2
{
bool operator()(int lhs, int rhs) const { /*...*/}
};
bool myFunctComp1 (int lhs, int rhs) const { /*...*/}
bool myFunctComp2 (int lhs, int rhs) const { /*...*/}
Now You can use the sort temeplate in the following ways
sort(myvector.begin(), myvector.end(), MyStructComp1()); // 1
sort(myvector.begin(), myvector.end(), MyStructComp2()); // 2
sort(myvector.begin(), myvector.end(), myFunctComp1); // 3
sort(myvector.begin(), myvector.end(), myFunctComp2); // 4
Here are the function the compiler creates form the template
sort<vector<int>::iterator, MyStrucComp1> // 1
sort<vector<int>::iterator, MyStrucComp2> // 2
sort<vector<int>::iterator, bool (*) (int lhs, int rhs)> // 3, // 4
Since the Compare parameter in the sort template is a type, and functors are types, the compiler creates a different function for every functor supplied as a template argument. sort<vector<int>::iterator, MyStrucComp1> and
sort<vector<int>::iterator, MyStrucComp2> are two different functions. So when sort<vector<int>::iterator, MyStrucComp1> is created, it is known exactly what the comparing code is and the comparator can be simply inlined.
Functions myFunctComp1 and myFunctComp2 however are of exactly the same type:
bool (*) (int lhs, int rhs) and the compiler creates one function sort<vector<int>::iterator, bool (*) (int lhs, int rhs)> for all comparing functions of type bool (*) (int lhs, int rhs). I saw opinions, that inlining is possible anyway in this situation, but I have no idea how.
It is possible to create templates with a pointer to function as a template parameter as it's a compile time constant, but it's ugly and constants can't be deduced from the function arguments. For example if sort was defined as:
template <class RandomAccessIterator,
bool (*comparer) (typename RandomAccessIterator::value_type, typename RandomAccessIterator::value_type)>
void sort ( RandomAccessIterator first, RandomAccessIterator last) {/* */}
You would have to call it like this
sort<std::vector<int>::iterator, myFunctComp1>(myvector.begin(), myvector.end());
You would get a different sort for every comparing function, but functors are much more convenient.
Related
Im trying to sort my vector depending on value returned by function calculateDistance() which returns double value. I guess the problem is caused by permutationCopmarator method. .cpp file looks like this:
bool TSPgenetic::permutationComparator(int* i, int* j){
return calculateDistance(i) < calculateDistance(j);
}
void TSPgenetic::chooseNewPopulation(){
sort(population->begin(), population->end(), permutationComparator);
sort(children->begin(), children->end(), permutationComparator);
`....`
}
Header file fragment:
bool permutationComparator(int*, int*);
Passing permutationComparator as the third parameter of std::sort is not valid. Only static class members is valid and functor objects. To resolve the issue, here's four choices:
Create a closure object using lambda expression and do your comparison there.
std::sort(population->begin(), population->end(), [](const int *i1, const int *i2){return calculateDistance(i1) < calculateDistance(i2);});
You can use std::bind, if your comparsion function needs not to be static.
auto comp_func = std::bind(&TSPgenetic::permutationComparator, this, std::placeholders::_1, std::placeholders::_2);
std::sort(population->begin(), population->end(), comp_func);
Make your comparison function static, if it's possible.
Overload bool operator () ( const int *i1, const int *i2 ) in your class in order that your class to be a functor object.
Note that logically a comparison function should not to be a member function. It is a function that takes two objects and determines their orders. So, almost in all cases, only the third option applies.
I wish to sort an array of objects of class Person on the basis of its data member 'age'. I store the objects in a vector<Person> v.
As far I have understood, there can be at least 4 ways to perform this action and I have the following questions based on the methods written below.
How does operator() defined inside a class work? Should I not overload the '<' operator here as well? Why '()' ?
I sent an object as the 3rd parameter in method 1. But, in method 2, I sent the name of a function. Why is it like that?
Which of the four methods is the best? I felt that method 3 was the easiest.
Method 1
class cmp
{
public:
bool operator() ( Person const &a, Person const &b )
{
return a.age < b.age ;
}
};
sort( v.begin(), v.end(), cmp());
Method 2
bool cmp( const Person a, const Person b )
{
return a.age < b.age ;
}
sort( v.begin(), v.end(), cmp );
Method 3
bool operator < ( const Person a, const Person b )
{
return a.age < b.age ;
}
sort( v.begin(), v.end());
Method 4
//using lambda expression
sort( v.begin(), v.end(), [](const Person &a, const Person &b){return a.age < b.age;});
To sort a range using std::sort (or any function for that matter), it needs to know how two elements from the range are compared, in order to determine less than (or greater than) relationship.
The Standard Library function std::sort comes in two flavors: one uses operator<, the other uses a compare function/functor. You've used both of them in your code — in particular, the third one in your example uses < and the rest use compare function/functor.
As for which one is the best approach?
Well, it depends. The one which uses operator< is less flexible since it is fixed but requires you less typing as well. Use it when it suffices.
The other one is more flexible as you can pass any compare function and get your elements sorted accordingly. Use it when operator< doesn't suffice. Also, when you choose this flavor, you have other choices as well : the comparer could be a function, a functor, or a lambda — if you use function or functor (defined at namespace level), then you can reuse them; on the other hand, lambda is usually defined in a function scope, so it is not that reusable, unless you define it at namespace scope, in which case it is almost same as function.
Example, suppose you want to sort a vector of int in increasing order:
std::vector<int> v{10, 3, 12, -26};
std::sort(v.begin(), v.end());
print(v);
Output: -26,3,10,12. So operator< does do the job.
But what if you want the elements sorted considering only magnitude (i.e ignore signs), then you have to use the other flavor:
std::vector<int> v{10, 3, 12, -26};
auto abs_cmp = [](int a, int b) { return std::abs(a) < std::abs(b); };
std::sort(v.begin(), v.end(), abs_cmp);
print(v);
Output : 3,10,12,-26. That is the output you would expect in this case.
Hope that helps.
The sort function has two overloads
i. void sort( RandomIt first, RandomIt last ); It doesn't accept compare function, it expects the items have operator< defined. You'r method 3 uses this overload.
template< class RandomIt >
void sort( RandomIt first, RandomIt last )
{
...
if (*i < *j)
....
...
}
ii. void sort( RandomIt first, RandomIt last, Compare comp ); it accepts a compare function, it's useful when your items don't have operator< defined.
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp )
{
...
if (comp(*i, *j))
....
...
}
Methods 1,2,4 use this overload. All the passed third arguments can be called by (). Method 1, sends an object by cmp(), this object has overloaded operator() and above code invokes it. Method 2 and 4, sends pointer to functions and a pointer to a function can be invoked by ().
How does operator() defined inside a class work? Should I not overload the '<' operator here as well? Why '()' ?
operator() is the function call operator. Instances of your class cmp are callable in the same way that a function is callable. The call is required by sort to perform the necessary comparison.
I sent an object as the 3rd parameter in method 1. But, in method 2, I sent the name of a function. Why is it like that?
Instances of cmp are callable. Function names are callable.
Which of the four methods is the best? I felt that method 3 was the easiest.
The main disadvantage of 3 is that you have defined that one Person is less than or greater than another Person according to their ages. What if you want to sort them by name elsewhere? You've already defined operator< for Person, so you can't do the same trick again. All three of the other methods define a comparison for use in a specific sort, rather than defining what it means in general to compare Person.
The main disadvantage of 2 is that it's somewhat harder for the compiler to inline than 1 or 4. It doesn't really have any advantages over 1, but for completeness it's nice that sort can take a function pointer.
The main advantage of 4 is that if you only use the comparison once, it's often nicer to have it right there in the same line of code that calls sort, instead of being off somewhere else in the file.
The main advantage of 1 is that it works in C++03 (unlike 4). 4 is more-or-less a new syntax for 1. 1 also has the advantage that it makes the comparator available for other code to use with the same name. You could achieve that with a lambda too if you wanted (you name a lambda by assigning it to an auto variable).
You simply provide functor, object that has operator() and is used while comparing objects.
As far as I know, sort accepts functors, functions and lambda expressions to use them to compare objects.
In method 3 you doesn't provide functor, function or lambda expression to compare so it's by default sorted using standard operator<. Obviously it doesn't sort your Person objects by age, as you would like to. In my opinion the cleanest form is method 4, using lambda expression.
I currently have an array of pair<double, int> which I sort using a simple custom comparator function e.g.
// compare by first
int sort_index_lcomparator(const pair<double, int>& a, const pair<double, int>& b) {
return a.first < b.first;
}
// then sort simply like
pair<double, int> arr[size];
std::sort(arr, arr + size, sort_index_lcomparator);
I'm actually interested in the index order and not in the sorted doubles. My problem is that I would like to change away from this structure and have instead a struct of two arrays rather than an array of a struct i.e. I would like to optimize for locality and auto-vectorization but in this case I need an overloaded swap which is attached to a type specifically. I guess I would need something along the lines of redefining swap for the double type and keep both arrays in sync in such custom swap. Is there a way to "override" swap in such a manner within a limited scope?
I have one proposal for you: make the index array the one you sort and keep the values as global array. From then on: sort based on comparator that accepts indices, but actually compares based on the values.
You should specialize std::sort using your custom "comparator".
template <class RandomAccessIterator, class Compare>
void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );
By default sort uses a standard comparator which just compares the elements referenced by the given iterators.
Using the custom Compare you may override this. Note that it's not a function (in C++ generally you may not pass a function as a template parameter). It's a class. You pass an object of this class to sort, whereas this object should implement the following operator:
bool operator () (const Type1 &a, const Type2 &b);
So, you may invoke sort for array of your double's. Your comparator should have pointers to the beginning of both your arrays: double and int.
In case with arrays the iterator resolves into a pointer to an array element. Using the array starting address you may convert it into an index, and use it to access the second array.
I want to construct three different priority_queue's that hold a class Thing and then sort each one differently by values that are held by the Thing. I know that I can define an operator method either internally, or a friend to the object, but is there a way to have it use different test method(s)? How do I tell it to use that method instead of the operator method? And how would the parameter list differ from creating an operator overload?
Like most STL containers, the priority_queue accepts a Compare class in its template arguments.
struct MyCompare1 {
bool operator()(const Thing& t1, const Thing& t2) {
// your logic here
}
};
std::priority_queue<Thing, std::vector<Thing>, MyCompare1> my_queue;
You can pass a custom comparator type that will be used instead of the default. This is a template parameter of the priority_queue.
You can specify your comparison function as the third parameter when defining the priority_queue. Note that the second parameter is the underlying container type, typically std::vector.
std::priority_queue<Thing> pq1;
std::priority_queue<Thing, std::vector<Thing>, std::greater<Thing> > pq2;
std::priority_queue<Thing, std::vector<Thing>, [your comparator here] > pq3;
I have a piece of code that confuses me:
sort(data, data+count, greater<int>() );
it is a sort function in the C standard library. I am having trouble figuring out the meaning of the third argument. I have read that it is called a binary predicate. What does that mean and how can I make my own such predicate?
The third argument is called a predicate. You can think of a predicate as a function that takes a number of arguments and returns true or false.
So for example, here is a predicate that tells you whether an integer is odd:
bool isOdd(int n) {
return n & 1;
}
The function above takes one argument, so you could call it a unary predicate. If it took two arguments instead, you would call it a binary predicate. Here is a binary predicate that tells you if its first argument is greater than the second:
bool isFirstGreater(int x, int y) {
return x > y;
}
Predicates are commonly used by very general-use functions to allow the caller of the function to specify how the function should behave by writing their own code (when used in this manner, a predicate is a specialized form of callback). For example, consider the sort function when it has to sort a list of integers. What if we wanted it to sort all odd numbers before all even ones? We don't want to be forced to write a new sort function each time that we want to change the sort order, because the mechanics (the algorithm) of the sort is clearly not related to the specifics (in what order we want it to sort).
So let's give sort a predicate of our own to make it sort in reverse:
// As per the documentation of sort, this needs to return true
// if x "goes before" y. So it ends up sorting in reverse.
bool isLarger(int x, int y) {
return x > y;
}
Now this would sort in reverse order:
sort(data, data+count, isLarger);
The way this works is that sort internally compares pairs of integers to decide which one should go before the other. For such a pair x and y, it does this by calling isLarger(x, y).
So at this point you know what a predicate is, where you might use it, and how to create your own. But what does greater<int> mean?
greater<T> is a binary predicate that tells if its first argument is greater than the second. It is also a templated struct, which means it has many different forms based on the type of its arguments. This type needs to be specified, so greater<int> is the template specialization for type int (read more on C++ templates if you feel the need).
So if greater<T> is a struct, how can it also be a predicate? Didn't we say that predicates are functions?
Well, greater<T> is a function in the sense that it is callable: it defines the operator bool operator()(const T& x, const T& y) const;, which makes writing this legal:
std::greater<int> predicate;
bool isGreater = predicate(1, 2); // isGreater == false
Objects of class type (or structs, which is pretty much the same in C++) which are callable are called function objects or functors.
There is a class template called greater which needs a type argument. So you provide int as one. It became greater<int> and you create an instance of this class and pass it to the function as third argument.
Such an object is called function object or simply functor in C++, as the class overloads () operator. It's a callable entity. Its like this:
template<typename T>
struct greater
{
bool operator()(const T &a, const T &b)
{
//compare a and b and return either true or false.
return a > b;
}
};
If you create an instance of greater<int> and, say, the object is g, then you can write g(100,200) which evaluates to a boolean value, as the expression g(100,200) calls operator(), passing 100 as first argument and 200 as second argument, and operator() compares them and return either true or false.
std::cout << g(100,200) << std::endl;
std::cout << g(200,100) << std::endl;
Output:
0
1
Online demo : http://ideone.com/1HKfC
A binary predicate is any function/object that receives two objects (hence binary) and returns a bool (hence predicate); the idea is that it evaluates if the two objects satisfy some particular condition - in the example, if one is greater than the other.
You can create a predicate either by just defining a function with the correct signature
bool IsIntGreater(int First, int Second)
{
return First>Second;
}
and passing the name of the function as the argument (this will result in passing a function pointer), or creating a function object (a functor), i.e. an object which overloads the function call operator and thus can be used as a function; the std::greater<T> type is a template functor, and in your snippet a temporary object of type std::greater<int> is created and passed to the std::sort algorithm.
Functors have several advantages over functions, especially when they have to be passed as arguments, have a look here for more information about this.
See comp in http://www.cplusplus.com/reference/algorithm/sort/
It is the function that does the comparison.