いくつかのタイプの要素があり、それらのすべてのタイプに対して「マネージャー」を作成したいとします。マネージャーは、要素の作成、アクティブ化/非アクティブ化、および削除を処理します(ユーザーは、マネージャーを使用せずにこれらの要素のインスタンスを作成/破棄しないと想定しています。コードの非常に単純な例は、次のようになります。 :
template <class T>
class NonCachedElementMngr
{
public:
NonCachedElementMngr():
rmCounter(0)
{}
~ NonCachedElementMngr()
{
T* element = 0;
if(mElements.size() > 0)
{
typename std::set<T*>::iterator it;
for(it = mElements.begin(); it != mElements.end(); ++it)
{
element = *it;
element->deactivate();
delete element;
}
}
}
T* create()
{
T* element = new T();
element->activate();
mElements.insert(element);
return element;
}
bool release(T* element)
{
bool ret = false;
typename std::set<T*>::iterator it;
it = mElements.find(element);
if(it != mElements.end())
{
element->deactivate();
delete element;
mElements.erase(it);
ret = true;
}
return ret;
}
private:
std::set<T*> mElements;
int rmCounter;
};
ここで、オブジェクトのサブグループについて、基本的な操作とは別に、いくつかのキャッシュも行う必要があると想像してみましょう。そのタイプのサブグループに対して、次のような別の「マネージャー」を定義できます。
template <class T>
class CachedElementMngr
{
public:
CachedElementMngr():
rmCounter(0)
{}
~CachedElementMngr()
{
T* element = 0;
if(mElements.size() > 0)
{
typename std::set<T*>::iterator it;
for(it = mElements.begin(); it != mElements.end(); ++it)
{
element = *it;
element->removeFromCache(); // <<<<<<<<<<<<<< Different line
element->deactivate();
delete element;
}
}
}
T* create()
{
T* element = new T();
element->storeInCache(); // <<<<<<<<<<<<<< Different line
element->activate();
mElements.insert(element);
return element;
}
bool release(T* element)
{
bool ret = false;
typename std::set<T*>::iterator it;
it = mElements.find(element);
if(it != mElements.end())
{
element->removeFromCache(); // <<<<<<<<<<<<<< Different line
element->deactivate();
delete element;
mElements.erase(it);
ret = true;
}
return ret;
}
private:
std::set<T*> mElements;
int rmCounter;
};
明らかなように、そのようにマークされた3行を除いて、両方のマネージャーはまったく同じです。この2つのテンプレートをリファクタリングするにはどうすればよいですか?コンパイル時に、特定のタイプがキャッシュ可能かどうかがわかります。デストラクタにも別の行があることに注意してください。実行可能な提案(仮想継承、テンプレートの特殊化、SFINAE ...)は大歓迎です。