C++ Registry pattern implementation
Good stuff!

I definitely see a few improvements you could make here:

Prefer using std::function to function pointers

There is a tiny bit more overhead invovled, but the extra flexibility is well worth it.

using FactoryFunc = std::function&lt;std::unique_ptr&lt;Base&gt;(Args...)&gt;;


Another advantage is that it lets you get rid of constructDerived entirely, and replace it with a nice lambda in registerClass.

Nitpick: registerClass should invoke registerFactory.

Since registerClass is just a specialization of registerFactory, it should invoke it instead of reimplementing it. This is preferable because having a single point of entry makes refactorings like adding logging or debug monitoring a lot less error-prone.

Prefer using instead of typedef

The semantics of type alisases are just a lot more legible that way.

Wrong function definition for forwarding args

If you want to use forwarding as you do, construct needs to be declared in a way to use universal references, like so:

template&lt;typename... CtrArgs&gt;
std::unique_ptr&lt;Base&gt; construct(const Key &amp;key, CtrArgs&amp;&amp;... args)


Otherwise, your std::forward&lt;&gt; call is useless and might as well be a std::move.

Personal opinion: The custom exception type is not necessary here.

Letting the out_of_range exception bubble up is perfectly acceptable here, and lets your code be cleaner.