Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>UPDATE:</strong> I believe the trick has not been understood hence I created the complete solution now. It is just one little change to the code of the OP. Just replace T in the <code>BaseSolver</code> with an empty class definition deriving from <code>T</code>.</p> <p><strong>Original Text:</strong> I think you can do it by delegating the friendship to a wrapper class that is private to the base Solver. This class will inherit from any class for which instances are to be created. The compiler should optimize the wrapper class away.</p> <pre><code>#include &lt;iostream&gt; #include &lt;map&gt; struct AbstractSolver { virtual double solve() = 0; }; class SolverFactory { std::map&lt;char const * const, AbstractSolver * (*)()&gt; creators; std::map&lt;char const * const, AbstractSolver *&gt; solvers; public: static SolverFactory &amp; instance() { static SolverFactory x; return x; } void registerType(char const * const name, AbstractSolver *(*create)()) { creators[name] = create; } AbstractSolver * getSolver(char const * const name) { auto x = solvers.find(name); if (x == solvers.end()) { auto solver = creators[name](); solvers[name] = solver; return solver; } else { return x-&gt;second; } } }; template&lt;class T&gt; class BaseSolver : public AbstractSolver { struct Wrapper : public T { // This wrapper makes the difference static char const * const get_name() { return T::name; } }; protected: static bool reg; BaseSolver() { reg = reg; } virtual ~BaseSolver() {} static T * create() { return new Wrapper; // Instantiating wrapper instead of T } static bool init() { SolverFactory::instance().registerType(Wrapper::get_name(), (AbstractSolver * (*)())BaseSolver::create); return true; } }; template&lt;class T&gt; bool BaseSolver&lt;T&gt;::reg = BaseSolver&lt;T&gt;::init(); struct SolverD2Q5 : public BaseSolver&lt;SolverD2Q5&gt; { public: double solve() { return 1.1; } protected: SolverD2Q5() {} // replaced private with protected static char const * const name; }; char const * const SolverD2Q5::name = "SolverD2Q5"; struct SolverX : public BaseSolver&lt;SolverX&gt; { public: double solve() { return 2.2; } protected: SolverX() {} // replaced private with protected static char const * const name; }; char const * const SolverX::name = "SolverX"; int main() { std::cout &lt;&lt; SolverFactory::instance().getSolver("SolverD2Q5")-&gt;solve() &lt;&lt; std::endl; std::cout &lt;&lt; SolverFactory::instance().getSolver("SolverX")-&gt;solve() &lt;&lt; std::endl; std::cout &lt;&lt; SolverFactory::instance().getSolver("SolverD2Q5")-&gt;solve() &lt;&lt; std::endl; std::cout &lt;&lt; SolverFactory::instance().getSolver("SolverX")-&gt;solve() &lt;&lt; std::endl; char x; std::cin &gt;&gt; x; return 0; } </code></pre>
 

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