Reputation: 21
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
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