To understand what the issue is, let's imagine that you wrote this code instead:
void addNeighbour(Element*& neighbour)
{
m_neighbours.emplace_back(neighbour);
neighbour->addNeighbour(this);
neighbour = nullptr; // <--- This is new
}
Now, think about what happens when you make this call:
neighbour->addNeighbour(this);
The call to the function passes in this
by reference, meaning "please, feel free to reassign this
." And then in the function call, the last line, indeed, tries to reassign neighbour
to nullptr
. But that's a problem, because you can't write
this = nullptr; // Error!
because this
is an rvalue.
The easiest fix here would be to not take the parameter by reference, since you aren't doing anything to it where you'd actually need the reference. Just take in an Element*
, saying "please hand me a copy of the pointer you're interested in."
(Independently - your code will get you into trouble because calling A->addNeighbour(B)
will call B->addNeighbour(A)
, which calls A->addNeighbour(B)
, which calls B->addNeighbour(A)
, etc. until you blow out your call stack. You should add a check in here to make sure that, if the Element
already is recorded, you don't add it a second time. You may want to make m_neighbours
a std::unordered_set
rather than a std::vector
for that purpose.)