Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>There are two problems here, 1. How to decide what type each child will be, and 2. How to create multiple children.</p> <h2>To decide which child to create</h2> <p>This can be done at compile time or runtime. To do this at compile time you need templates.</p> <pre><code>template&lt;class Child, class Arg1, class Arg2&gt; vector&lt;unique_ptr&lt;Parent&gt;&gt; CreateVec(Arg1&amp;&amp; arg1, Arg2&amp;&amp; arg2) { vector&lt;unique_ptr&lt;Parent&gt;&gt; result; result.push_back(unique_ptr&lt;Child&gt;( new Child(std::forward&lt;Arg1&gt;(arg1), std::forward&lt;Arg2&gt;(arg2)))); return result; } </code></pre> <p>called as follows <code>CreateVec&lt;MyChild&gt;(myArg1, myArg2)</code>.</p> <p>If you need to decide at runtime, you can use a map of factory functions indexed by a run-time variable. Or you could use a pointer to a factory object as your run-time variable.</p> <h2>To create multiple children</h2> <p>Here you have a choice between chained functions and variadic templates.</p> <h3>Chained functions</h3> <p>This is essentially what iostreams does. Have your function which creates a vector and adds a single child return an object which allows you to add a second child, and returns itself allowing you to continue.</p> <p>The problem here is that you want the function to return the vector, so it can't also return another object. You could use a conversion operator to get the vector, or an explicit function, but probably easiest is to create the vector first, and just use the functions to add the children.</p> <pre><code>class AddChildren { vector&lt;unique_ptr&lt;Parent&gt;&gt;&amp; m_vector; public: explicit AddChildren(vector&lt;unique_ptr&lt;Parent&gt;&gt;&amp; theVector) : m_vector(theVector) {} template&lt;class Child, class Arg1, class Arg2&gt; AddChildren&amp; add(Arg1&amp;&amp; arg1, Arg2&amp;&amp; arg2) { m_vector.push_back(unique_ptr&lt;Child&gt;( new Child(std::forward&lt;Arg1&gt;(arg1), std::forward&lt;Arg2&gt;(arg2)))); return *this; } }; </code></pre> <p>used as follows:</p> <pre><code>vector&lt;unique_ptr&lt;Parent&gt;&gt; myvector; AddChildren(myvector) .add&lt;ChildA&gt;(var1, var2) .add&lt;ChildB&gt;(var3, var4) .add&lt;ChildC&gt;(var5, var6); </code></pre> <p>If you are using a run-time method of choosing the type you can use <code>operator()</code> and have it look like this:</p> <pre><code>vector&lt;unique_ptr&lt;Parent&gt;&gt; myvector; AddChildren(myvector) (childAType, var1, var2)(childBType, var3, var4)(childCType, var5, var6); </code></pre> <p>(This can also be done with compile-time selection of type by using a dummy object of a specific type-selector type for each child type as a parameter.)</p> <h3>Using variadic templates</h3> <p>Use a variadic template to peel off three parameters at a time, and add a child object.</p> <pre><code>void addChildren(vector&lt;unique_ptr&lt;Parent&gt;&gt;&amp; theVector) {} template&lt;class FirstChild, class FirstArg1, class FirstArg2, class... Rest&gt; void addChildren(vector&lt;unique_ptr&lt;Parent&gt;&gt;&amp; theVector, FirstChild childtype, FirstArg1&amp;&amp; arg1, FirstArg2&amp;&amp; arg2, Rest&amp;&amp;... rest) { addChild(theVector, childtype, std::forward&lt;Arg1&gt;(arg1), std::forward&lt;Arg2&gt;(arg2)); addChildren(theVector, std::forward&lt;Rest&gt;(rest)...); } template&lt;class... Args&gt; vector&lt;unique_ptr&lt;Parent&gt;&gt; CreateVec(Args&amp;&amp;... args) { vector&lt;unique_ptr&lt;Parent&gt;&gt; result; addChildren(result, std::forward&lt;Args&gt;(args)...); return result; } </code></pre> <p>I assume here the existence of a function <code>addChild</code> which can add a child given its type (as a parameter) and its arguments.</p> <p>The main problem with this is that VS2012 doesn't have variadic templates. There are two ways to simulate variadic templates. 1. Write a single function which takes the maximum number of parameters you might need, and defaults most of them to some known type which you can take to mean "not present". 2. Write out as many overloads as you think you will need.</p> <p>If you know you will never need more than say ten child objects, the second option is actually perfectly feasible -- you only need to write them once and it's probably less than 150 lines of code. Alternatively you can use Boost.Preprocessor to generate the functions, but that's a whole new level of complexity.</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. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      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