std::sort and custom swap function - c++

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.

Related

C++ STL algorithms: get pointers of elements in container

I have a function that is taking two pointers as parameters.
bool function(T* a, T* b);
And a container (vector).
vector<T> vector;
I wish to use an algorithm of the STL (the for_each) to apply the function on the elements of the vector. However, I don't know if the pointers of the elements will go automatically in the function as parameters. For example, will
for_each(vector.begin(), vector.end(), function(/*something here?*/))
work, or I need to go with a loop (the new for each in loop of the C++11) ?
You cannot use std::for_each() with your function for at least two reasons:
std::for_each passes a single parameter to the lamba, your function() takes two parameters.
std::for_each passes a reference to each member of the container, and not a pointer.
Try utilizing a normal for loop for solving this problem.
vector<T> v;
for(size_t i(0); i < v.size()-1; ++i)
{
function(&v[i], &v[i+1]);
}
This will pass as the values an address to elements i and i+1 of v which of type T.

Priority queue to push pair and int

I want to use priority_queue like this:
priority_queue< pair< int, int> ,int ,cmp >
The comparision should be based on the int value in non-decreasing order.
Example:
((2,5),1),((2,5),2),((2,5),3)
Read the template parameters of std::priority_queue again. The second parameter is the underlying container. You can't use an int.
What you seem to be asking is how to store a pair and an int in a priority queue and sort by the int. Well, you've already figured out how to store a pair of ints. Simply expand that idea and store a pairof a pair and int. That's a naïve solution though. Instead, I recommend using a struct with the pair and the int as members so that you can give them descriptive names. Consider using a struct for the pair of ints too. Then simply use a compare functor which compares the third int only in the order of your choosing ignoring the pair.
priority_queue accepts only "one element" by saying one element I mean only a single element of arbitrary type. For having a pair, and int and another component in the priority queue you need to bring all of them as one meaning you need to be build a struct which will hold them. Then you have to use the bool operator < to tell the compiler how to compare the elements of your type .
bool operator < ( const structName& left, const structName& right)
{
return left.number < right. number;
}
this means that the comparison must be done with the member named number.

Are STL predicates allowed to use their argument's address?

When writing a custom predicate function/functor to pass to an STL algorithm, is the predicate allowed to use the address of its argument?
Here's the problem that inspired the question. I have a vector vec, and a vector inds, which contains some indices into vec. I'd like to remove those elements in vec whose indices are listed in inds.
One approach is to use remove_if with a predicate functor InInds that determines its argument's index in vec by taking its address:
class InInds {
private:
const vector<Element>& vec_;
const vector<int>& inds_;
public:
InInds(const vector<Element>& vec, const vector<int>& inds)
: vec_(vec), inds_(inds) {}
bool operator()(const Element& element) {
// WARNING: uses the ADDRESS of element, not its value. May not be kosher?
int index = &element - &vec[0];
return std::find(inds_.begin(), inds_.end(), index) != inds_.end();
}
}
InInds works if called directly on an element in vec. It will break if it's called on a copy of an element, since the copy's address will not be useful to determine element's index.
My question is: will this predicate work in remove_if for any standards-compliant compiler? Or are predicates strictly meant to operate only on values, not addresses?
Use of remove_if with your predicate is wrong since remove_if usually moves undeleted elements toward the beginning of the range. You need to copy undeleted elements to another container instead of removing them in place.

Why does std::vector transfer its constness to the contained objects?

A const int * and an int *const are very different. Similarly with const std::auto_ptr<int> vs. std::auto_ptr<const int>. However, there appears to be no such distinction with const std::vector<int> vs. std::vector<const int> (actually I'm not sure the second is even allowed). Why is this?
Sometimes I have a function which I want to pass a reference to a vector. The function shouldn't modify the vector itself (eg. no push_back()), but it wants to modify each of the contained values (say, increment them). Similarly, I might want a function to only change the vector structure but not modify any of its existing contents (though this would be odd). This kind of thing is possible with std::auto_ptr (for example), but because std::vector::front() (for example) is defined as
const T &front() const;
T &front();
rather than just
T &front() const;
There's no way to express this.
Examples of what I want to do:
//create a (non-modifiable) auto_ptr containing a (modifiable) int
const std::auto_ptr<int> a(new int(3));
//this works and makes sense - changing the value pointed to, not the pointer itself
*a = 4;
//this is an error, as it should be
a.reset();
//create a (non-modifiable) vector containing a (modifiable) int
const std::vector<int> v(1, 3);
//this makes sense to me but doesn't work - trying to change the value in the vector, not the vector itself
v.front() = 4;
//this is an error, as it should be
v.clear();
It's a design decision.
If you have a const container, it usually stands to reason that you don't want anybody to modify the elements that it contains, which are an intrinsic part of it. That the container completely "owns" these elements "solidifies the bond", if you will.
This is in contrast to the historic, more lower-level "container" implementations (i.e. raw arrays) which are more hands-off. As you quite rightly say, there is a big difference between int const* and int * const. But standard containers simply choose to pass the constness on.
The difference is that pointers to int do not own the ints that they point to, whereas a vector<int> does own the contained ints. A vector<int> can be conceptualised as a struct with int members, where the number of members just happens to be variable.
If you want to create a function that can modify the values contained in the vector but not the vector itself then you should design the function to accept iterator arguments.
Example:
void setAllToOne(std::vector<int>::iterator begin, std::vector<int>::iterator end)
{
std::for_each(begin, end, [](int& elem) { elem = 1; });
}
If you can afford to put the desired functionality in a header, then it can be made generic as:
template<typename OutputIterator>
void setAllToOne(OutputIterator begin, OutputIterator end)
{
typedef typename iterator_traits<OutputIterator>::reference ref;
std::for_each(begin, end, [](ref elem) { elem = 1; });
}
One big problem syntactically with what you suggest is this: a std::vector<const T> is not the same type as a std::vector<T>. Therefore, you could not pass a vector<T> to a function that expects a vector<const T> without some kind of conversion. Not a simple cast, but the creation of a new vector<const T>. And that new one could not simply share data with the old; it would have to either copy or move the data from the old one to the new one.
You can get away with this with std::shared_ptr, but that's because those are shared pointers. You can have two objects that reference the same pointer, so the conversion from a std::shared_ptr<T> to shared_ptr<const T> doesn't hurt (beyond bumping the reference count). There is no such thing as a shared_vector.
std::unique_ptr works too because they can only be moved from, not copied. Therefore, only one of them will ever have the pointer.
So what you're asking for is simply not possible.
You are correct, it is not possible to have a vector of const int primarily because the elements will not assignable (requirements for the type of the element contained in the vector).
If you want a function that only modifies the elements of a vector but not add elements to the vector itself, this is primarily what STL does for you -- have functions that are agnostic about which container a sequence of elements is contained in. The function simply takes a pair of iterators and does its thing for that sequence, completely oblivious to the fact that they are contained in a vector.
Look up "insert iterators" for getting to know about how to insert something into a container without needing to know what the elements are. E.g., back_inserter takes a container and all that it cares for is to know that the container has a member function called "push_back".

C++ Code Clarification Needed

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.