1

I'm stuck. When trying to add a new element to the vector of strings inside a struct via the iterator I get this error about const qualifier:

error: passing ‘const std::vector<std::__cxx11::basic_string<char> >’ as ‘this’ argument discards qualifiers [-fpermissive]
  175 |  p->children.push_back("New child");

The code:

typedef struct Concept_tree
{ 
    string id;
    string name; 
    std::vector<string> children; 

    bool operator==(const Concept_tree &ct2)
    {
        return (id == ct2.id);
    } 

    Concept_tree()                                           { };
    Concept_tree(string id):              id(id)             { };
    Concept_tree(string id, string term): id(id), name(term) { };
} 
Concept_tree;


namespace std 
{
    template<>
    struct hash<Concept_tree> 
    {
       size_t operator()(const Concept_tree &ct) const
       {
          return std::hash<string>()(ct.id);
       }
    };
}

...

std::unordered_set<Concept_tree> ct_uset; 

...

string test = "id00001";

auto p = ct_uset.find(test);

p->children.push_back("New child");

I understand the cause of the error but can't deduce its exact position. Is it that the constructors are implemented improperly? Could anyone help?

Pulsar
  • 13
  • 4
  • Mark children vector as mutable (now you can only read this vector because p is const iterator). – rafix07 Apr 20 '21 at 21:14
  • It worked! [rafix07](https://stackoverflow.com/users/8950365/rafix07) and [ShadowRanger](https://stackoverflow.com/users/364696/shadowranger), you have my gratitude! – Pulsar Apr 20 '21 at 21:20

1 Answers1

3

You got the iterator p from an unordered_set; the contents of unordered_set are immutable (to avoid violating invariants), and the iterator returned is a const view of the elements to ensure that.

You could mark children as mutable so it can be mutated even when the Concept_tree is const (since it's not part of equality/hash computation, this might be okay). But this will make it possible to mutate children even when you want a Concept_tree to be logically const. To avoid that, you could use an unordered_map mapping just the id (immutable key) to the actual Concept_tree (mutable value) object.

Side-note: You probably want to mark your operator== as const so this is const, or make it a non-member function with both argument const per What are the basic rules and idioms for operator overloading?.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • Yeah just forgot that `const` qualifier for `==`. Thanks also for the idea regarding storing id and Concept_tree object in an `unordered_map`. I thought over how to implement it but the only idea I came up was `unordered_set`. – Pulsar Apr 20 '21 at 21:25