Как удалить настроенный объект с помощью stl remove из набора контейнеров?

Ниже приведен класс и контейнер

class student {
    std::string name;
    int id;
}

set<Student*, compare> s; // sorted by id that i have done correctly
class compare {
public:
    bool operator()( Student* s1, Student* s2) {
        return s1->id < s2->id;
    }
};

Как удалить из множества объект с каким-то именем = "suri";

Что я сделал?

std::remove(s.begin(), s.end(), nameIs("suri"));

функтор

struct nameIs {
    nameIs ( std::string s ) : toFind(s) { }
    bool operator() ( Student* st)
    { return st->name.compare(toFind) == 0; }
    std::string toFind;
};

Но я получаю ошибку времени компиляции Ошибка 2 ошибка C3892: '_Next': вы не можете назначить константную переменную c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm 1816

Что я делаю не так? Как удалить настроенный объект с помощью stl remove из набора контейнеров?


person Suri    schedule 10.05.2015    source источник
comment
Я также добавил сравнить   -  person Suri    schedule 10.05.2015


Ответы (3)


введите здесь описание изображения

если вы посмотрите на это, *first == val но на самом деле в вашем случае это должно быть *first->name == val

ну это можно попробовать

std::set<Student*>::iterator it = s.begin();
for (it = s.begin(); it != s.end(); ) {
     if ((*it)->name == "suri") {
        s.erase(it++);
         break;
    }
    else {
        ++it;
    }
}
person pola sai ram    schedule 10.05.2015
comment
я не могу использовать любую функцию stl, например, удалить? - person Suri; 10.05.2015

Как указал @pola sai ram, вы не можете подать в суд на std::remove, потому что для этого требуется, чтобы элементы были назначаемыми.

Однако вам удалять не нужно:
std::remove на самом деле не удаляет элементы из вашего контейнера, а только копирует все элементы, которые вы хотите оставить на передний план (см. erase-remove-idiom). Для фактического удаления вам всегда нужно использовать функцию erase для конкретного контейнера. Так что в вашем случае вы можете просто использовать find_if вместо remove. Недостатком является то, что вам нужно вызывать его несколько раз:

auto it = std::find_if(begin(s), end(s), nameIs("suri"));
while (it != end(s)){
    it = s.erase(it);
    it = std::find_if(it, end(s), nameIs("suri"));
}
person MikeMB    schedule 10.05.2015

Такой алгоритм был предложен и добавлен в Основы библиотеки 2 TS. Если ваш компилятор поддерживает Library Fundamentals 2 TS, вы можете #include <experimental/set> использовать std::experimetal::erase_if(s, nameIs("suri")).

person cpplearner    schedule 10.05.2015