Объединение шаблонов и наследования в преобразовании дерева

У меня есть данные, хранящиеся в древовидной структуре C ++, которые я читаю из файла. Дерево выглядит так:

class BaseNode {
std::vector<BaseNode*> children_;
...
};
class WhiteNode : public BaseNode { ... };
class BlackNode : public BaseNode { ... };

После того, как дерево построено, я хотел бы преобразовать его, например, в строку.

Чтобы отделить код дерева от кода преобразования, я хотел бы использовать шаблоны, то есть реализовать что-то подобное:

template <class T>
T WhiteNode::Convert() { ... };

Тем не менее, так как узлы дерева хранятся как BaseNode*Я не знаю, как получить доступ к такой функции-члена шаблона. И поскольку функции-члены шаблона не могут быть унаследованы, я не думаю, что это будет работать.

Я придумала рабочее решение, хотя:

class BaseConversion {
public:
virtual ~BaseConversion() {}
virtual void * FromBlack() = 0;
virtual void * FromWhite() = 0;
};

template <class T>
class Conversion : public BaseConversion {
public:
void * FromBlack();
void * FromWhite();
};

class BaseNode {
std::vector<BaseNode*> children_;
virtual void * Convert(BaseConversion * conversion) = 0;
public:
virtual ~BaseNode() {}
template <class T>
T Convert() {
return *static_cast<T*>(Convert(new Conversion<T>));
}
};

class WhiteNode : public BaseNode {
void * Convert(BaseConversion * conversion) {
return conversion->FromWhite();
}
};

class BlackNode : public BaseNode {
void * Convert(BaseConversion * conversion) {
return conversion->FromBlack();
}
};

И логика преобразования может быть совершенно отдельной:

template <>
void * Conversion<std::string>::FromWhite() {
return new std::string("converting WHITE node to std::string ...");
}

template <>
void * Conversion<std::string>::FromBlack() {
return new std::string("converting BLACK node to std::string ...");
}

Тестирование кода:

BaseNode * node = new BlackNode;
std::cout << node->Convert<std::string>() << std::endl;
node = new WhiteNode;
std::cout << node->Convert<std::string>() << std::endl;

возвращает ожидаемый результат:

converting BLACK node to std::string ...
converting WHITE node to std::string ...

Хотя это решение работает, я уверен, что это можно сделать гораздо проще. Любое другое, более простое решение, которое я нашел, не удалось, например, из-за стирания типа.

Я был бы признателен за любую помощь в этом. Спасибо!

5

Решение

Нечто похожее на ваше решение, но без пустоты *.

class NodeVisitor
{
virtual void VisitBlack(BlackNode* node);
virtual void VisitWhite(BlackNode* node);
};

class BaseNode {
std::vector<BaseNode*> children_;
...
virtual void visit(NodeVisitor* visitor) = 0;
};

class WhiteNode : public BaseNode {
virtual void visit(NodeVisitor* visitor) { visitor->visitWhite(this); }
};

class BlackNode : public BaseNode {
virtual void visit(NodeVisitor* visitor) { visitor->visitBlack(this); }
};

затем

std::string convert(BaseNode* node)
{
class ConvertVisitor
: public NodeVisitor
{
ConvertVisitor(std::string* res)
: m_res(res)
{ }

virtual void VisitBlack(BlackNode* node)
{
*m_res = // convert black node to string;
}

virtual void VisitWhite(BlackNode* node)
{
*m_res = // convert white node to string;
}

std::string* m_res;
};

std::string res;
ConvertVisitor visitor(&res);
node->visit(&visitor);
return res;
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]