C++查找实例化的模板

C++ finding the instantiated templates

本文关键字:实例化 查找 C++      更新时间:2023-10-16

我刚刚在代码中发现了以下宝石(示例非常简化,但逻辑相同):

template <class T>
class garbage_bin
{
private:
    garbage_bin<T>(void)
    {
    }
   static garbage_bin<T>* pinstance;
public:
   static garbage_bin<T>& instance()
   {
       if(pinstance == NULL)
       {
           pinstance = new garbage_bin<T>();
       }
       return *pinstance;
   }
   void empty()
   {
       for(size_t i=0; i<items.size(); i++)
       {
           free (items[i]);
       }
   }
   void throwIn(T item)
   {
       items.push_back(item);
   }
   vector<T> items;
};

然后在代码中的某个地方(这只是一个例子......像这样的有数千个):

char* r = strdup(src);
garbage_bin<char*>::instance().throwIn(r);

后来在代码中的某个地方,就在退出之前......

garbage_bin<char*>::instance().empty();
garbage_bin<molecules*>::instance().empty();
garbage_bin<CDatabaseUsers*>::instance().empty();

等等...

因此,正如我们所看到的,这实现了一个垃圾箱类,您可以在其中"扔入"所有类型的对象,并且在稍后阶段为了避免内存泄漏,您可以"清空"垃圾箱。但这里出现了一个大瓶颈:为了使它正常工作,你需要知道实例化了这个垃圾箱的所有类,以便清空它们......

我想到的最直接的解决方案是为实例化创建一个typeid调用的映射,并将garbage_bin<T>::instance()分配给名称,但是古代编译器决定他不喜欢这种方法。

显然,我可以搜索代码以找到所有模板化,但我想知道......有没有更简单的方法可以做到这一点?

垃圾

桶!

class garbage_bin_base;
class garbage_bin_bin {
public:
    void throwIn(garbage_bin_base* rubbish) { items.push_back(rubbish); }
    void empty() { for (auto item: items) item->empty(); }
private:
    vector<garbage_bin_base*> items;
};
class garbage_bin_base {
public:
    virtual empty() = 0;
    garbage_bin_base() { garbage_bin_bin::instance().throwIn(this); }
};
template <typename T>
class garbage_bin : public garbage_bin_base {
};

您可以为要删除的内容添加注册表:

Registry registry;
// ...
if (pinstance == NULL)
{
     pinstance = new garbage_bin<T>();
     registry.add<T>();
}
// ...
registry.clear_all();

例如:

class Registry
{
     struct Base
     { 
         virtual ~Base() {}
         virtual void clear() = 0;
     };
     template <typename T> struct Derived : Base
     {
         virtual void clear() { garbage_bin<T*>::instance().empty(); }
     };
     std::vector<std::unique_ptr<Base>> targets;
public:
     void clear_all() { for (auto & p : targets) { p->clear(); } }
     template <typename T> void add()
     {
          targets.emplace_back(new Derived<T>);
     }
};

我宁愿用std::vector<std::unique_ptr<T>>(或者,也许是std::vector<std::shared_ptr<T>>)替换garbage_bin<T>

如果要限制接口,请将garbage_bin<T>重新实现为std::vector<std::unique_ptr<T>>的包装器。这样,您可能不需要 empty 方法,因为 std::vectorstd::unique_ptr 的析构函数会在自己之后进行清理。但是,如果要在销毁之前清空垃圾箱,则只需调用std::vector::clear即可实现empty

我知道这不是最简单的事情(因为 OP 说有"数千个"地方需要更改),但显然需要重构这个糟糕的设计。