5

ファイルから読み取った 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 ...

このソリューションは機能しますが、はるかに簡単に実行できると確信しています。私が思いついた他のより単純な解決策は、たとえば型消去のために失敗しました。

それについて何か助けていただければ幸いです。ありがとう!

4

1 に答える 1

2

あなたのソリューションに似ていますが、void* はありません。

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;
}
于 2013-06-20T14:40:37.507 に答える