-2

Class Owner owns multiple objects of class Item via unique_ptr. I want objects of Item to store a reference (not a pointer) to the Owner objects which owns them, with the following requirements:

  1. There can never be a dangling reference.

  2. The reference contained in an itm object of class Item never points to an Owner object which does not own itm.

  3. An Item object always has an owner.

  4. Item class will be used via its subclasses.

I tried automatically registering the objects of Item class during construction (in Item::Item()), but it leads to double deletion when they're created on the stack. Hence, I probably need to prevent them being created on the stack. But that's a problem when I am subclassing them. Is there an easier way of ensuring that the mutual links are always correct, without relaxing any of the requirements? I suspect that 3. might have to be relaxed, to enable creating the object first and registering it with the Owner later.

quant_dev
  • 6,181
  • 1
  • 34
  • 57
  • What is not clear in my question? Any suggestions of clarifications are more than welcome. – quant_dev Jun 17 '18 at 22:30
  • 3
    IMHO if the `Item`s are created on stack, and by stack I assume you mean they have automatic storage, then `Owner` doesn't really own them, at least resource-wise. Other that it seems that a reference to `Owner` in `Item` fits the bill. – luk32 Jun 17 '18 at 22:36
  • Thanks. So in order to ensure that `Item` is always owned by `Owner`, I have to block automatic storage for `Item`? – quant_dev Jun 17 '18 at 22:43
  • 2
    If you make sure that only `Owner` is allowed to construct an `Item`, and that the reference is passed into the `Item` on construction all your points should be covered. – super Jun 17 '18 at 23:00
  • Are you *sure* an `Item` actually *needs* to store a back-reference? Or could that be provided by the way you access it? – Deduplicator Jun 17 '18 at 23:37

1 Answers1

3

To elaborate on my comment, if you make Items constructor private, and take the reference to the owner on construction. Then you can make Owner a friend class, or as in my example make one of Owners function a friend function.

This way Items can only be created here and nowhere else. When they get created they get the reference to the Owner directly.

The reference in Item will always be valid, since when the Owner gets destroyed the Items it owns are destroyed with it.

#include <iostream>
#include <vector>
#include <memory>

class Item;

class Owner {
    public:
    std::vector<std::unique_ptr<Item>> foos;

    void makeItem();
};

class Item {
    Item(Owner& b) : owner(b) {}

    friend void Owner::makeItem();
    Owner& owner;
};

void Owner::makeItem() {
    foos.emplace_back(new Item(*this));
}

int main() {
    Owner b;
    //Item item(b); not allowed, constructor is private
    b.makeItem();
}

Not completely sure what you mean with point 4.

super
  • 12,335
  • 2
  • 19
  • 29
  • I suspect, that `Foo` will be a base class. Your example will probably have to be adapted to allow creation of custom `Foo`s, but I guess mimicking `std`'s `emplace` is possible and relatively easy. – luk32 Jun 17 '18 at 23:38
  • @luk32 You are probably right. It was not clear to me what OPs intention was for that or the usage of `Item`s so I left it out. – super Jun 17 '18 at 23:48