0

I have created 2 custom structs on my project and each one have a std::set.

struct Subject {
        std::string name;
        std::set<SubjectFrame> frames;

        Subject(std::string subject_name);

        void AddFrame(SubjectFrame &frame);

        bool operator<(const Subject &rhs) const { return (name  < rhs.name);}
        bool operator==(const Subject &rhs) const { return (name == rhs.name);}
};

struct Dataset {
        std::set<Subject> subjects;
        std::map<int, std::vector<Subject> > classification_groups;

        Dataset(const std::string ds_path);

        void AddSubject(Subject &subject);
        void GetDSFromFileSystem(const std::string dataset_path);
        void GetClassificationGroups(int number_of_groups_to_create);
};

Every time I wanna add some frame to my set 'frames' I call this function:

void Dataset::AddSubject(Subject &subject) {
        set<Subject>::iterator it = this->subjects.find(subject);
        if (it != this->subjects.end()) {
                for (Subject fr : this->subjects) {
                        it->AddFrame(fr);
                }
        }   else this->subjects.insert(subject);
}

That calls this function:

void Subject::AddFrame(SubjectFrame &frame) {
        set<SubjectFrame>::iterator it = this->frames.find(frame);
        if (it != this->frames.end()) {
                if (frame.l_eye_centroid.x != 0) {
                        it->r_eye_centroid = frame.r_eye_centroid;
                        it->l_eye_centroid = frame.l_eye_centroid;
                }
                if (frame.path != "") it->path = frame.path;
                else return;
        }
        else this->frames.insert(frame);
}

So, the logic behind an add operation is: I pass an object and check if there's a object with that name already inside my std::set. If yes, I update the existent object with the informations that my parameter object has and the already registered object don't have, if no I insert the object.

I'm getting this errors when I try to compile my program:

error: no viable overloaded '=' it->r_eye_centroid = frame.r_eye_centroid;

error: no viable overloaded '=' it->l_eye_centroid = frame.l_eye_centroid;

error: no viable overloaded '=' if (frame.path != "") it->path = frame.path;

error: member function 'AddFrame' not viable: 'this' argument has type 'const Subject', but function is not marked const it->AddFrame(fr);

Someone has any idea what is causing, and how I can solve, these problems?

chr0x
  • 1,151
  • 3
  • 15
  • 25
  • You will probably need to define an `operator=` or a copy constructor or both for your custom class. – callyalater Mar 17 '16 at 17:49
  • A `std::set` doesn't allow you to change the elements as that can mess up the ordering. You need to remove, modify and re-insert it. https://stackoverflow.com/questions/2217878/c-stl-set-update-is-tedious-i-cant-change-an-element-in-place – Galik Mar 17 '16 at 17:58

1 Answers1

5

For std::set, iterator-s are const, this is because they are used as key in the set which should not be modified to avoid any inconsistencies in strict weak ordering.

One way so solve it is to make the field you want to modify mutable, but make sure it is not used in your set ordering.

marcinj
  • 48,511
  • 9
  • 79
  • 100
  • `iterator` type for `std::set` were only made `const` since c++11. [Cppreference](http://en.cppreference.com/w/cpp/container/set). – callyalater Mar 17 '16 at 17:51
  • @callyalater, this is how the question is tagged. – SergeyA Mar 17 '16 at 17:55
  • That is true. I was just pointing it out so that if the OP wanted to ensure backwards compatibility, he could use `const_iterator` instead. – callyalater Mar 17 '16 at 17:56
  • TY for your answer @marcinj. But the problem wasn't solved doing this :/ I tried to use: const set::iterator it and const set::iterator it ; the errors are the same. I did it right? PS: defining the atributes as mutable I solve the first 3 errors, but the last error continues even if I set atributes as mutable. – chr0x Mar 17 '16 at 18:02
  • You need to make your function called on iterator const also. – marcinj Mar 17 '16 at 18:04
  • Actually you might reconsider this, making this function const and adding mutable in your class will make a mess in your design. Removing, modifying, readding element as Galik suggested would be more elegant. – marcinj Mar 17 '16 at 18:29