2

私のウィジェットライブラリでは、ユーザー提供のVIEWクラスを初期化するために、ある種の呼び出しチェーンを実装したいと思います。このクラスは、次のような追加機能を追加する別のクラスから派生する可能性があります。

#include <iostream>

template<typename VIEW>
struct App
{
    VIEW view;
    void init() {view.initialize(); }
};

template<typename DERIVED>
struct SpecializedView
{
    void initialize()
    {
        std::cout << "SpecializedView" << std::endl;
        static_cast<DERIVED*>(this)->initialize();
    }
};

struct UserView : SpecializedView<UserView>
{
    void initialize() {std::cout << "UserView" << std::endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    // Cannot be altered to: App<SpecializedView<UserView> > app;
    App<UserView> app; 
    app.init();
    return 0;
}

出力が次のようになるような、ある種の呼び出しチェーンを実現することは可能ですか(ユーザーが指定したVIEWクラスが「SpecializedView」から派生している場合)。

console output:

SpecializedView
UserView

もちろん、から派生したタイプで変数アプリをインスタンス化するのは簡単ですが、このコードはライブラリに隠されているため、変更できないようにする必要があります。言い換えると、ライブラリコードは、ユーザー派生型のみをパラメーターとして取得する必要があります。

4

1 に答える 1

1

initialize()クラスと基本クラスが存在し、initialize()メソッドを定義している場合は、それを呼び出す別の関数を作成することもできます。

template <class T>
void callInitialize(T* t) {
    t->initialize();
    IF_EXISTS(base_class<T>::bc::initialize)
        callInitialize<base_class<T>::bc>(t);
}

もちろん、呼び出しの順序を逆にすることもできます。

関数の存在を確認するためのテンプレートを作成することは可能ですか?を参照してください。の実装についてIF_EXISTS。また、base_class<T>は標準の構成ではなく、この回答は、これを自動的に実行できないことを示しています。セマンティクスは次のようになります。

template<T>
struct base_class<T> {
    typedef void bc;
};

template<>
struct base_class<UserView> {
    typedef SpecializedView<UserView> bc;
};

おそらくあなたのフレームワークはこれを行うための半自動の方法を許可しています。

于 2012-12-18T11:18:31.640 に答える