Joel Bodenmann
Joel Bodenmann

Reputation: 2282

Unforgettable Factory: Doesn't work with default constructible objects

I am referring to this excellent blog post regarding the "Unforgettable Factory Registration Pattern": http://www.nirfriedman.com/2018/04/29/unforgettable-factory/

I've noticed that this stops working when the self-registering types are default constructible. In the example provided by the code, the self-registering types (Animal base class) defines a constructor with an int parameter. If I slightly modify the code to make Animal become default constructible, the data map in the factory remains empty and objects of type Cat and Dog can no longer be constructed through the factory.

As far as I understand the issue lies in the fact that the Animal class no longer calls the registerT function. However, I fail to understand why that is and what modification(s) are necessary to make it work with default constructible classes.

Can somebody shed some light on this?

Useful:

Upvotes: 1

Views: 89

Answers (1)

The int argument is a red herring. When changing the argument list you modified

Dog(int x) : m_x(x) {}

to be

Dog() = default;

From a user-provided constructor, to a defaulted one.

In effect, this means the compiler (I checked Clang and GCC) doesn't emit a function definition for Dog::Dog(), so it doesn't odr-use Animal::Registrar<Dog>::Registrar<Dog>(), which means its definition isn't instantiated (member function bodies only are only instantiated when odr-used). And so we never odr-use its registered static data member.

If the constructor is defaulted, then we never actually end up registering the factory function into the map. And indeed, after it becomes user-provided again, things start to work.

I am however unable to understand why that makes a difference. The user-provided constructor is still an inline member function. And inline function definitions are tied to odr-usage too. But perhaps that should be the subject of another question.

Upvotes: 1

Related Questions