0

I want to remove a particular student object for a given roll no. from a students list using erase operation in STL. Following are my class designs. But the compiler shows the following error message at place where I used the erase function.

no instance of overloaded function "std::vector<_Tp, _Alloc>::erase [with _Tp=Student, _Alloc=std::allocator<Student>]" matches the argument list -- argument types are: (Student) -- object type is: std::vector<Student, std::allocator<Student>>

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

class Student
{
    int roll;
    char *name;
    int score;

    public:
        Student(int r=0)
        {
            roll=r;
        }

        void get_data()
        {
            cout<<"Enter roll : ";
            cin>>roll;
            cout<<"Enter name : ";
            cin>>name;
            cout<<"Score : ";
            cin>>score;
        }

        void show_data()
        {
            cout<<"Roll : "<<roll<<endl;
            cout<<"Name : "<<name<<endl;
            cout<<"Score : "<<score<<endl;
        }

        int ret_score()
        {
            return score;
        }

        int ret_roll()
        {
            return roll;
        }
};

class Student_array
{
    public:
    vector <Student> Student_array;
    vector <Student>::iterator it;

    void add_student()
    {
        Student s;
        s.get_data();
        Student_array.push_back(s);
    }

    void remove_student()
    {
        int roll;
        cout<<"Enter roll no. of the student to be removed : ";
        cin>>roll;
        for(int i=0;i<Student_array.size();i++)
        {
            if(roll==Student_array[i].ret_roll())
            {
                Student_array.erase(Student_array[i]);
                break;
            }
        }
        cout<<"Roll no. not found enter a valid roll no.\n";
    }
};
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Side note: storing an iterator (`vector ::iterator it;`) has some risk because it is easily rendered invalid by adding or removing items from the `vector`. See [Iterator invalidation rules](https://stackoverflow.com/questions/6438086/iterator-invalidation-rules) for a Standard revision-by-Standard revision breakdown of what you can and can't get away with. – user4581301 Jan 11 '21 at 18:28

2 Answers2

2

std::vector::erase() takes an iterator as input, not a Student object, eg:

void remove_student()
{
    int roll;
    cout << "Enter roll no. of the student to be removed : ";
    cin >> roll;
    for(int i = 0; i < Student_array.size(); ++i)
    {
        if (roll == Student_array[i].ret_roll())
        {
            Student_array.erase(Student_array.begin() + i);
            return; // <-- not 'break'!
        }
    }
    cout << "Roll no. not found enter a valid roll no.\n";
}

Alternatively, you can use std::find_if() to find the desired Student instead of using a manual loop, eg:

void remove_student()
{
    int roll;
    cout << "Enter roll no. of the student to be removed : ";
    cin >> roll;
    auto iter = std::find_if(Student_array.begin(), Student_array.end(),
        [=](Student &s){ return s.ret_roll() == roll; }
    );
    if (iter != Student_array.end())
        Student_array.erase(iter);
    else
        cout << "Roll no. not found enter a valid roll no.\n";
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks for your answer. Just a small query, if suppose I want to sort and display the students in descending order of their score, then how should I frame the function? I could use the sort template with range from rbegin() to rend() but I cannot understand how do I relate that sorting with scores of students – Carmela Jones Jan 11 '21 at 19:13
  • Use a custom predicate that compares `score` values, eg: `std::sort(Student_array.begin(), Student_array.end(), [](Student &s1, Student &s2){ return s1.ret_score() > s2.ret_score(); });` Or, if you implement an `operator>` for `Student` that compares on `score` then you can use [`std::greater`](https://en.cppreference.com/w/cpp/utility/functional/greater) for the predicate, eg: `class Student { ... bool operator>(const Student &rhs) const { return score > rhs.score; } }; std::sort(Student_array.begin(), Student_array.end(), std::greater());` – Remy Lebeau Jan 11 '21 at 19:33
  • Thank you so much that was really really helpful – Carmela Jones Jan 11 '21 at 19:37
0

You must use iterator to erase an element

for (auto iter = Student_array.begin(); iter != Student_array.end(); ++iter)
{
    if (roll != iter->ret_roll())
        continue;

    Student_array.erase(iter);
    break;
}
Ali Razmkhah
  • 280
  • 1
  • 10