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.
Related
I have a vector of pair defined as follows:
vector<pair<int, myClass *>> myVector;
The vector is sorted using the following:
sort(myVector.begin(), myVector.end());
This code is not mine and everything is working fine.
The only thing I don't get and I would like to understand is:
When I have two elements of my vector with the same int value as first, how the sorting is done? On which criteria?
I was thinking first, it's based on the value of the pointer to my object in the pair. But I can't see it.
I want to understand it because I need to reproduce this behavior (the sorting) on a demonstrator on Matlab.
std::sort uses std::less as default comparator. For a std::pair that just calls the elements operator< and sorts with respect to first, then second. For details see here: https://en.cppreference.com/w/cpp/utility/pair/operator_cmp.
However, comparing pointers that are not pointing to elements of the same array via < is implementation defined. You need to use std::less for proper comparison of pointers in general.
Hence, the order of elements with same first is implementation defined and difficult to be reproduced exactly.
As I said in the comment to my question, tt's indeed the numeric value of the pointer which is use as second sorting argument. This behavior doesn't make any sense in the program itself (once again, not my program) but also it won't be reproducible in Matlab. Anyway, thanks all for your help.
sort(A.begin(), A.end(),
[]( pair<int, myClass *> p1, pair<int, myClass *>p2 )
{ return p1.first < p2.first; });
modify the lambda according your wish or how you want the sorting to happen.
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.
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.
Can someone explain this code please? how is it that the function bar accepts a reference to the first element of the vector?
jintArray arry;
std::vector<int> foo = GetIntegerArray(env, arry);
bar(&foo[0])
where the protoytpe of bar is
bar(int* array)
This is valid as long as the template type isn't bool. The C++ vector type specifies that the vector elements are consecutive in memory like that so that you can do exactly this.
The reason why it doesn't work with bool is due to template specialization. Where the bools are compressed down to a bitfield.
http://en.wikipedia.org/wiki/Vector_%28C%2B%2B%29#vector.3Cbool.3E_specialization
how is it that the function bar accepts a reference to the first element of the vector?
This seems to be the source of the confusion. The expression &foo[0] is not a reference to the first element, but rather a pointer. operator[] is overloaded in the vector class to obtain a reference (or const-reference), and applying & will obtain the address of the object.
Yes. Just make sure the vector is not empty, or &foo[0] would be an error. C++11 introduced the std::vector<T>::data() function that does not have this problem.
Also, returning a vector by value is usually not a good idea. You might want to use an output iterator or a vector reference parameter in GetIntegerArray, so you would call it like this:
std::vector<int> foo;
GetIntegerArray(env, arry, back_inserter(foo));
or
std::vector<int> foo;
GetIntegerArray(env, arry, foo);
When you use std::vector<int>, it is guaranteed that all the element are created in contiguous memory. As such, when you write &v[0] it returns the pointer to the first element, and from this you can go the next element by writing &v[0]+1, and so on.
By the way, if you want to traverse through all elements or a section of elements, then a better interface for bar would be this:
void bar(int *begin, int *end)
{
for ( ; begin != end; ++begin)
{
//code
}
}
So you can call like this:
bar(&foo[0], &foo[0] + foo.size());//process all elements
bar(&foo[0], &foo[0] + foo.size()/2);//process first half elements
bar(&foo[0], &foo[0] + N); //process first N elements(assumingN <=foo.size())
bar(&foo[0]+foo.size()/2, &foo[0]+foo.size());//process second half elements
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".