3mbd3v
3mbd3v

Reputation: 21

Moving object which is referred

I have two structs:

struct A
{};

struct B
{
    A& a;
};

and initialize them A a0; B b{a0};. But now, I want to move object a0 to new one:

A a1{std::move(a0)};

I don't know how to inform b that the value of it's member a should be changed. It's impossible to change value of standard reference, so I was thinking to change it into std::reference_wrapper or something similar. But still there is a problem - how to inform object b (specifically - its member which now is some kind of smart reference) that value of field a should be changed?

I was thinking about observer pattern, where A will be subject and B member referring to A will be observer. After moving subject, it will send all observers its new address. It may be solution, but maybe there is something easier?


As appendix, why I use something like that. In my project, I have another structure (simplified version below):

struct C
{
    A a;
    B b{a};
};

A is wrapper to memory (pointer to memory is given to A in constructor, but here not mentioned to keep it simple), it knows size of allocated memory and how to write and read it. B is object which knows how to insert some values to memory (i.e. how to insert int32_t - in LE or BE, how to serialize compound object). This two structures are in some closed library (company library, so I can open issue to change it, but it is used in some other projects, so I must be sure what kind of changes I need and are they really necessary). C gives me interface to put only specific objects into memory - I get only raw memory to construct it, so I must handle creating objects A and B inside it and outside C nobody needs to know what dependencies I use to write into this memory.

Structure C should be movable, because it will be returned using std::optional - its constructor is private and there exists static method create which builds object of C depending on status of some other operations needed to construct it (here described simply using bool argument):

static std::optional<C> create(bool v)
{
    return v ? std::optional<C>{C()} : std::optional<C>{};
}

To tests, I also write constructor of C:

C()
{
    std::cout << "C::C()" << std::endl << &a << std::endl << &b.a << std::endl;
}

and function which is trying to build this object:

auto c = C::create(true);
std::cout << "main" << std::endl;
std::cout << &(c.value().a) << std::endl;
std::cout << &(c.value().b.a) << std::endl;

Here is result of executing this test:

C::C()
0x7ffe8498e560
0x7ffe8498e560
main
0x7ffe8498e570
0x7ffe8498e560

which shows that C member b holds wrong reference now.

I'm open to criticism, because I know it could be bad design and maybe I should do it in some other way.

Upvotes: 2

Views: 104

Answers (1)

Jarod42
Jarod42

Reputation: 217255

Your class C should be:

struct C
{
    C(const C& c) : a(c.a), b(this->a) {}
    C(C&& c) : a(std::move(c.a)), b(this->a) {}

    A a;
    B b{a};
};

Then your reference is still valid.

Upvotes: 2

Related Questions