C++ Observer design pattern, prevent object from being reallocated

173 views Asked by At

Due to the fact that in some cases the objects are reallocated, for example in the case of std::vector, C++ observable pattern implementation can be problematic:

According to the "Gang of four" book, the implementation for an observable object looks like this:

class ObservableSubject {
public:
  virtual ~ObservableSubject() = default;
  virtual void notify() = 0;

protected:
  ObservableSubject() = default;

private:
  std::vector<Observer*> mObservers;
};

Where Observer looks like this:

class Observer {
public:
  virtual ~Observer() = default;

  virtual void update(ObservableSubject& subject) = 0;

protected:
  Observer() = default;
};

Considering this example:

class Mapper final: public Observer  {};

with the Mapper being held like this std::vector<Mapper>, the pointer held in mObservers will be invalidated as soon as std::vector<Mapper> reallocates the memory. The solution would be of course to use a pointer(i.e. std::shared_ptr) and have std::vector<std::shared_ptr<Mapper>>. This solution can be problematic as the developer has to remember that Mapper cannot be reallocated.

Is there a way to constraint a class in C++ not to be reallocated?

The implementation in the book: enter image description here enter image description here

1

There are 1 answers

0
Jarod42 On

You might disallow constructors and create a factory returning smart pointer:

class Mapper final: public Observer  {
     // Pass-key idiom to allow `std::make_unique` usage
     class private_key {
         private_key() = default;
     };
public:
    Mapper(private_key) {}

    Mapper(const Mapper&) = delete;
    Mapper(Mapper&&) = delete;

    static std::unique_ptr<Mapper> create() { return std::make_unique<Mapper>(private_key{}); }

    // ...
};

So address of the object is "stable".