Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>My comments were probably not very clear. So here is a C++11 "solution" relying on template meta programming : (Possibly not the nicest way of doing this though)</p> <pre><code>#include &lt;iostream&gt; #include &lt;utility&gt; // Type list stuff: (perhaps use an existing library here) class EmptyType {}; template&lt;class T1, class T2 = EmptyType&gt; struct TypeList { typedef T1 Head; typedef T2 Tail; }; template&lt;class... Etc&gt; struct MakeTypeList; template &lt;class Head&gt; struct MakeTypeList&lt;Head&gt; { typedef TypeList&lt;Head&gt; Type; }; template &lt;class Head, class... Etc&gt; struct MakeTypeList&lt;Head, Etc...&gt; { typedef TypeList&lt;Head, typename MakeTypeList&lt;Etc...&gt;::Type &gt; Type; }; // Calling produce template&lt;class TList, class BaseType&gt; struct Producer; template&lt;class BaseType&gt; struct Producer&lt;EmptyType, BaseType&gt; { template&lt;class... Args&gt; static BaseType* Produce(Args... args) { return nullptr; } }; template&lt;class Head, class Tail, class BaseType&gt; struct Producer&lt;TypeList&lt;Head, Tail&gt;, BaseType&gt; { template&lt;class... Args&gt; static BaseType* Produce(Args... args) { BaseType* b = Head::Produce(args...); if(b != nullptr) return b; return Producer&lt;Tail, BaseType&gt;::Produce(args...); } }; // Generic AbstractFactory: template&lt;class BaseType, class Types&gt; struct AbstractFactory { typedef Producer&lt;Types, BaseType&gt; ProducerType; template&lt;class... Args&gt; static BaseType* Produce(Args... args) { return ProducerType::Produce(args...); } }; class Base {}; // Example base class you had struct Derived0 : public Base { // Example derived class you had Derived0() = default; static Base* Produce(int value) { if(value == 0) return new Derived0(); return nullptr; } }; struct Derived1 : public Base { // Another example class Derived1() = default; static Base* Produce(int value) { if(value == 1) return new Derived1(); return nullptr; } }; int main() { // This will be our abstract factory type: typedef AbstractFactory&lt;Base, MakeTypeList&lt;Derived0, Derived1&gt;::Type&gt; Factory; Base* b1 = Factory::Produce(1); Base* b0 = Factory::Produce(0); Base* b2 = Factory::Produce(2); // As expected b2 is nullptr std::cout &lt;&lt; b0 &lt;&lt; ", " &lt;&lt; b1 &lt;&lt; ", " &lt;&lt; b2 &lt;&lt; std::endl; } </code></pre> <p>Advantages:</p> <ol> <li>No (additional) run-time overhead as you would have with the function pointers. Works for any base type, and for any number of derived types. You still end up calling the functions of course.</li> <li>Thanks to variadic templates this works with any number of arguments (giving an incorrect number of arguments will produce a compile-time error message).</li> <li>Explicit registering of the produce member functions is not required.</li> </ol> <p>Disadvantages:</p> <ol> <li>All of your derived types must be available when you declare the Factory type. (You must know what the possible derived types are and they must be complete.)</li> <li>The produce member functions for the derived types must be public.</li> <li>Can make compilation slower. (As always the case when relying on template metaprogramming)</li> </ol> <p>In the end, using the prototype design pattern might turn out better. I don't know since I haven't tried using my code.</p> <p>I'd like to state some additional things (after further discussion on the chat):</p> <ul> <li>Each factory can only return a single object. This seems strange, as the users decide whether they will take the input to create their object or not. I would for that reason suggest your factory can return a collection of objects instead.</li> <li>Be careful not to overcomplicate things. You want a plugin system, but I don't think you really want factories. I would propose you simply make users register their classes (in their shared object), and that you simply pass the arguments to the classes' <code>Produce</code> (static) member functions. You store the objects if and only if they're not the nullptr. </li> </ul>
 

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