-1

Good evening,

I'm working on a piece of code that used to work perfectly fine using std::set.

However, due to a need of an inherent order between objects, I'm going to have to convert it to a vector.

I'm experiencing some issues with iterating over elements of said vector, whereas everything worked perfectly fine when it was defined as an std::set.

The vector is defined as a property of the following Manager class, as such:

    class Manager : public Citizen {
        std::vector<Employee*> employees;

This Manager class overrides a pure virtual printing method from its parent class with the following signature:

std::ostream& printLong(std::ostream& os) const override;

The method implementation is as following:

    std::ostream& Manager::printLong(std::ostream& os) const {
    // Personal info
    os << this->first_name << " " << this->last_name << endl;
    os << "id - " << this->id_number << " ";
    os << "birth_year - " << this->birth_year << endl;
    os << "Salary: " << this->salary << endl;

    // Do not print employees in case there are none
    if (this->employees.empty()) {
        return os;
    }

    // Employee info
    os << "Employees:" << endl;

    std::vector<Employee*>::iterator i = this->employees.begin();
    while (i != employees.end()) {
        Employee* current_employee = (*i);
        current_employee->printShort(os);
        ++i;
    }
    
    return os;
}

The problematic line is:

        std::vector<Employee*>::iterator i = this->employees.begin();

VSCode throws the following error:

no suitable user-defined conversion from "__gnu_cxx::__normal_iterator<mtm::Employee *const *, std::vector<mtm::Employee *, std::allocator<mtm::Employee *>>>" to "__gnu_cxx::__normal_iterator<mtm::Employee **, std::vector<mtm::Employee *, std::allocator<mtm::Employee *>>>" existsC/C++(312)

Why is this not working? What can I do to fix this?

It's worth mentioning that this is part of a course problem where we're not allowed to use auto.

Alternatively, if using vector is not an option in your opinion, what I'm trying to accomplish is to maintain an order between elements so that I can print them according to how they were added/removed by the user into the list of employees.

2 Answers2

3

this is a pointer to const Manager, this->employees.begin(); returns std::vector<Employee*>::const_iterator. The fix:

// std::vector<Employee*>::iterator i = this->employees.begin();
std::vector<Employee*>::const_iterator i = this->employees.begin();

Even better

auto i = this->employees.begin();
273K
  • 29,503
  • 10
  • 41
  • 64
1

You're calling begin() from a const method, so employees is const, which means the begin() overload that gets selected returns a std::vector<Employee*>::const_iterator, not std::vector<Employee*>::iterator. Change your variable declaration accordingly:

std::vector<Employee*>::const_iterator i = this->employees.begin();
Etienne de Martel
  • 34,692
  • 8
  • 91
  • 111
  • Thank you for your comment! Why did this work without a const_iterator when I was using this a an std::set, then? It shouldn't have worked if that's the case. – HitoriJanai Jan 13 '22 at 01:13
  • It shouldn't work either. You can't get a non const iterator from a const container, regardless of the container. Maybe you changed something else besides the vector and didn't notice? – Etienne de Martel Jan 13 '22 at 01:20
  • `std::set` [doesn't like it](https://stackoverflow.com/questions/908949/what-happens-when-you-modify-an-element-of-an-stdset) when you try to modify one of its elements. Perhaps in the implementation `std::set::iterator` was an [alias](https://en.cppreference.com/w/cpp/container/set#Notes) for `std::set::const_iterator` to begin with, in which case assigning a `const_iterator` to an `iterator` would be fine. – Nathan Pierson Jan 13 '22 at 06:33
  • Maybe that particular implementation bodged it, yes, because it _should_ return a `const_iterator`. – Etienne de Martel Jan 13 '22 at 15:57