Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>If you can live with having to use a different syntax for specifying complete types, you might do the following (warning: untested code):</p> <p>Let's first start with the machinery:</p> <pre><code>// this gives the complete type which needs to be used to create objects // and provides the implementation of clone() template&lt;typename T&gt; class Cloneable: public T { public: template&lt;typename... U&gt; Cloneable(U&amp;&amp;... u): T(std::forward&lt;U&gt;(u) ...) {} T* clone() { return new Cloneable(*this); } private: // this makes the class complete // Note: T:: to make it type dependent, so it can be found despite not yet defined typename T::CloneableBase::CloneableKey unlock() {} }; // this provides the clone function prototype and also makes sure that only // Cloneable&lt;T&gt; can be instantiated class CloneableBase { template&lt;typename T&gt; friend class Cloneable; // this type is only accessible to Clonerable instances struct CloneableKey {}; // this has to be implemented to complete the class; only Cloneable instances can do that virtual CloneableKey unlock() = 0; public: virtual CloneableBase* clone() = 0; virtual ~CloneableBase() {} }; </code></pre> <p>OK, now the actual class hierarchy. That one is pretty standard; no CRTP intermediates or other complications. However no class implements the <code>clone</code> function, but all inherit the declaration (directly or indirectly) from <code>CloneableBase</code>.</p> <pre><code>// Base inherits clone() from CloneableBase class Base: public CloneableBase { // ... }; // Derived can inherit normally from Base, nothing special here class Derived: public Base { // ... }; </code></pre> <p>Here's how you then create objects:</p> <pre><code>// However, to create new instances, we actually need to use Cloneable&lt;Derived&gt; Cloneable&lt;Derived&gt; someObject; Derived* ptr = new Cloneable&lt;Derived&gt;(whatever); // Now we clone the objects Derived* clone1 = someObject.clone(); Derived* clone2 = ptr-&gt;clone(); // we can get rid og the objects the usual way: delete ptr; delete clone1; delete clone2; </code></pre> <p>Note that a <code>Cloneable&lt;Derived&gt;</code> is-a <code>Derived</code> (it is a subclass), therefore you need to use <code>Cloneable</code> only for construction, and can otherwise pretend to work with <code>Derived</code> objects (well, <code>tyepinfo</code> will also identify it as <code>Cloneable&lt;Derived&gt;</code>).</p>
    singulars
    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.
    1. This table or related slice is empty.
    1. VO
      singulars
      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