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 の「訪問」の 2 番目の (コメント付き) バージョンで同じことを直接行うふりをしています。

「this」の型が ElementBase<...>* であるため、明らかにこれは機能しません。

ElementBase内の実際の派生クラスへのポインター「this」をダウンキャストするにはどうすればよいですか?

4

1 に答える 1

3

user786653 が言うように、Curiously Recurring Template パターンはこれを解決できます

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;
    }
};
于 2012-12-13T18:50:11.903 に答える