A
adeht
In his book, "Modern C++ Design", Andrei Alexandrescu presents a Generic
Object Factory class (Loki::Factory). One of its advantages (also mentioned
in
the book) is being able to register the class in the factory without having
a
central place that needs to be modified each time we add a new type. For
example, the registration can be done in the same compilation unit as the
class implementation:
(code like this has been presented in the book)
// DerivedType.cpp
// DerivedType is the type we want to register, and it is derived from
BaseType
namespace {
BaseType *CreateDerivedTypeObject() { return new DerivedType; }
const bool registered = MyFactory::Instance().Register("DerivedType",
CreateDerivedTypeObject);
}
MyFactory is:
typedef Loki::SingletonHolder<Loki::Factory<BaseType, std::string> >
MyFactory;
Now, in the client code I only use the base class interface, like:
BaseType *object = MyFactory::Instance().CreateObject("DerivedType");
This works, for example, if I'd compile the library (which contains the base
class, derived classes
and factory) to be a dynamically loaded one, since all translation units in
the library will be included.
But if I compile to a static library, the linker won't see any of the
derived classes being used (implicitly)
and will drop them from the final module.
Currently, I have implemented a hack solution - to register all derived
classes in a centralized
place (for example a static method BaseType::RegisterAllDerived()).. but as
you can see, it's not
very pretty.
I found no way to tell the linker to link with all objects in the library,
except by specifying
the objects outside the library - therefore not using a library (I am using
VC++7.1).
I understand that this isn't a serious issue, since in a library there can
be a only a finite amount
of types to register... But it seems too hacky.
Any insight about this?
PS. This linker optimization has other consequences, for example dropping
win32 resource objects
in a static library.
Object Factory class (Loki::Factory). One of its advantages (also mentioned
in
the book) is being able to register the class in the factory without having
a
central place that needs to be modified each time we add a new type. For
example, the registration can be done in the same compilation unit as the
class implementation:
(code like this has been presented in the book)
// DerivedType.cpp
// DerivedType is the type we want to register, and it is derived from
BaseType
namespace {
BaseType *CreateDerivedTypeObject() { return new DerivedType; }
const bool registered = MyFactory::Instance().Register("DerivedType",
CreateDerivedTypeObject);
}
MyFactory is:
typedef Loki::SingletonHolder<Loki::Factory<BaseType, std::string> >
MyFactory;
Now, in the client code I only use the base class interface, like:
BaseType *object = MyFactory::Instance().CreateObject("DerivedType");
This works, for example, if I'd compile the library (which contains the base
class, derived classes
and factory) to be a dynamically loaded one, since all translation units in
the library will be included.
But if I compile to a static library, the linker won't see any of the
derived classes being used (implicitly)
and will drop them from the final module.
Currently, I have implemented a hack solution - to register all derived
classes in a centralized
place (for example a static method BaseType::RegisterAllDerived()).. but as
you can see, it's not
very pretty.
I found no way to tell the linker to link with all objects in the library,
except by specifying
the objects outside the library - therefore not using a library (I am using
VC++7.1).
I understand that this isn't a serious issue, since in a library there can
be a only a finite amount
of types to register... But it seems too hacky.
Any insight about this?
PS. This linker optimization has other consequences, for example dropping
win32 resource objects
in a static library.