C++ singleton template class crashes my program - c++

I created a singleton pattern as a template class.
template <typename T>
class TemplateSingleton
{
protected:
TemplateSingleton() { }
virtual ~TemplateSingleton() { }
public:
static T * GetInstance()
{
if (m_pInstance == NULL)
m_pInstance = new T;
return m_pInstance;
};
static void FreeInstance()
{
if (m_pInstance != NULL)
{
delete m_pInstance;
m_pInstance = NULL;
}
};
private:
static T * m_pInstance;
};
template <typename T> T * TemplateSingleton<T>::m_pInstance = NULL;
And use inherited from child class.
This class can be used as a singleton by inheriting a template, or as a generic class if not inherited.
#define MAX_COUNT 8
class CDataHandler : public TemplateSingleton<CDataHandler>
{
public:
CDataHandler();
~CDataHandler();
...
private:
CDataObj m_clDataObj[MAX_COUNT]; // CDataObj *m_clDataObj ?
DWORD m_dwDataObjCount;
...
};
class CDataObj
{
public:
CDataObj();
~CDataObj();
...
private:
...
};
The code above is in a DLL, and the program is implemented to call only the instance constructor of CDataHandler.
And my program crashes and quits.
By the way, if I change CDataObj member variable from array to pointer, it works fine.
(In this case, new in the constructor of the CDataHandler, and delete in the destructor.)
Is there something wrong with this code?
Addition)
constructor and destructor code for CDataHandler :)
CDataHandler::CDataHandler()
: m_dwDataObjCount(0)
//, m_clDataObj(NULL)
{
// Do nothing
// m_clDataObj = new CDataObj[MAX_COUNT];
}
CDataHandler::~CDataHandler()
{
//if (m_clDataObj != NULL)
{
for (int i = 0; i < MAX_COUNT; i++)
{
m_clDataObj[i].Close();
}
// delete[] m_clDataObj;
// m_clDataObj = NULL;
}
}

Not sure what is causing your program to crash, but there are two potential problems in the code you posted.
First, you don't know when m_pInstance will be initialised to NULL. If you call GetInstance() during static data initialisation, m_pInstance might not yet be initialised to NULL and thus GetInstance() will return some invalid pointer. Look up "static data initialisation order fiasko" or something like this, there is a lot of information on this.
To avoid this, you can use local static variables, along the lines of:
T* GetInstance()
{
static T* t = new T{};
return t;
}
Second, you use a template for your singleton. That's okay, but you have to take care: If the definition of the class is available to more than one compilation unit, each of these compilation units will instantiate their own singleton, leaving you with multiple different instances depending on from which compilation unit you are accessing them.
To solve this, you can use extern template for a certain T in the DLL to tell others they should not instantiate this template specialisation and then compile an explicit template instantiation into the DLL to provide the implementation for everyone.

Related

Is there a way to get class object in static function other than passing it as parameter?

Is there a way to get the class object in a class static function other than passing it as function argument? I cannot pass it as argument or make my class singleton.
class test{
public:
int i=10;
test(){}
Static test_static_method(){
// somehow get an object of the class to call class member.
std::cout << classObj->i << "\n";
}
};
I am trying to pass the static function to a C-API that takes in void(*)(). But I need class instance in my function to access the class data. Any help is appreciated.
If you're not going to have too many instances of your class, you can use preallocated "callback pool" -- pre-created functions that you allocate as needed for the callbacks:
#define REP10(P, M) M(P##0) M(P##1) M(P##2) M(P##3) M(P##4) M(P##5) M(P##6) M(P##7) M(P##8) M(P##9)
#define REP100(M) REP10(,M) REP10(1,M) REP10(2,M) REP10(3,M) REP10(4,M) REP10(5,M) REP10(6,M) REP10(7,M) REP10(8,M) REP10(9,M)
typedef void (*callback_fn_t)(void); // or whatever signature you need
class myclass {
static struct callback_t {
callback_t *next;
callback_fn_t callback;
myclass *obj;
} callback_table[100];
callback_t *my_callback;
static callback_t *freelist;
#define CB_FUNC_DECL(M) static void cbfunc##M() { callback_table[M].obj->callback(); }
REP100(CB_FUNC_DECL)
public:
callback_fn_t get_callback() {
if (!my_callback) {
if (!freelist) return nullptr;
my_callback = freelist;
freelist = my_callback->next;
my_callback->obj = this; }
return my_callback->callback;
}
void callback() {
/* this non-static method is called by the callback */
}
myclass() : my_callback(nullptr) { }
myclass(const myclass &a) : my_callback(nullptr) {
// need to manually define copy
}
~myclass() {
if (my_callback) {
my_callback->obj = nullptr;
my_callback->next = freelist;
freelist = my_callback; }
}
};
#define CB_TABLE_INIT(M) { M ? myclass::callback_table+M-1 : 0, myclass::cbfunc##M },
myclass::callback_t myclass::callback_table[100] = { REP100(CB_TABLE_INIT) };
myclass::callback_t *myclass::freelist = &myclass::callback_table[99];
Now if you want to use one of these objects as a callback, you call get_callback to get the function pointer you give to the C library, and it will call the callback method in your class on that object.
** I offer here an addition of a singleton solution although you said you can't, for future readers of this topic, who might see it helpful. Pay attention to the other solution.
The answer to your question is "No" for a reason. Objects are unique, and any object of the same class can (and usually will) contains a different data. When you are talking about static function/members of a class, different objects of the same class, will always contain the exact same data in those static functions/members.
However, if from some reason (probably an architecture bug), you don't care which object you will access using your static function, you can either make your class a singleton (which means that you'll always have only one instance of your class, and you'll always know which object data you'll use), or define an object instance static pointer in your class. Something like that:
class test {
public:
int i = 10;
test *class_obj;
test() {
class_obj = this; // The last object that created
}
Static test_static_method() {
// somehow get an object of the class to call class member.
std::cout << class_obj->i << "\n";
}
};
Read about:
Singleton
C++ Singleton
Static members in C++

How to declare a global QWidget?

I want to have a class, which extends QWidget, that I can access in my whole program. I've already tried to declare it in the main.cpp (but this is obsiously not declared in the other files) or to to it after the class declaration (in this case, if I include the file more than once, I get the error multiple declaration).
Is it possible to the Widget as global, and if yes, how ?
Edit :
What I want to do is to write informations on an second window, which is an instance of the class Console (I have written that class).
Then, I have the class MainWindow, with the classes it contains; calculation_widget, and variable_widget, which contain respectively a list of calculations and variables.
I want to be able to write on the Console window from all those classes.
I don't recommend using this, but it would be better than a global pointer. In case you need your window(-s) only once in your application you could use the Singleton (Anti-)pattern.
This is the SingletonTemplate class.
#ifndef __CSingletonTemplate_H__
#define __CSingletonTemplate_H__
template <class T> class CSingletonTemplate
{
public:
static T* GetInstance()
{
if (m_Instance == 0)
{
m_Instance = new T();
}
return m_Instance;
}
static T& GetRefInstance()
{
if (m_Instance == 0)
{
m_Instance = new T();
}
return *m_Instance;
}
static void Release()
{
if (m_Instance != 0)
{
delete m_Instance;
m_Instance = 0;
}
}
protected:
CSingletonTemplate() { ; }; // Hidden constructor
CSingletonTemplate(CSingletonTemplate const&) { ; }; // Hidden copy constructor
CSingletonTemplate& operator=(CSingletonTemplate const&) { ; }; // Hidden assign operation
~CSingletonTemplate() { ; }; // Hidden destructor
private:
static T* m_Instance;
};
template <class T> T* CSingletonTemplate<T>::m_Instance = 0;
#endif // __CSingletonTemplate_H__
You use it by declaring a class like follows:
class MyWindow : public CSingletonTemplate<MyWindow>
{
friend class CSingletonTemplate<MyWindow>;
private:
MyWindow();
virtual ~MyWindow();
Q_DISABLE_COPY(MyWindow);
};
And you can use this class my calling MyWindow::GetInstance()->...
For more information about the Singleton Pattern visit: https://sourcemaking.com/design_patterns/singleton

C++ finding the instantiated templates

I have just discovered the following jewel in the code (the example is very simplified, but the logic is the same):
template <class T>
class garbage_bin
{
private:
garbage_bin<T>(void)
{
}
static garbage_bin<T>* pinstance;
public:
static garbage_bin<T>& instance()
{
if(pinstance == NULL)
{
pinstance = new garbage_bin<T>();
}
return *pinstance;
}
void empty()
{
for(size_t i=0; i<items.size(); i++)
{
free (items[i]);
}
}
void throwIn(T item)
{
items.push_back(item);
}
vector<T> items;
};
and then somewhere in the code (this is just ONE example ... there are thousands like this):
char* r = strdup(src);
garbage_bin<char*>::instance().throwIn(r);
and later somewhere in the code, right before the exit ...
garbage_bin<char*>::instance().empty();
garbage_bin<molecules*>::instance().empty();
garbage_bin<CDatabaseUsers*>::instance().empty();
and so on ...
so as we can see, this implements a garbage bin class, in which you can "throw in" all kind of objects, and at a later stage to avoid the memory leaks you "empty" the garbage bin. But here comes the big bottleneck: In order for this to work properly, you need to know all the classes for which this garbage bin was instantiated in order to empty them...
The most direct solution I was thinking of is to create a map of typeid calls for the instantiations, and assign the garbage_bin<T>::instance() to the name however an ancient compiler decided that he does not like this approach.
Obviously, I can make a search through the code to find all the templatizations, but I'm wondering ... is there a simpler way to do this?
Garbage bin bin!
class garbage_bin_base;
class garbage_bin_bin {
public:
void throwIn(garbage_bin_base* rubbish) { items.push_back(rubbish); }
void empty() { for (auto item: items) item->empty(); }
private:
vector<garbage_bin_base*> items;
};
class garbage_bin_base {
public:
virtual empty() = 0;
garbage_bin_base() { garbage_bin_bin::instance().throwIn(this); }
};
template <typename T>
class garbage_bin : public garbage_bin_base {
};
You could add a registry for things to be deleted:
Registry registry;
// ...
if (pinstance == NULL)
{
pinstance = new garbage_bin<T>();
registry.add<T>();
}
// ...
registry.clear_all();
For example:
class Registry
{
struct Base
{
virtual ~Base() {}
virtual void clear() = 0;
};
template <typename T> struct Derived : Base
{
virtual void clear() { garbage_bin<T*>::instance().empty(); }
};
std::vector<std::unique_ptr<Base>> targets;
public:
void clear_all() { for (auto & p : targets) { p->clear(); } }
template <typename T> void add()
{
targets.emplace_back(new Derived<T>);
}
};
I would rather replace garbage_bin<T> with std::vector<std::unique_ptr<T>> (or, maybe, std::vector<std::shared_ptr<T>>).
If you want to restrict the interface, then reimplement garbage_bin<T> as a wrapper around std::vector<std::unique_ptr<T>>. In this way, you probably don't need the empty method since the destructors of std::vector and std::unique_ptr will clean-up after themselves. However, if you want to empty the bin before destruction, then implement empty just calling std::vector::clear.
I understand that this is not exactly the simplest thing to do (because the OP says there are "thousands" of places to be changed) but a refactoring of this bad design is clearly needed.

Is this a correct Implemenation of the Singleton Pattern? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
The following code is my implementation of the Singleton Pattern.
#include <iostream>
template<class T>
class Uncopyable
{
protected:
Uncopyable(){}
~Uncopyable(){}
private:
Uncopyable(const Uncopyable<T>&);
Uncopyable& operator=(const Uncopyable<T>&);
};
template <class T>
class Singleton : private Uncopyable<T>
{
public:
static T* getInstancePtr()
{
return instance;
}
protected:
Singleton<T>()
{
if(instance == 0)
{
instance = new T();
}
};
~Singleton<T>()
{
};
private:
static T* instance;
};
template<class T> T* Singleton<T>::instance = 0;
class Test : public Singleton<Test>
{
public:
Test(){};
~Test(){};
inline void test() const
{
std::cout << "Blah" << std::endl;
}
private:
friend class Singleton<Test>;
protected:
};
int main(int argc, char* argv[])
{
Test* t = Test::getInstancePtr();
Test* t2 = Test::getInstancePtr();
t->test();
t2->test();
return 0;
}
It works in this form, however I am uncertain as to whether it really is correct due to the constructor and destructor of the Singleton being protected as opposed to being private. If I declare them as private the code will not compile as they are not accessible to the class. Is this implementation safe to use, or is there anything I can do to improve it to ensure only one instance will be created and used.
Thanks
That is most certainly an incorrect implementation of singleton. There are too many issues with that implementation.
In C++11, you can make use of std::call_once and std::once_flag to implement singleton pattern. Here is one example:
//CRTP base singleton class
template<typename TDerived>
class Singleton
{
static std::unique_ptr<TDerived> m_instance;
static std::once_flag m_once;
protected:
Singleton() {}
public:
~Singleton() { }
static TDerived & GetInstance()
{
std::call_once
(
Singleton::m_once,
[] (){ Singleton::m_instance.reset( new TDerived() ); }
);
return *m_instance;
}
};
template<typename TDerived>
std::unique_ptr<TDerived> Singleton<TDerived>::m_instance;
template<typename TDerived>
std::once_flag Singleton<TDerived>::m_once;
Now you can derive from it as:
class Demo : public Singleton<Demo>
{
public:
void HelloWorld() { std::cout << "HelloWorld" << std::endl; }
};
//call HelloWorld() function through singleton instance!
DemoSingleton::GetInstance().HelloWorld();
There are several things wrong with the code you've posted.
The Uncopyable class doesn't need to be templated
The Singleton class isn't thread safe
Your Singleton instance is never deleted
I would re-implement your accessor as:
static T& GetInstance()
{
static T instance;
return instance;
}
Then make sure you call Singleton<T>::GetInstance() in the main thread of your application (during initialisation) to avoid any threading issues.
your destructor private will cause the compile error?cause when the process ends,the compile cannot call the private function so the object cannot be delete
No this is not a good implementation of the singleton pattern, it does not work!
The only instance of Test in the example is NULL! The constructor is never called!
You need to change Singleton::getInstancePtr to:
public:
static T* getInstancePtr()
{
if(instance == 0)
{
instance = new T();
}
return instance;
}
protected:
Singleton<T>() {};
The constructor for Test will now be called.
Usually singleton objects live for the lifetime of the program, so I do not implement them like that, because you use dynamic allocation, then someone must free it and you return a pointer to your singleton object, then you may accidentally delete it, so I will use something like this:
template< class T >
struct Singleton : Uncopyable<T> {
public:
static T& get_instance() {
static T res;
use( res ); // make sure object initialized before used
return res;
}
private:
static void use( T& ) {}
};
There is no correct implementation of the Singleton anti-pattern in C++.
The main issues with this attempt are:
The semantics are a very weird and error-prone; you must instantiate Singleton somewhere in order to create the instance. You example never creates the instance, and t->test() is erroneously calling a function via a null pointer.
Construction is not thread-safe; two instances could be created if two unsynchronised threads both instantiate Singleton.
If the instance is actually created, then it is leaked.
A less erroneous implementation might be more like this:
template <typename T>
T & singleton()
{
static T instance;
return instance;
}
but this still has issues: in particular, the instance may be destroyed before other static objects, which may attempt to access it in their destructors.

Looking for a better C++ class factory

I have an application that has several objects (about 50 so far, but growing). There is only one instance of each of these objects in the app and these instances get shared among components.
What I've done is derive all of the objects from a base BrokeredObject class:
class BrokeredObject
{
virtual int GetInterfaceId() = 0;
};
And each object type returns a unique ID. These IDs are maintained in a header file.
I then have an ObjectBroker "factory". When someone needs an object, then call GetObjectByID(). The boker looks in an STL list to see if the object already exists, if it does, it returns it. If not, it creates it, puts it in the list and returns it. All well and good.
BrokeredObject *GetObjectByID(int id)
{
BrokeredObject *pObject;
ObjectMap::iterator = m_objectList.find(id);
// etc.
if(found) return pObject;
// not found, so create
switch(id)
{
case 0: pObject = new TypeA; break;
case 1: pObject = new TypeB; break;
// etc.
// I loathe this list
}
// add it to the list
return pObject;
}
What I find painful is maintaining this list of IDs and having to have each class implement it. I have at least made my consumer's lives slightly easier by having each type hold info about it's own ID like this:
class TypeA : public BrokeredObject
{
static int get_InterfaceID() { return IID_TYPEA; }
int GetInterfaceID() { return get_InterfaceID(); }
};
So I can get an object like this:
GetObjectByID(TypeA::get_InterfaceID());
Intead of having to actually know what the ID mapping is but I still am not thrilled with the maintenance and the potential for errors. It seems that if I know the type, why should I also have to know the ID?
What I long for is something like this in C#:
BrokeredObject GetOrCreateObject<T>() where T : BrokeredObject
{
return new T();
}
Where the ObjectBroker would create the object based on the type passed in.
Has C# spoiled me and it's just a fact of life that C++ can't do this or is there a way to achieve this that I'm not seeing?
Yes, there is a way. A pretty simple even in C++ to what that C# code does (without checking for inheritance though):
template<typename T>
BrokeredObject * GetOrCreateObject() {
return new T();
}
This will work and do the same as the C# code. It is also type-safe: If the type you pass is not inherited from BrokeredObject (or isn't that type itself), then the compiler moans at the return statement. It will however always return a new object.
Singleton
As another guy suggested (credits to him), this all looks very much like a fine case for the singleton pattern. Just do TypeA::getInstance() to get the one and single instance stored in a static variable of that class. I suppose that would be far easier than the above way, without the need for IDs to solve it (i previously showed a way using templates to store IDs in this answer, but i found it effectively is just what a singleton is).
I've read that you will leave the chance open to have multiple instances of the classes. One way to do that is to have a Mingleton (i made up that word :))
enum MingletonKind {
SINGLETON,
MULTITON
};
// Singleton
template<typename D, MingletonKind>
struct Mingleton {
static boost::shared_ptr<D> getOrCreate() {
static D d;
return boost::shared_ptr<D>(&d, NoopDel());
}
struct NoopDel {
void operator()(D const*) const { /* do nothing */ }
};
};
// Multiton
template<typename D>
struct Mingleton<D, MULTITON> {
static boost::shared_ptr<D> getOrCreate() {
return boost::shared_ptr<D>(new D);
}
};
class ImASingle : public Mingleton<ImASingle, SINGLETON> {
public:
void testCall() { }
// Indeed, we have to have a private constructor to prevent
// others to create instances of us.
private:
ImASingle() { /* ... */ }
friend class Mingleton<ImASingle, SINGLETON>;
};
class ImAMulti : public Mingleton<ImAMulti, MULTITON> {
public:
void testCall() { }
// ...
};
int main() {
// both do what we expect.
ImAMulti::getOrCreate()->testCall();
ImASingle::getOrCreate()->testCall();
}
Now, you just use SomeClass::getOrCreate() and it cares about the details. The custom deleter in the singleton case for shared_ptr makes deletion a no-op, because the object owned by the shared_ptr is allocated statically. However, be aware of problems of destruction order of static variables: Static initialization order fiasco
The way I would solve this problem is using what I would call the Static Registry Pattern, which in my mine mind is the C++ version of dependency injection.
Basically you have a static list of builder objects of a type that you use to build objects of another type.
A basic static registry implementation would look like:
template <class T>
class StaticRegistry
{
public:
typedef std::list<T*> Container;
static StaticRegistry<T>& GetInstance()
{
if (Instance == 0)
{
Instance = new StaticRegistry<T>;
}
return *Instance;
}
void Register(T* item)
{
Items.push_back(item);
}
void Deregister(T* item)
{
Items.remove(item);
if (Items.empty())
{
delete this;
Instance = 0;
}
}
typedef typename Container::const_iterator const_iterator;
const_iterator begin() const
{
return Items.begin();
}
const_iterator end() const
{
return Items.end();
}
protected:
StaticRegistry() {}
~StaticRegistry() {}
private:
Container Items;
static StaticRegistry<T>* Instance;
};
template <class T>
StaticRegistry<T>* StaticRegistry<T>::Instance = 0;
An implementation of BrokeredObjectBuilder could look like this:
class BrokeredObjectBuilderBase {
public:
BrokeredObjectBuilderBase() { StaticRegistry<BrokeredObjectBuilderBase>::GetInstance().Register(this); }
virtual ~BrokeredObjectBuilderBase() { StaticRegistry<BrokeredObjectBuilderBase>::GetInstance().Deregister(this); }
virtual int GetInterfaceId() = 0;
virtual BrokeredObject* MakeBrokeredObject() = 0;
};
template<class T>
class BrokeredObjectBuilder : public BrokeredObjectBuilderBase {
public:
BrokeredObjectBuilder(unsigned long interface_id) : m_InterfaceId(interface_id) { }
virtual int GetInterfaceId() { return m_InterfaceId; }
virtual T* MakeBrokeredObject() { return new T; }
private:
unsigned long m_InterfaceId;
};
class TypeA : public BrokeredObject
{
...
};
// Create a global variable for the builder of TypeA so that it's
// included in the BrokeredObjectBuilderRegistry
BrokeredObjectBuilder<TypeA> TypeABuilder(TypeAUserInterfaceId);
typedef StaticRegistry<BrokeredObjectBuilderBase> BrokeredObjectBuilderRegistry;
BrokeredObject *GetObjectByID(int id)
{
BrokeredObject *pObject(0);
ObjectMap::iterator = m_objectList.find(id);
// etc.
if(found) return pObject;
// not found, so create
BrokeredObjectBuilderRegistry& registry(BrokeredObjectBuilderRegistry::GetInstance());
for(BrokeredObjectBuilderRegistry::const_iterator it = registry.begin(), e = registry.end(); it != e; ++it)
{
if(it->GetInterfaceId() == id)
{
pObject = it->MakeBrokeredObject();
break;
}
}
if(0 == pObject)
{
// userinterface id not found, handle this here
...
}
// add it to the list
return pObject;
}
Pros:
All the code that knows about creating the types is seperated out into the builders and the BrokeredObject classes don't need to know about it.
This implementation can be used in libraries and you can control on a per project level what builders are pulled into a project using a number of different techniques.
The builders can be as complex or as simple (like above) as you want them to be.
Cons:
There is a wee bit of infrastructure involved (but not too much).
The flexability of defining the global variables to include what builders to include in your project does make it a little messy to work with.
I find that people find it hard to understand this pattern, I'm not sure why.
It's sometimes not easy to know what is in the static registry at any one time.
The above implementation leaks one bit of memory. (I can live with that...)
The above implementation is very simple, you can extend it in lots of different ways depending on the requirements you have.
Use a template class as the broker.
Make the instance a static member of the function. It will be created on first use and automagically-destroyed when the program exits.
template <class Type>
class BrokeredObject
{
public:
static Type& getInstance()
{
static Type theInstance;
return theInstance;
}
};
class TestObject
{
public:
TestObject()
{}
};
int main()
{
TestObject& obj =BrokeredObject<TestObject>::getInstance();
}
Instead of GetInterfaceId() in the BrokeredObject base class, you could define that pure virtual method:
virtual BrokeredObject& GetInstance()=0;
And in the derived classes you'll return from that method the instance of the particular derived class, if it's already created, if not, you'll first create it and then return it.
It doesn't look like you need the global object to do the management, so why not move everything into the classes themselves?
template <class Type>
class BrokeredObject
{
protected:
static Type *theInstance;
public:
static Type *getOrCreate()
{
if (!theInstance) {
theInstance = new Type();
}
return theInstance;
}
static void free()
{
delete theInstance;
}
};
class TestObject : public BrokeredObject<TestObject>
{
public:
TestObject()
{}
};
int
main()
{
TestObject *obj = TestObject::getOrCreate();
}
If you have RTTI enabled, you can get the class name using typeid.
One question, why are you using a factory rather than using a singleton pattern for each class?
Edit: OK, so you don't want to be locked into a singleton; no problem. The wonderful thing about C++ is it gives you so much flexibility. You could have a GetSharedInstance() member function that returns a static instance of the class, but leave the constructor public so that you can still create other instances.
If you always know the type at compile time there is little point in calling BrokeredObject* p = GetObjectByID(TypeA::get_InterfaceID()) instead of TypeA* p = new TypeA or TypeA o directly.
If you on the other hand don't know the exact type at compile time, you could use some kind of type registry.
template <class T>
BrokeredObject* CreateObject()
{
return new T();
}
typedef int type_identity;
typedef std::map<type_identity, BrokeredObject* (*)()> registry;
registry r;
class TypeA : public BrokeredObject
{
public:
static const type_identity identity;
};
class TypeB : public BrokeredObject
{
public:
static const type_identity identity;
};
r[TypeA::identity] = &CreateObject<TypeA>;
r[TypeB::identity] = &CreateObject<TypeB>;
or if you have RTTI enabled you could use type_info as type_identity:
typedef const type_info* type_identity;
typedef std::map<type_identity, BrokeredObject* (*)()> registry;
registry r;
r[&typeid(TypeA)] = &CreateObject<TypeA>;
r[&typeid(TypeB)] = &CreateObject<TypeB>;
Each new class could of course, in any case, be self-registering in the registry, making the registration decentralized instead of centralized.
You should almost certainly be using dependency injection.
Why not this?
template
BrokeredObject* GetOrCreateObject()
{
return new T();
}
My use-case tended to get a little more complex - I needed the ability to do a little bit of object initialization and I needed to be able to load objects from different DLLs based on configuration (e.g. simulated versus actual for hardware). It started looking like COM and ATL was where I was headed, but I didn't want to add the weight of COM to the OS (this is being done in CE).
What I ended up going with was template-based (thanks litb for putting me on track) and looks like this:
class INewTransModule
{
public:
virtual bool Init() { return true; }
virtual bool Shutdown() { return true; }
};
template <typename T>
struct BrokeredObject
{
public:
inline static T* GetInstance()
{
static T t;
return &t;
}
};
template <>
struct BrokeredObject<INewTransModule>
{
public:
inline static INewTransModule* GetInstance()
{
static INewTransModule t;
// do stuff after creation
ASSERT(t.Init());
return &t;
}
};
class OBJECTBROKER_API ObjectBroker
{
public:
// these calls do configuration-based creations
static ITraceTool *GetTraceTool();
static IEeprom *GetEeprom();
// etc
};
Then to ensure that the objects (since they're templated) actually get compiled I added definitions like these:
class EepromImpl: public BrokeredObject<EepromImpl>, public CEeprom
{
};
class SimEepromImpl: public BrokeredObject<SimEepromImpl>, public CSimEeprom
{
};