unordered set of shared pointers of a custom class

Viewed 68

I'm trying to use unordered set with shared pointers of a custom class

the class is the following :

class BASE
{
public:
    BASE(std::string name) : _name{ name } {}
    std::string getName() const { return _name; }
    void setName(std::string name) { _name = name; }

    friend bool operator==(std::shared_ptr<BASE> b1, std::shared_ptr<BASE> b2);
private:
    std::string _name;
};

struct BaseHash {
    size_t operator()(std::shared_ptr<BASE> b) const { return std::hash<std::string>()(b->getName()); }
};

bool operator==(std::shared_ptr<BASE> b1, std::shared_ptr<BASE> b2)
{
    return b1->getName() == b2->getName();
}

Then I created the following example :

std::unordered_set<std::shared_ptr<BASE>, BaseHash> bases;
    bases.insert(std::make_shared<BASE>("base0"));
    bases.insert(std::make_shared<BASE>("base1"));

    bases.insert(std::make_shared<BASE>("base0")); // LINE C

As expected in the LINE C when I tried to add another object with the same argument base 0 (which already exists in the unordered set) it was not added.

but the problem in this example that someone can use the function setName from the base class and change the name of base 1 to base 0. in this case could we have two objects with same key in the same unordered_set ?

I did not understand how things work in this case.

Please note :

  • The reason why I'm using unordered set is that I want unique objects of BASE in the set, and I want fast insertion, removal and search.
  • I want to use shared pointers because I don't want to copy the elements in the unordered set, and also I want to call not constant functions for them.
  • I may misunderstood something, I never used unordered set with custom object
1 Answers

If you have two objects in your set with "name1" and "name2" as names. And you change the name of one of the objects, such that you have two objects with the same name. Then your set will still have the keys "name1" and "name2".

If you want the keys of the set to be correctly updated, then you need to write a container class for your set. For example:

class MySet
{
public:
  bool insert(std::shared_ptr<BASE> p)
    {
      if (bases.find(p->getName())!= bases.end())
      {
        bases.insert(p);
        return true;
      }
      return false;
    }
private:
  std::unordered_set<std::shared_ptr<BASE>, BaseHash> bases
};

This code was quickly written so excuse any mistakes.

Related