1

私は一連のオブジェクトの遅延初期化のためのクラスを作成しています (完全に汎用的ではなく、すべて私の制御下にあります)。各タイプのオブジェクトは 1 つだけ存在します。std::vectorandを使用した線形時間の実装がboost::any既にあります。うまくいけば、私が話していることのより良いアイデアが得られるはずです。

私がアクセスしたいすべてのオブジェクトが持っていると仮定することができます

typedef boost::shared_ptr<CLASSNAME> HandleType

それらはすべて、参照によって ObjectProvider を受け取るコンストラクターを持っています。

class ObjectProvider {
    typedef std::vector<boost::any> ContainerType;
    ObjectProvider() : container() {}

public:

    // this is where the relevant method is
    template <class TElementType>
    typename TElementType::HandleType get() {
        for (ContainerType::iterator it = container.begin(); it != container.end(); ++it) {
            try {
                return boost::any_cast<typename TElementType::HandleType>(*it);
            } catch (boost::bad_any_cast &) {}
        }
        // failed to find it so create it
        TElementType::HandleType handle = boost::make_shared<TElementType>(*this);
        container.push_back(handle);
        return handle;            
    }

private:
    ContainerType container;
};


// ----- FOR TESTING -----
class SomeObject {
public:
     SomeObject(ObjectProvider &) {}
     typedef boost::shared_ptr<SomeObject> HandleType;
};

int main(int argc, char** argv) {
    ObjectProvider provider;

    // expensive creation is done here
    SomeObject::HandleType obj1 = provider.get<SomeObject>();

    // expensive creation is not re-done
    SomeObject::HandleType obj2 = provider.get<SomeObject>();
    assert (obj1 == obj2); // pointers should point to the same object

}

動機: これらのオブジェクト (さまざまなサービスのクライアント) の多くは、さまざまな種類の追加のクライアントを作成する必要がありますが、毎回再作成する必要はありません。したがって、このクラスの目標は、作成済みのクライアントをキャッシュする方法を提供することです。

これが私の質問です:

  • これを行うより良い方法はありますか?

  • 特に、ループインを回避しget<...>()、何らかの方法でタイプごとにキーを設定する方法はありますか? 線形時間ではなく一定時間のアクセスが欲しいのですが、現在の方法では検索に使用できる型情報を利用できません。

私が考えていることの少しの追加説明のために、Javaで次のようなことをするかもしれません:

Map<Class<?>, Object> objMap;
public <T> T get(Class<T> class) {
    Object obj = objMap.get(class);
    if (obj != null) {
        return (T)obj;
    } else {
        T newObj = ;// fiddle with java reflection to create a new instance
        objMap.put(class, newObj);
    }
 }
4

4 に答える 4

0

一定時間アクセスしたい場合は、独自のタイプ ID を作成できます。

class Registry
{
private:
    static int get_id()
    {
        static int id = 0;
        return id++;
    }

    template< typename T>
    static int get_type_id()
    {
        const static int id = get_id();
        return id;
    }
    std::vector<HandleType> handles;
    HandleType make_handle( const Registry&r)
    {
        // do what you need to do to create a new handle.
    }
public:
    template<typename T>
    HandleType get()
    {
        int id = get_type_id<T>();
        if (id + 1 > handles.size())        
        {
            handles.resize( id + 1, HandleType());
        }
        if (!handles[id])
        {
            handles[id] = make_handle( *this);
        }
        return handles[id];
    }

};

編集:私は、この回答が各タイプの数値IDも自動的に作成しようとすることを除いて、基本的にumlumと同じ回答をしたことがわかります。

于 2013-08-27T19:28:22.740 に答える