2013-06-20 6 views
5

ファイルから読み込んだC++ツリー構造でデータが格納されています。ツリーは次のようになります。ツリー変換でのテンプレートと継承の結合

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

ツリーが作成されたら、それを変換します。文字列に変換する。ツリーノードがBaseNode*として格納されているので、私ドン、

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

しかし:変換コードから別のツリーのコードを保つために

、私はそのような何かを実装する、すなわちテンプレートを使用したいと思いますそのようなテンプレートメンバ関数にアクセスする方法はわかりません。テンプレートのメンバ関数は継承できないので、これはうまくいくとは思わない。私も実用的なソリューション、と思いついたの

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; 

戻り

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(); 
    } 
}; 

そして、変換ロジックを完全に分離することができ期待される結果:

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

このソリューションは機能しますが、もっと簡単に行うことができます。私が思いついた他の単純な解決策は、失敗しました。タイプ消去のためです。

私はそのことについてお手伝いします。ありがとう!

答えて

2

あなたのソリューションに似ていますが、ボイドなしのもの*。

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; 
} 
+0

感謝。 voidポインターを避ける方が少し優雅です。しかし、私はもっとコンパクトなものを探していました。おそらくコンバージョンやビジタークラスはありませんでした。 – DonDieselkopf

+0

これは完全に実行可能ではありません。 C++ 11のサポートはありますか? –

+0

はい、あります。 C++ 11のソリューションがあれば、私は興味があります。私は実際にCRTPのような解決策を期待していました。しかし、私のアプリケーションを見て、私はますます訪問者のパターンに固執するように誘惑されます。それにもかかわらず、他の意見は大歓迎です。 – DonDieselkopf

関連する問題