Reputation: 2605
I want to create a method where I search for a specific object (this case a Bar
object), inside a vector
.
When I find that object bar in the vector
, I should push_back
that piece to the end of the vector
.
I have 3 questions regarding this implementation... but I don't know if there is an easier way to do this.
This is my implementation:
std::vector<std::shared_ptr<Bar>> mBarVector;
//(...)
void Foo::pushBack(Bar& bar)
{
for (auto& b : mBarVector)
{
if(*b == bar) // ERROR [1]
{
//mBarVector.erase(?) This position...?! How? [2]
//mBarVector.push_back(bar); ERROR! [3]
}
}
}
How can I compare the the current iteration on the bar vector, with the reference to a bar from the method parameter?
Since I'm not using for(int i = 0, ...) how can I erase the position that I'm currently at?
After I remove the bar object from the vector, how can I insert a new one that is coming from a reference (to a shared_ptr)?
Upvotes: 0
Views: 350
Reputation: 238351
If you want to do a deep comparison, then you're doing it correctly now, but you need to implement operator==(const Bar&, const Bar&)
. If you want to do a shallow comparison, then you need to compare the addresses of the objects: if(b.get() == &bar)
You can't erase the current item in a range based loop, unless you separately keep track of the index or another iterator. A range based loop is simply not useful in this case.
A shared pointer to the object is in variable b
. Simply copy that. Or, better for performance, move it.
but I don't know if there is an easier way to do this.
There is.
First you need to find an iterator to the element to be moved. Simplest way to do that, depends again on whether you want shallow or deep comparison. For deep comparison, you can use std::find
. You still need to have defined operator==(const Bar&, const Bar&)
. For shallow comparison, you can use std::find_if
with a comparison functor that compares the addresses.
Once you have the iterator, you can move the pointed element to the end using std::rotate
if you want the order of other elements to stay the same. Simply rotate the vector from the found element to the end, so that the next element becomes the first one. Or, if the order is otherwise irrelevant, then you can do std::swap
with the last element which is more efficient.
Edit: mkaes proposed std::stable_partition
in a comment. It would also work and doesn't need a separate find
call. You'll need a comparison functor even if you do use deep comparison. It'll work for multiple matches too, but that also means that it won't end early if one is found. You can use std::partition
, if the order of other elements is irrelvant.
Upvotes: 3