c++ - 模板重构

标签 c++ templates refactoring template-specialization

假设我们有几种类型的元素,我们想创建一个 每种类型的“经理”。经理负责 任何元素的创建、激活/停用和删除 (我们假设用户不会创建/销毁这些元素的实例 不使用经理。 一个非常简单的代码示例如下所示:

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/

相关文章:

c++ - GNU Make 因 If 语句中的语法错误而退出

c++ - 大小为 8 的读取无效,但没有内存泄漏

c++ - 字符串复制函数产生 `pointer being freed was not allocated`

javascript - 有没有更干净的方式来链接这些 Bluebird promise ?

java - 如何继承/使用多个类的方法

c++ - Valgrind报告QThread::start()上的内存泄漏

c++ - 在从模板化中介派生的类中调用非模板基类构造函数

c++ - 如何推断可变参数之后的模板参数?

c++ - 如何避免在实现中重复类名和模板调用?

vim - 使用 vim 在目录中重构类/方法/字符串的有效方法