2012-12-13 59 views
3

我試圖以參數化方式實現訪問者模式的修改版本,避免以這種方式爲每個具體元素重載一個「普遍訪問者」,但由於我在模板編程方面沒有太多的經驗,我不知道如何完成「模式」。使用模板實現「訪客模式」

代碼:

// test.cpp 
#include <iostream> 
#include <vector> 

using namespace std; 

struct Base 
{ 
    virtual ~Base() {} 
    virtual void visit() = 0; 
}; 

template<typename Visitor> 
struct ElementBase : public Base 
{ 
    // No virtual. 
    void visit() 
    { 
     _e.visit(this); 
    } 

private: 
    Visitor _e; 
}; 

// Atoms. 
template<typename Visitor> 
struct ElementA : public ElementBase<Visitor> 
{ 
    ElementA() : a(5) {} 

    int a; 
}; 

// Visitors. 
struct VisitorA 
{ 
    void visit(ElementBase<VisitorA> *a) 
    { 
     ElementA<VisitorA>* elto = dynamic_cast<ElementA<VisitorA>*>(a); 

     cout << elto->a << endl; 
    } 

    /* 
    void visit(ElementA<VisitorA> *a) 
    { 
     cout << a->a << endl; 
    } 
    */ 
}; 

std::vector<Base*> v; 

int main() 
{ 
    v.push_back(new ElementA<VisitorA>()); 

    for (auto i : v) 
     i->visit(); 
} 

能正常工作,其輸出爲5(如預期)。但是我假裝要做的是直接與VisitorA中的「訪問」的第二個(評論)版本相同。

顯然,這不起作用,因爲「this」的類型爲ElementBase < ...> *。

如何將指針「this」向下轉換爲ElementBase中的實際派生類?

+1

我不能完全肯定它會在你的情況下工作,但它聽起來像你要找的[奇怪的循環模板模式](http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Curiously_Recurring_Template_Pattern) – user786653

+0

我也認爲這種模式,但我不知道如何應用這個問題。 –

回答

3

像user786653稱,奇異遞歸模板模式可以解決這個

template<typename Visitor, typename Derived> 
struct ElementBase : public Base 
{ 
    void visit() 
    { 
     _e.visit(static_cast<Derived*>(this)); 
    } 

private: 
    Visitor _e; 
}; 

// Atoms. 
template<typename Visitor> 
struct ElementA : public ElementBase<Visitor, ElementA<Visitor> > 
{ 
    ElementA() : a(5) {} 

    int a; 
}; 

// Visitors. 
struct VisitorA 
{ 
    void visit(ElementA<VisitorA> *a) 
    { 
     cout << a->a << endl; 
    } 
}; 
+0

這個編譯? ElementA是一個參數結構,也許:「public ElementBase >>」? –

+0

而演員應該是「dynamic_cast」,不是嗎? –

+1

不,應該是'static_cast',請參閱http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern#Polymorphic_copy_construction。使用該模板可以在編譯時知道類型,因此不需要'dynamic_cast'的運行時間開銷。你是對的'公共ElementBase >>' – Peter