Note that there are some explanatory texts on larger screens.

plurals
  1. POCan templates be completely avoided in C++?
    primarykey
    data
    text
    <p>My question, which is in the last paragraph, needs (in my opinion) some explanatory setup. Basically, I'm wondering if you can avoid using templates if instead you make all your would-be template classes instead inherit from a base class that declares virtual methods you will be using, among them a function for memory allocation that, when implemented, will return a pointer to the derived (not base) type.</p> <h2>BEGIN setup</h2> <p>C++ does not seem to have the notion of a "universal base class" from which everything is implicitly derived; I imagine that class would be defined like this:</p> <pre><code>class universal_base { }; </code></pre> <p>Of course, now that I have defined it, I can make all my classes derive from it. Then, because of polymorphism, any references or pointers to <code>universal_base</code> that I pass around will be basically the same as template parameters:</p> <pre><code>template &lt;typename T&gt; class C { T &amp;x; int f(T &amp;y); C(T &amp;z): x(z + 1) {} }; class C { universal_base &amp;x; int f(universal_base &amp;y); C(universal_base &amp;z): x(z + 1) {} }; </code></pre> <p>The difference is that in the first construction, the expression <code>z + 1</code> can't be guaranteed to be valid; you just have to tell users that <code>T</code> must overload <code>operator+</code>. In the second construction, I could add a virtual such operator to <code>universal_base</code>:</p> <pre><code>// in universal_base public: virtual universal_base&amp; operator+(const universal_base &amp;x) = 0; </code></pre> <p>and use <code>typeid</code> and <code>dynamic_cast</code> in the implementations to get the argument right. This way, it is impossible to write ill-formed code, because the compiler will complain if you don't implement <code>operator+</code>.</p> <p>Of course, this way it is not possible to declare members of non-reference type:</p> <pre><code>class C: public universal_base { universal_base x; // Error: universal_base is a virtual type }; </code></pre> <p>However, this can be gotten around through careful use of initialization. In fact, if I wanted to create a template for the above,</p> <pre><code>template &lt;typename T&gt; class C: public universal_base { T x; }; </code></pre> <p>I would almost certainly be giving it objects of type <code>T</code> at some point. In that case, there is no reason that I could not do the following:</p> <pre><code>class universal_base { public: virtual universal_base&amp; clone() = 0; }; class C: public universal_base { universal_base &amp;x; C(universal_base &amp;y) : x(y.clone()) {} } </code></pre> <p>Effectively, I create a variable of a type that is determined at runtime. This of course requires that every object of type <code>C</code> be appropriately initialized, but I do not think this is a huge sacrifice.</p> <p>This is not academic, since it has the following use: if I am writing a module that is intended to be linked into other programs and handle their data in some generic way, I cannot possibly know the types that will be used. Templates are not helpful in this situation, but the technique above works fine.</p> <h2>END setup</h2> <p>So, my question: does this completely replace templates, modulo the thing about initialization? Is it inefficient or dangerous somehow?</p>
    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.
 

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