4

I have a vector of tuples with members j, k, and l. I am trying to adapt the erase-remove idiom such that I can remove an entire tuple if the value of the .k member meets a certain condition.

I tried using the standard .erase(removeif()) methodology where the predicate referenced the tuple member position, but was told that the class of vector in question has no member "k".

vec_list_iter_exp_out.erase(
    std::remove_if(
        vec_list_iter_exp_out.begin(),
        vec_list_iter_exp_out.end(), 
        vec_list_iter_exp_out.k < 33), vec_list_iter_exp_out.end());

I would expect that if vec_list_iter_exp_out consisted of the following, hypothetical values:

vec_list_iter_exp_out[0] = 5, 22, 9
vec_list_iter_exp_out[1] = 12, 31, 54
vec_list_iter_exp_out[2] = 17, 42, 0
vec_list_iter_exp_out[3] = 253, 3, 5
vec_list_iter_exp_out[4] = 65, 110, 24

That the entirety of vec_list_iter_exp_out[2] and vec_list_iter_exp_out [4] would be removed and vec_list_iter_exp_out would then consist of the following:

vec_list_iter_exp_out[0] = 5, 22, 9
vec_list_iter_exp_out[1] = 12, 31, 54
vec_list_iter_exp_out[2] = 253, 3, 5

Instead I get the aforementioned compile error.

Any help would be greatly appreciated!

Edit: definition of the vector in question, as requested.

struct TriStore
{
    double j,k,l;
};

std::vector<TriStore> vec_list_iter_exp_out;

and snippet for insertion (obviously references other functions and what-have-you, but that would take up far too much space)

    for(int z = 1; z <= iters; z++)
    {
        vec_iters.push_back(vec_list_iter_exp_out.size());
        for(int i = vec_iters[z-1]; i < vec_iters[z]; i++)
        {
            if(vec_list_iter_exp_out[i].k < kk)
            {
                triangle_list(vec_list_iter_exp_out[i].j,vec_list_iter_exp_out[i].k,vec_list_iter_exp_out[i].l);
                vec_list_iter_exp_out.insert(vec_list_iter_exp_out.end(),vec_tri_list.begin(),vec_tri_list.end());
            }
        }
    }

1 Answers1

6

Third argument of remove_if needs to be a unary predicate. Instead you are passing an expression.

Instead of vec_list_iter_exp_out.k < 33 try something like [](const TriStore &x){return x.k < 33;}

What if I want to decide this 33 at runtime

From this comment by Nishant Singh: Please use

[&value](const TriStore& x) {return x.k < value;}  // Capture by reference
[value](const TriStore& x) {return x.k < value;}  // Capture by value

p.s. Instead of TriStore why don't you use tuple<double, double, double>?

Gyapti Jain
  • 4,056
  • 20
  • 40
  • 1
    This worked! I can't yet mark the question as answered, but I will as soon as the timer runs out. Also, I'm too new to display an upvote, but I did and your answer was excellent. Thank you! – Judson Clark May 09 '19 at 05:32
  • 1
    I am happy just by knowing that it helped you. I am sure you would love to read about `std::tuple` and lambdas in C++. – Gyapti Jain May 09 '19 at 05:34
  • Gyapti, if I wanted to make "33" variable and instead something that was passed into the initial function that this is nested within, how would I go about doing that? I tried to simply use the existing variable name and got this message: "an enclosing-function local variable cannot be referenced in a lambda body unless it is in the capture list" – Judson Clark May 09 '19 at 06:14
  • 2
    @JudsonClark you need to capture the variable by reference or value like `[&value](const TriStore& x) {return x.k < value;}` where `value` the variable you want capture. Note that I am capturing it by reference, if you want to capture it by value, use `[value](const TriStore& x) {return x.k < value;}` – Nishant Singh May 09 '19 at 06:39
  • Thanks @NishantSingh. I am late to this comment, would add it to the answer. – Gyapti Jain May 09 '19 at 10:06
  • So is this the correct implementation? ```vec_list_iter_exp_out.erase(std::remove_if(vec_list_iter_exp_out.begin(),vec_list_iter_exp_out.end(), [&kk](const TriStore &x){return x.k < kk;}),vec_list_iter_exp_out.end());``` For what it is worth, kk is of type double. – Judson Clark May 09 '19 at 16:29