1

For a school assignment I need to remove purple from my vector by using and this is what I came up with:

bool IsEqual(string s, string s2)
{
    if (s == s2)
    {
        return true;
    }
}

int main() {
    vector<string> coulours2 = { "red", "green", "blue", "orange", "purple", "orange", "black", "green" };
    vector<string>::iterator newEnd;
    newEnd = remove_if(coulours2.begin(), coulours2.end(), bind2nd(IsEqual, "purple"));
    colours2.erase(newEnd);
    cin.get();
    return 0;
}

But I get a lot of errors, I think I am using bind2nd wrong. How should I use it correctly?

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
anonymous-dev
  • 2,897
  • 9
  • 48
  • 112
  • 3
    What are the errors? Where is your [MCVE]? And [please don't do `cin.get()` like that](http://stackoverflow.com/a/36374595/560648)! – Lightness Races in Orbit Jan 09 '17 at 17:01
  • 4
    You are using `remove_if` + `erase` wrong. – Jesper Juhl Jan 09 '17 at 17:02
  • 1
    Specifically, there are multiple versions of [`erase`](http://en.cppreference.com/w/cpp/container/vector/erase). You're using the one that erases the single element at the iterator, rather than the one that erases a range. – jaggedSpire Jan 09 '17 at 17:04
  • Sorry about the title i corrected it. I am trying to remove "purple" from colours2. And how am I using it wrong Jesprer Juhl? – anonymous-dev Jan 09 '17 at 17:04
  • 1
    `IsEqual` would be simpler as just `return s == s2;`. Also, why not just `std::equal`? – Jesper Juhl Jan 09 '17 at 17:06
  • Actually, since `IsEqual` just falls off the end of the function without returning anything when the strings are not equal; you have Undefined Behaviour right there. Also; why is it taking its arguments by value (copy) and not as `const string&`? – Jesper Juhl Jan 09 '17 at 17:30
  • The `return 0` from main is redundant - the standard guarantees this for `main` (only). Also, for more portable code you should - if you insist on an explicit return - `return EXIT_SUCCESS;`. – Jesper Juhl Jan 09 '17 at 17:33

2 Answers2

5

For starters, the std::bind1st and std::bind2nd functions are deprecated. You should consider using std::bind instead, which is much more generic and easier to use.

If you do want to use bind2nd, then the function you pass in must be an adaptable function, a function object type that exports some extra type information. To convert a raw function pointer to an adaptable function, use the amusingly-named ptr_fun function:

remove_if(coulours2.begin(), coulours2.end(), 
          bind2nd(ptr_fun(IsEqual), "purple"));

However, there's no need to define your own function here at all. Just use std::equal_to:

remove_if(coulours2.begin(), coulours2.end(),
          bind2nd(equal_to<string>(), "purple"));

As was mentioned in the comments, you're also using the erase/remove_if pattern incorrect. Try this instead:

coulours2.erase(remove_if(coulours2.begin(), coulours2.end(), 
                bind2nd(equal_to<string>(), "purple")),
                coulours2.end());

The "better" way to do this using std::bind looks like this:

using namespace std::placeholders;
coulours2.erase(remove_if(coulours2.begin(), coulours2.end(), 
                bind(equal_to<string>(), _1, "purple")),
                coulours2.end());

Or just use a lambda:

coulours2.erase(remove_if(colours2.being(), colours2.end(),
                [](const string& elem) { return elem == "purple"; },
                coulours2.end());
David
  • 27,652
  • 18
  • 89
  • 138
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
2

You don't need IsEqual at all, or any custom comparator. You don't need the remove_if variant, you can use regular remove.

colors.erase(std::remove(colors.begin(), colors.end(), "purple"), colors.end());
David
  • 27,652
  • 18
  • 89
  • 138