Removing items from vectors, using references

I have a very poor understanding of how vectors work in application. I have been looking at this page here: http://www.openframeworks.cc/tutorials/c++%20concepts/001_stl_vectors_basic.html

What comes up as a problem for me is that I am defining my “checkDead” unary predicate in my external class, oscThread (which is within `vector< vector >).

bool checkDead(oscThread &p){
    return p.isDead;
}

Upon the condition that I want that oscThread removed, I set “isDead” to true, and then call that function, passing in a reference to (this):

if(ttLength == 0){
    isDead = true;
    checkDead(*this);
}

Which could totally be wrong. Probably wrong. Back in ofApp, I try to call ofRemove like this:

ofRemove(braid[i],braid[i][j].checkDead);

The error comes up in the second argument, stating that a reference to a non-static member function must be called. Which I assumed was &braid[i][j].checkDead, but that gives me “Cannot create a non-constant pointer to member function”.

I really want to be able to understand these things without having to ask questions each time, but it’s all part of the process. Could anyone help explain what might be going on here?

ofApp.cpp
ofApp.h
oscThread.cpp
oscThread.h

Thank you (and to all of you that constantly offer great advice on the forums). I plan on trying out different methods for this project, but I know that learning and understanding this will help me immensely.

1 Like

Hey one quick question - which version of oF are you using? It becomes important because in c++11 (0.9.0+ i.e. the master branch), there are a whole slew of quick and easy ways to interact with collections like std::vector using lambdas and iterators.

Ah! I’m using v0.8.4 currently.

There are two very solid options at this link:

The first uses the standard algorithm library (std::remove_if). You define an struct that extends std::unary_function. It is usually considered a “best practice” to prefer to use existing c++ algorithms rather than reinventing the same operations on your own (sometimes … not always) the existing algorithms in the standard library can be optimized, etc. In your case, you could replace argument – a const reference to a string (const std::string&) argument to take a const reference to your custom object type. Just make sure that the methods / variables you call within that operator are public (although other options with friend classes, etc are possible if you can’t).

The second method simply shows how to erase items from a vector while you are iterating through that same vector. This can be tricky, especially when using iterators because as soon as you call “erase” on a vector existing iterators can (under some conditions) become invalid and you can’t use them any more.

Finally you should be able to use the same unary operator with ofRemove. It must be an external function as demonstrated.

In C++11, instead of using these external stand-alone functions (which can be annoying and (arguably) at odds with an object-oriented style, you can define a “lambda” function right in place where you need it. Lambda functions are similar to closures in Javascript if that is helpful. Anyway, 0.9.0+ begins to use these extensively and AFAIK you should be able to use functions like ofRemove with these lambda functions rather than external unary operators.

Hope that’s helpful!

theres an error in the way you are calling ofRemove, it should be:

ofRemove(braids[i], checkDead)

which will remove from that vector every element for which the check function returns true

I had decided to wait until 0.9.0 to release to continue with this project so I could try out the lambda function route, but I’m still having some issues getting the vector removed. I feel like the logic works out better now than it did before, but I’m still pretty hacky when it comes to non-oF c++.

now in ofApp::update() I am trying to remove the element with:

braid[i].erase(
         std::remove_if(braid[i].begin(), braid[i].end(),
         [](const oscThread & o) { return o.dead; }),
         braid[i].end());

or alternately:

ofRemove(braid[i], [](const oscThread& o) { return o.ttLength == 0; });

and within my class, I am just setting dead to true upon the conditions that I want. I am getting no response when trying to erase.

Here is the full code below:

ofApp.h

ofApp.cpp

oscThread.h

oscThread.cpp

I think it might even be possible that elements within braid[i] are being removed properly, but I am not resizing the vector that holds it.

By adding

if(braid[i].size() == 0){
   braid.erase(braid.begin()+i);
}

I seem to actually remove them successfully. Is this a problematic way of handling the vectors?