c – 在模板类中解析前向声明的任何方法?
我有一个模板类定义如下:
template <typename T> void ProxyNoOp(T *) {} template <typename T> void ProxyDelete(T * ptrT) {delete ptrT;} template <typename T,typename C,void (* Release)(T *) = ProxyNoOp<T> > class Proxy { public: class Container : public std::list<T *> { public: Container() {} ~Container() {clear();} void clear() { iterator clsEnd = end(); for (iterator clsCurrent = begin(); clsCurrent != clsEnd; ++clsCurrent) { T * ptrT = *clsCurrent; static_cast<Proxy *>(ptrT)->m_ptrContainer = NULL; Release(ptrT); } } }; private: iterator m_clsPosition; C * m_ptrContainer; public: Proxy() : m_ptrContainer(NULL) {} ~Proxy() { if ( m_ptrContainer != NULL ) { Container * ptrContainer = static_cast<Container *>(m_ptrContainer); static_cast<std::list<T *> >(ptrContainer)->erase(m_clsPosition); } } C * GetContainer() const {return m_ptrContainer;} }; 为简洁起见,已删除或更改了许多代码.数据结构的概念是,容器不仅维护对包含元素的引用,而且包含的元素保持对容器的引用PLUS它们在容器中的位置,使得快速删除(恒定时间)和自动(在析构函数中调用) ) 此代码可以证明此方法存在问题: #include "proxy.h" // the above template class class Child; class Parent : public Proxy<Child,Parent>::Container {}; class Child : public Proxy<Child,Parent> {}; 在编译Parent时,Proxy< Child,Parent> :: Container的定义会在此行导致错误:static_cast< Proxy *>(ptrT) – > m_ptrContainer = NULL; – 在汇编中,Child尚未定义,仅被声明.如果我将Parent和Child的声明顺序更改为: #include "proxy.h" class Parent; class Child : public Proxy<Child,Parent> {}; class Parent : public Proxy<Child,Parent>::Container {}; Proxy< Child,Parent>的定义导致此行出错:Container * ptrContainer = static_cast< Container *>(m_ptrContainer);,原因与之前相同 – 在编译中的那一点,未完全定义Parent. 有什么方法可以解决这个问题,仍然使用模板吗? STL,BOOST等中是否有标准数据结构来实现这一目标? 编辑: 代码将不会按原样编译,我应该更清楚(从上面引用自己:为了简洁起见,已经删除或更改了许多代码.).它实际上并不使用std :: list< T *>,而是一个实际上相同的自定义双向链接.当我只询问这个问题时,我不想发布大量的辅助代码. 我并没有要求对数据结构本身进行批评(尽管我听得很清楚),但对于那些想知道为什么在这里创建的人来说,有几个例子: 游戏引擎具有这些模型的模型和实例,例如战争游戏,其中有一个坦克模型和由其创建的任意数量的坦克.这些类可以这样编写: class Instance; class Model : public Proxy<Model,Instance,ProxyDelete<Instance> >::Container {...}; class Instance : public Proxy<Model,ProxyDelete<Instance> > {...}; 删除模型时,也应删除从该模型创建的所有实例(因此,ProxyDelete< Instance>模板参数),因为没有模型的实例存在实例是没有意义的. 假设您的图形用户界面(GUI)渲染器跟踪所有可见元素(按钮,框架等),因此它知道要渲染的内容,但文本的呈现方式不同,因为它是对图形API的不同调用: class GuiTextElement; class GuiRenderer : public Proxy<GuiRenderer,GuiTextElement,ProxyNoOp<GuiTextElement> >::Container {...}; class GuiTextElement : public Proxy<GuiRenderer,ProxyNoOp<GuiTextElement> > {...}; 精明度较低的人会说“为什么不简单地将std :: list< Instance *>作为模型的成员添加到std :: list< GuiTextElement *>作为GuiRenderer的成员?”.原因如下: >当容器被销毁时,它们的容器“拥有”的元素不会被自动删除(是的,我知道boost :: ptr_list). 解决方法
我不认为你向我们展示的代码表明了你所问的问题.
我做了一些最小的修改以克服早期的编译器错误,所以我可以达到可以重现你的问题的程度.但是,这样做,你的问题就不存在了. 以下是我的更改: >添加#include< list>. 您可以尝试逐个添加它们以查看每个解决的错误 – 它们都与您的问题无关.或者你可以download the code并自己编译. 我用三个不同的编译器编译了这个,clang-4.2,g -4.6和g -4.2-apple;在适当的情况下,在C 11和C 98模式下;启用-Wall.在所有情况下,它编译时没有任何错误或警告. 另外,我没有看到引用的行如何产生您描述的错误. T或C是否不完整无关紧要,因为您所做的只是: > static_cast一个T *到一个代理*,只需要声明T,没有定义. 前一行依赖于在迭代器上调用operator *,而且显然是你的自定义类可能以某种方式依赖于T或C,但这不可能在下一行引起错误. 所以,有一些可能性: >错误不是您描述的错误,也不是您描述的错误,问题出在迭代器类或您没有向我们展示的列表类中.>您向我们展示的代码与您的真实代码有很大不同,它甚至不再有导致问题的部分痕迹.>我的琐碎变化并不像我想象的那样微不足道,并以某种方式解决了你的问题. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |