P
Patrick Guio
Dear all,
I try to compile the following code in two ways:
* using one compilation unit:
g++ main.cpp base.cpp -o main
* creating a library for the class factory.
g++ -c -o base.o base.cpp
ar rv libfactory.a base.o
g++ main.cpp -o main-lib -L. -lfactory
when using compilation unit, the base class is added in the base class
factory (the registerMe variable) and I can create an object at ruin-time.
When using the library the global object in the anonymous namespace
(registerMe) is not included, any idea why is that so?
Following are the necessary source codes.
Sincerely, Patrick
factory.h
--------------------------------------------------------------------------
template <class ManufacturedType>
class GenericFactory
{
public:
typedef ManufacturedType* BasePtr;
typedef std::string ClassIDKey;
private:
typedef BasePtr (*BaseCreateFn)(int, char **);
typedef std::map<ClassIDKey, BaseCreateFn> FnRegistry;
GenericFactory() {}
FnRegistry registry;
public:
static GenericFactory &instance()
{
static GenericFactory<ManufacturedType> bf;
return bf;
}
void RegCreateFn(const ClassIDKey & id, BaseCreateFn fn)
{
registry[id] = fn;
}
BasePtr create(const ClassIDKey &className,int nargs, char *args[])
const
{
BasePtr theObject(0);
typename FnRegistry::const_iterator
regEntry(registry.find(className));
if (regEntry != registry.end()) {
theObject = regEntry->second(nargs,args);
} else {
throw std::string("Error: unrecognised ClassIDKey: "+className);
}
return theObject;
}
};
template <class AncestorType, class ManufacturedType>
struct RegisterInFactory
{
typedef typename GenericFactory<AncestorType>::BasePtr BasePtr;
typedef typename GenericFactory<AncestorType>::ClassIDKey ClassIDKey;
static BasePtr CreateInstance(int nargs, char *args[])
{
return BasePtr(new ManufacturedType(nargs, args));
}
RegisterInFactory(const ClassIDKey &id)
{
GenericFactory<AncestorType>::instance().RegCreateFn(id,
CreateInstance);
}
};
--------------------------------------------------------------------------
base.h
--------------------------------------------------------------------------
struct Base
{
Base(int nargs=0, char *args[]=0);
virtual ~Base();
virtual void whoami();
};
--------------------------------------------------------------------------
base.cpp
--------------------------------------------------------------------------
#include "factory.h"
#include "base.h"
Base::Base(int nargs, char *args[])
{
std::cout << "Base class created with " << nargs << " arguments: ";
if (nargs > 0) {
std::cout << args[0];
for (int i=1; i<nargs; i++) std::cout << ", " << args;
}
std::cout << std::endl;
}
Base::~Base() {}
void Base::whoami()
{
std::cout << "I am a Base class" << std::endl;
}
namespace {
RegisterInFactory<Base, Base> registerMe("Base");
}
--------------------------------------------------------------------------
main.cpp
--------------------------------------------------------------------------
#include "factory.h"
#include "base.h"
typedef GenericFactory<Base> Factory;
typedef Factory::BasePtr BasePtr;
int main(int nargs, char *args[])
{
try {
BasePtr object(Factory::instance().create("Base", nargs, args));
object->whoami();
return 0;
} catch (std::string &msg) {
std::cerr << msg << std::endl;
return 0;
}
}
--------------------------------------------------------------------------
I try to compile the following code in two ways:
* using one compilation unit:
g++ main.cpp base.cpp -o main
* creating a library for the class factory.
g++ -c -o base.o base.cpp
ar rv libfactory.a base.o
g++ main.cpp -o main-lib -L. -lfactory
when using compilation unit, the base class is added in the base class
factory (the registerMe variable) and I can create an object at ruin-time.
When using the library the global object in the anonymous namespace
(registerMe) is not included, any idea why is that so?
Following are the necessary source codes.
Sincerely, Patrick
factory.h
--------------------------------------------------------------------------
template <class ManufacturedType>
class GenericFactory
{
public:
typedef ManufacturedType* BasePtr;
typedef std::string ClassIDKey;
private:
typedef BasePtr (*BaseCreateFn)(int, char **);
typedef std::map<ClassIDKey, BaseCreateFn> FnRegistry;
GenericFactory() {}
FnRegistry registry;
public:
static GenericFactory &instance()
{
static GenericFactory<ManufacturedType> bf;
return bf;
}
void RegCreateFn(const ClassIDKey & id, BaseCreateFn fn)
{
registry[id] = fn;
}
BasePtr create(const ClassIDKey &className,int nargs, char *args[])
const
{
BasePtr theObject(0);
typename FnRegistry::const_iterator
regEntry(registry.find(className));
if (regEntry != registry.end()) {
theObject = regEntry->second(nargs,args);
} else {
throw std::string("Error: unrecognised ClassIDKey: "+className);
}
return theObject;
}
};
template <class AncestorType, class ManufacturedType>
struct RegisterInFactory
{
typedef typename GenericFactory<AncestorType>::BasePtr BasePtr;
typedef typename GenericFactory<AncestorType>::ClassIDKey ClassIDKey;
static BasePtr CreateInstance(int nargs, char *args[])
{
return BasePtr(new ManufacturedType(nargs, args));
}
RegisterInFactory(const ClassIDKey &id)
{
GenericFactory<AncestorType>::instance().RegCreateFn(id,
CreateInstance);
}
};
--------------------------------------------------------------------------
base.h
--------------------------------------------------------------------------
struct Base
{
Base(int nargs=0, char *args[]=0);
virtual ~Base();
virtual void whoami();
};
--------------------------------------------------------------------------
base.cpp
--------------------------------------------------------------------------
#include "factory.h"
#include "base.h"
Base::Base(int nargs, char *args[])
{
std::cout << "Base class created with " << nargs << " arguments: ";
if (nargs > 0) {
std::cout << args[0];
for (int i=1; i<nargs; i++) std::cout << ", " << args;
}
std::cout << std::endl;
}
Base::~Base() {}
void Base::whoami()
{
std::cout << "I am a Base class" << std::endl;
}
namespace {
RegisterInFactory<Base, Base> registerMe("Base");
}
--------------------------------------------------------------------------
main.cpp
--------------------------------------------------------------------------
#include "factory.h"
#include "base.h"
typedef GenericFactory<Base> Factory;
typedef Factory::BasePtr BasePtr;
int main(int nargs, char *args[])
{
try {
BasePtr object(Factory::instance().create("Base", nargs, args));
object->whoami();
return 0;
} catch (std::string &msg) {
std::cerr << msg << std::endl;
return 0;
}
}
--------------------------------------------------------------------------