1

I have a set of Students and an iterator which finds a specific student which I then need to change. The problem is, when I go to change the object the pointer points to, it says the object is const. I'm not sure why this is, as I do not think I ever explicitly make the objects constant. I am relatively new to C++, so I may be doing something to make the Student objects const accidentally.

Here is the main funcion

set<Student> students;
ifstream file(*somefilename*);
while (!file.is_open())
{
    cout << filename << endl;
    cout << "Could not open file. Enter new filename: ";
    cin >> filename;
    file.open(filename);
}

while (!file.eof()) {
    string temp = "";
    string name;
    int regNo;
    if (file.eof())break;
    for (int i = 0; i < 3; i++) {
        if (i == 0)
            file >> regNo;
        else {
            file >> temp;
            name += temp;
        }
    }
    cout << "For loop done" << endl;
    students.insert(Student(name, regNo));
}

file.close();

file.open("ex1/marks.txt");

while(!file.eof()){
    int regNo;
    string module;
    int mark;
    file >> regNo;
    Student tempStud("",regNo);
    file >> module;
    file >> mark;
    set<Student>::iterator it = students.find(tempStud);
    if (it != students.end()) {
        **it->addMark(module, mark);**//here's the problem code
    }
}

file.close();

for (set<Student>::iterator it = students.begin(); it != students.end(); it++)
    cout << *it << endl;

cin.get();}

And here is the header file for the Student class

    public:
       Student(const string &name, int regNo);

    int getRegNo() const;

    void addMark(string& module, float mark);

    float getMark(const string &module) const;

    float getMin() const;

    float getMax() const;

    float getAvg() const;

    bool operator <(const Student& s2) const;

    bool operator >(const Student& s2);

    bool operator ==(const Student& s2);

private:
    int regNo;
    map<string, float> marks;  // keys are modules, values are marks in range 0.0 to 100.0
friend ostream& operator<<(ostream &str, const Student &s);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
lowry2234
  • 25
  • 3
  • 2
    On what line is the error occurring? What exactly does the error message say? (quote it) Also, please make sure to post a [minimal](http://stackoverflow.com/help/mcve) example – Travis Jan 03 '17 at 03:01
  • It says *what* object is const? – YiFei Jan 03 '17 at 03:06
  • 1
    [Relevant question](http://stackoverflow.com/questions/2217878/c-stl-set-update-is-tedious-i-cant-change-an-element-in-place). The MCVE in it appears to be the best way to modify an element in a `std::set`. – Justin Time - Reinstate Monica Jan 03 '17 at 03:18
  • [Another relevant question](http://stackoverflow.com/questions/7340434/how-to-update-an-existing-element-of-stdset), declare mutable. – YiFei Jan 03 '17 at 03:21

1 Answers1

2

You are not doing anything to make the Student objects const accidentally.


The Problem

Here is your problem: (C++ documentation)

All iterators in a set point to const elements.

In other words, a set will not allow you to modify elements through an iterator, even if the elements are not technically const otherwise.

So why is set defined that way? (source)

The elements of the set will be in sorted order. If you are allowed to modify an element, then this sorting order can not be maintained. Hence you can not modify the item.


The Solution

You have one of three options.

1) Don't use set

Unless there is a very good (and very specific) reason you need to use set, then don't. Use map instead. It won't have this same restriction.

2) Remove and Insert

Remove the old element and insert the "updated" version of that element. This takes O(1) time. (example)

3) Use mutable

If the data members that you want to modify are not involved in the natural ordering of the object type, then declare them to be mutable. This is equivalent to saying that their value does not change the identity of a logically const instance of the class. This will let you mutate those data members even in a const object or iterator (example)

Community
  • 1
  • 1
Travis
  • 2,135
  • 17
  • 29
  • 1
    Why don't you just write a complete answer before submitting? – Austin Brunkhorst Jan 03 '17 at 03:25
  • 1
    @AustinBrunkhorst Point #6 [here](http://meta.stackexchange.com/a/17250/346303) – Travis Jan 03 '17 at 03:29
  • I'm specifically referring to posting the answer when it's in a partial state. The link is correct, however I do not believe it's referring to your approach of streaming edits as you're literally typing them. – Austin Brunkhorst Jan 03 '17 at 04:45
  • I thought it was something like that but I couldn't find anything that confirmed it. Thank you so much! I ended up going with the second option you suggested, and it works perfectly. – lowry2234 Jan 03 '17 at 17:05