Home > Net >  How to use 'mutable' correctly so the set iterator won't be const?
How to use 'mutable' correctly so the set iterator won't be const?

Time:01-06

I'm trying to remove the employee in my code and change his salary back to 0, but all I get in the function is his id. I used the built in iterator for the set, but found out that it is const. How can I use mutable, or some other way to change his salary to 0? I have an employee and a manager- the manager can hire or fire the employee, which will change his salary (obviously). This is my code:

class Manager : public Citizen {
    protected:
        int salary;
        std::set<Employee> employees;

void removeEmployee(const int id) {
            mutable std::set<Employee>::iterator employee;

            for (employee = this->employees.begin(); employee != this->employees.end(); employee  ) {
                if (employee->getId() == id) {
                    employee->setSalary(0);
                    this->employees.erase(employee);
                    return;
                }
            }
            throw EmployeeNotHired();
        }

And the error I'm getting-

C:\Users\User\CLionProjects\hw2Cpp\Manager.h:53:50: error: non-member 'employee' cannot be declared 'mutable'
             mutable std::set<Employee>::iterator employee;
                                                  ^~~~~~~~
C:\Users\User\CLionProjects\hw2Cpp\Manager.h:57:42: error: passing 'const mtm::Employee' as 'this' argument discards qualifiers [-fpermissive]
                     employee->setSalary(0);

What should I do?

**** edit**** I tried changing it to:

class Employee : public Citizen {
protected:
    mutable int salary;
    mutable int score;
    std::set<Skill> skills;

But I am still unable to change the salary to 0.

error: passing 'const mtm::Employee' as 'this' argument discards qualifiers [-fpermissive]
                     employee->setSalary(0);

CodePudding user response:

That's not how it works. You can change a value through a const reference, if the member is marked mutable (mutable int salary;) not the iterator.

However, why do you want to set the salary to zero just before you delete it? And anyway, changing values in a set is not allowed if it affects the order of that set, so generally a bad idea.

CodePudding user response:

The design of std::set ensures that elements of the set "cannot be modified" i.e. they can only be accessed via const references. This is for a good reason: std::set relies on the order of its elements remaining the same thoughout the lifetime to maintain its internal search tree datastructure.

Ways to deal with this are:

  1. declaring setSalary as a const member function. (Not a good idea since setting the salary probably does modify the object in a way that wouldn't be expected of a const function.)
  2. Extract the employee (C 17)
    //employee->setSalary(0);
    //this->employees.erase(employee);
    auto node = employees.extract(employee);
    node.value().setSalary(0);
    
  3. Choose a different data structure such as a std::unordered_map<int, Employee> mapping from id to Employee or std::vector<Employee>.

However unless the setSalary function has effects other than modifying the Employee object, just remove the object from the set; The object is deleted in the process anyways...

  •  Tags:  
  • Related