Estou limitado ao C++17. Preciso fazer uma estrutura de árvore (não necessariamente binária) que possa ser profundamente copiada em 2 clones independentes. Atualmente, tenho uma Node
classe de interface onde há 2 implementações:
Uma
Operation
classe contém um enum representando a operação booleana a ser realizada em seusstd::vector<std::unique_ptr<Node>>
operandos. Esses constituem os ramos na árvore.Uma
Condition
classe contém os dados que serão comparados quando for dito para avaliar. Eles compõem as folhas na árvore.
Por fim, tenho uma Event
classe com a std::unique_ptr
que aponta para a raiz Node
desta árvore. Tanto Operation
an quanto Condition
podem ser a raiz da árvore.
Tenho seguido esta postagem do blog em relação à clonagem adequada de um std::unique_ptr
, mas não sei bem como manter a parte polimórfica dos construtores de cópia das classes Event
and Operation
. Ter esses construtores de cópia é uma parte inerente do meu problema?
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
namespace tree
{
struct Node
{
// Virtual clone function to make a new std::unique_ptr
// with a copy of the contents of the old std::unique_ptr
// Both std::unique_ptrs will be independent of each other
virtual std::unique_ptr<Node> clone() const = 0;
std::string name;
};
enum class Boolean
{
And,
Or,
Xor
};
struct Operation : public Node
{
// Copy constructor (because copying a std::vector is non-trivial)
// that will allocate a new std::vector of the same size and clone
// new std::unique_ptrs from the other std::vector
Operation(const Operation &other) : op(other.op), nodes(other.nodes.size())
{
std::transform(other.nodes.cbegin(), other.nodes.cend(), nodes.begin(),
[](const auto &old) {
// This line has the compilation error because Node is abstract,
// but I need this for the polymorphism, correct?
return op ? std::make_unique<Node>(old->clone()) : nullptr;
});
}
// Clones this class
virtual std::unique_ptr<Node> clone() const override
{
return std::make_unique<Operation>(*this);
}
Boolean op;
// Can hold any number of other Operation or Condition objects
std::vector<std::unique_ptr<Node>> nodes;
};
struct Condition : public Node
{
// Clones this class
virtual std::unique_ptr<Node> clone() const override
{
return std::make_unique<Condition>(*this);
}
int datum;
};
struct Event
{
Event(std::string name) : name(name) {}
// This line has the same compilation error
Event(const Event &other) : name(other.name), root(std::make_unique<Node>(other.root->clone())) {}
std::string name;
std::unique_ptr<Node> root;
};
} // tree