私は一連のオブジェクトの遅延初期化のためのクラスを作成しています (完全に汎用的ではなく、すべて私の制御下にあります)。各タイプのオブジェクトは 1 つだけ存在します。std::vector
andを使用した線形時間の実装が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);
}
}