1

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.

6
  • 1
    What comparator are you talking about? Commented Dec 16, 2016 at 19:39
  • remove_if expects expects a unary predicate. You can pass a lambda that returns true or false based upon your search. Commented Dec 16, 2016 at 19:39
  • Why do you need more than one argument for the predicate (I assume that's what you mean by comparator)? Commented Dec 16, 2016 at 19:40
  • @MikeMB, Sorry for the terminology mix-up. I expect to send the element and the string to compare the element to. Something like: bool pred( std::wstring elem, std::wstring element_to_remove); Commented Dec 16, 2016 at 19:43
  • @Igor: No problem. I believe LRiO already answered the question to your satisfaction? Commented Dec 16, 2016 at 19:50

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

5 Comments

I got a compiler error: "a parameter cannot have a type that contains 'auto'". After changing the "auto" to "std::wstring" everything compiles and runs fine. BTW, e1.find() is a correct function.
@Igor: You're using a compiler from the dark ages, apparently :) Yes, before C++14, you need to specify the type.
not really. I have MSVC 2010, which is enough for my purposes (C++11)
@Igor : A very limited subset of C++11... ;-]
@ildjarn, it is enough for my purpose so far... ;-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.