Igor
Igor

Reputation: 6255

std::remove vs std::remove_if

I have a following class:

class Foo
{
public:
    void Fill();
private:
    std::vector<std::wstring> vec;
};

And then the implementation is:

void Foo::Fill()
{
    vec.push_back( L"abc aaa" );
    vec.push_back( L"def aaa" );
    vec.push_back( L"fed bbb" );
    vec.push_back( L"cba bbb" );
}

What I'd like to do to delete an element from this vector, lets say one that contains "def". What would be the easiest way to do so?

I'm thinking to use remove_if, but the comparator accept only 1 parameter - container element.

Is there an elegant solution? I'd use looping as a last resort.

Upvotes: 1

Views: 493

Answers (1)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385144

If it's a class rather than a function, the predicate has a constructor, and constructors can take arguments.

You can pass your search string into this constructor, store it as a member, then use it inside the function call operator:

struct Pred
{
    Pred(std::wstring str) : str(std::move(str)) {}
    bool operator()(const std::wstring& el) const
    {
       return el.find(str) != el.npos;
    }
private:
    const std::wstring str;
};

std::remove_if(std::begin(vec), std::end(vec), Pred("def"));

// N.B. `el.find` is probably wrong. Whatever.

A "shortcut" to doing this is to use a lambda for the predicate, then the passing through of the search string is done for you either via the lambda capture, or by virtue of the fact that you literally typed it in right there and then:

std::remove_if(
   std::begin(vec), std::end(vec),
   [](const auto& el) { return el.find("def") != el.npos; }
);

// N.B. `el.find` is probably still wrong. Whatever.

If the predicate is a function, and you want it to invoke a binary comparator, you could mess about with std::bind to achieve the same result.

Upvotes: 4

Related Questions