Note that there are some explanatory texts on larger screens.

plurals
  1. POAny way to resolve forward declaration in a template class?
    primarykey
    data
    text
    <p>I have a template class defined as such:</p> <pre><code>template &lt;typename T&gt; void ProxyNoOp(T *) {} template &lt;typename T&gt; void ProxyDelete(T * ptrT) {delete ptrT;} template &lt;typename T, typename C, void (* Release)(T *) = ProxyNoOp&lt;T&gt; &gt; class Proxy { public: class Container : public std::list&lt;T *&gt; { public: Container() {} ~Container() {clear();} void clear() { iterator clsEnd = end(); for (iterator clsCurrent = begin(); clsCurrent != clsEnd; ++clsCurrent) { T * ptrT = *clsCurrent; static_cast&lt;Proxy *&gt;(ptrT)-&gt;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&lt;Container *&gt;(m_ptrContainer); static_cast&lt;std::list&lt;T *&gt; &gt;(ptrContainer)-&gt;erase(m_clsPosition); } } C * GetContainer() const {return m_ptrContainer;} }; </code></pre> <p>A lot of the code has been removed or changed for the sake of brevity. The idea of the data structure is that not only does a container maintain references to contained elements, but the contained elements maintain a reference to the container PLUS their position in the container, making removal quick (constant time) and automatic (called in the destructor)</p> <p>A problem with this approach can be demonstrated by this code:</p> <pre><code>#include "proxy.h" // the above template class class Child; class Parent : public Proxy&lt;Child, Parent&gt;::Container {}; class Child : public Proxy&lt;Child, Parent&gt; {}; </code></pre> <p>When compiling <code>Parent</code>, the definition of <code>Proxy&lt;Child, Parent&gt;::Container</code> causes an error at this line: <code>static_cast&lt;Proxy *&gt;(ptrT)-&gt;m_ptrContainer = NULL;</code> - at the point in the compilation, <code>Child</code> has not been defined, only declared. If I change the declaration order of <code>Parent</code> and <code>Child</code> to be this:</p> <pre><code>#include "proxy.h" class Parent; class Child : public Proxy&lt;Child, Parent&gt; {}; class Parent : public Proxy&lt;Child, Parent&gt;::Container {}; </code></pre> <p>the definition of <code>Proxy&lt;Child, Parent&gt;</code> causes an error at this line: <code>Container * ptrContainer = static_cast&lt;Container *&gt;(m_ptrContainer);</code>, the reason being the same as before - at that point in the compilation, <code>Parent</code> is not fully defined.</p> <p>Is there any way I can get around this and still use templates? Is there a standard data structure in STL, BOOST, etc. that accomplishes this?</p> <p><strong>EDIT:</strong></p> <p>The code will not compile as-is, I should have been clearer about that (to quote myself from above: <em>A lot of the code has been removed or changed for the sake of brevity.</em>). It doesn't actually use <code>std::list&lt;T *&gt;</code>, but a custom doubly linked that is effectively the same. I didn't want to post a ton of ancillary code when only asking about this one issue.</p> <p>I wasn't asking for critique on the data structure itself (although I am fine to hear it), but for those wondering why it was created here are a couple examples:</p> <p>A game engine has models and instances of those models, such as a war game where there is one tank model and any number of tanks created from it. The classes could be written as such:</p> <pre><code>class Instance; class Model : public Proxy&lt;Model, Instance, ProxyDelete&lt;Instance&gt; &gt;::Container {...}; class Instance : public Proxy&lt;Model, Instance, ProxyDelete&lt;Instance&gt; &gt; {...}; </code></pre> <p>When a model is deleted, all instances made from that model should also be deleted (hence the <code>ProxyDelete&lt;Instance&gt;</code> template parameter) since it doesn't make sense for an instance to exist without the model it was made from.</p> <p>Suppose your graphical user interface (GUI) renderer keeps track of all visible elements (buttons, frames, etc.) so it knows what to render, but text is rendered differently since it is a different call to the graphics API:</p> <pre><code>class GuiTextElement; class GuiRenderer : public Proxy&lt;GuiRenderer, GuiTextElement, ProxyNoOp&lt;GuiTextElement&gt; &gt;::Container {...}; class GuiTextElement : public Proxy&lt;GuiRenderer, GuiTextElement, ProxyNoOp&lt;GuiTextElement&gt; &gt; {...}; </code></pre> <hr> <p>The less astute will say "why don't you simply add <code>std::list&lt;Instance *&gt;</code> as a member of the <code>Model</code> and <code>std::list&lt;GuiTextElement *&gt;</code> as a member of <code>GuiRenderer</code>?". Here are a few reasons:</p> <ol> <li>Elements that are "owned" by their containers are not automatically deleted when the container is destroyed (yes, I am aware of <code>boost::ptr_list</code>).</li> <li>There is no way, without adding another class member, to refer to the container using a contained element. For example, to get a <code>Model</code> from an <code>Instance</code>.</li> <li>If you did add a class member to accomplish #2, you would also need to update it when elements are removed from their containers.</li> <li>For the speed fanatics - if contained elements don't maintain an iterator to their position in the container, before that element can be removed the container must first be searched for it.</li> </ol>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload