假设我们有几种类型的元素,我们想创建一个 每种类型的“经理”。经理负责 任何元素的创建、激活/停用和删除 (我们假设用户不会创建/销毁这些元素的实例 不使用经理。 一个非常简单的代码示例如下所示:
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;
};
很明显,除了 三行标记为如此。 我该如何重构这两个模板? 我们在编译时知道特定类型是否可缓存。 请注意,析构函数中也有不同的行。 任何可行的建议(虚拟继承、模板特化、SFINAE...)都将受到欢迎。
最佳答案
将特定行为分解为策略:
#include <set>
struct cached_tag;
struct noncached_tag;
template<typename Tag>
struct ElementMngrCachePolicy;
template<>
struct ElementMngrCachePolicy<cached_tag>
{
template<typename T>
static void removeFromCache(T* const element) { /*impl...*/ }
template<typename T>
static void storeInCache(T* const element) { /*impl...*/ }
};
template<>
struct ElementMngrCachePolicy<noncached_tag>
{
template<typename T>
static void removeFromCache(T* const) { /*do nothing*/ }
template<typename T>
static void storeInCache(T* const) { /*do nothing*/ }
};
template<typename T, typename CachePolicy>
class ElementMngr
{
typedef std::set<T*> elements_t;
public:
ElementMngr() :
rmCounter()
{ }
~ElementMngr()
{
for (typename elements_t::iterator it = mElements.begin(); it != mElements.end(); ++it)
{
T* const element = *it;
CachePolicy::removeFromCache(element);
element->deactivate();
delete element;
}
}
T* create()
{
T* const element = new T();
CachePolicy::storeInCache(element);
element->activate();
mElements.insert(element);
return element;
}
bool release(T* const element)
{
typename elements_t::iterator it = mElements.find(element);
if (it == mElements.end())
return false;
CachePolicy::removeFromCache(element);
element->deactivate();
delete element;
mElements.erase(it);
return true;
}
private:
elements_t mElements;
int rmCounter;
};
template<typename T>
class CachedElementMngr : public ElementMngr<T, ElementMngrCachePolicy<cached_tag> >
{ };
template<typename T>
class NonCachedElementMngr : public ElementMngr<T, ElementMngrCachePolicy<noncached_tag> >
{ };
关于c++ - 模板重构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5741146/