c ++ Использование reinterpret_cast для приведения unique_ptr <Derived>* к unique_ptr <Base>* для создания трансформируемой древовидной структуры - PullRequest
0 голосов
/ 05 апреля 2020

В настоящее время я пишу программу, которая должна манипулировать древовидной структурой (абстрактным синтаксическим деревом).
В дереве узел имеет своих потомков как unique_ptr и выглядит так:

struct Node {
  // to replace node itself in the tree:
  // points to unique_ptr that owns this node
  // a node can be stored in different unique_ptr types
  //  -> for example: NodeY could be stored in unique_ptr<NodeY> or unique_ptr<NodeX>)
  //  ->   thus self has to be of type unique_ptr<Node>*
  unique_ptr<Node> *self;
  // ...
};

struct NodeX: Node {
  unique_ptr<Node> child1;
  unique_ptr<NodeY> childY;
};

struct NodeY: Node {
  unique_ptr<NodeX> child1;
  unique_ptr<NodeY> child2;
  vector<unique_ptr<NodeY>> otherChildren;
};

struct NodeZ: NodeY {
  // ...
};
// and a lot of other nodes with different child types ...

При изменении В дереве должна быть возможность заменить узел в дереве.
Для этой цели я сохраняю указатель self на свойствующий unique_ptr в каждом узле. Действие замены будет выглядеть следующим образом:

// could replace node:
void visitNodeY(NodeY *node) {
  if (node->someCondition) {
     // replace
     auto newNode = make_unique<NodeZ>();
     unique_ptr<Node> *self = node->self; 
     // replace with make_unique<NodeA>() would break inheritance hierarchy, but i will not do it :)
     *self = move(newNode); // replace and delete old node
     node = self.get();     // get new address
     node->self = self;     // self still points to same address, only contend of unique_ptr has changed
  }
}

Теперь проблема заключается в установке указателя self после построения узла.
Для достижения этого я использую reinterpret_cast:

void createNodeX_children(NodeX *nodex) {
  // create childY
  nodex->childY = make_unique<NodeY>();
  // ...
  // is that save?
  nodex->childY->self = reinterpret_cast<unique_ptr<Node>*>(&nodex->childY);
}

Мой вопрос сейчас: можно ли сохранить с помощью reinterpret_cast таким образом, пока я не нарушу иерархию наследования, как упомянуто выше?

1 Ответ

2 голосов
/ 05 апреля 2020

Не reinterpret_cast. Вы можете использовать std::unique_ptr конструкторы для полиморфной передачи собственности.

...