How can I create a singleton class in mql4

 

Hi all,

I wanted to create a singleton (OO design pattern) class and wrote the following code. However, I'm getting an unresolved static variable pool error while compiling. Any suggestions how to fix it?

class Pool {
   private:
      static Pool* pool;
      Pool (void) {
      }
   
   public:     
      static Pool* getInstance() {
         if (!pool){
            pool = new Pool();
         }          
         return(pool);
      }      
};
 
 

That documentation isn't exactly super-clear about the fact that, like in C++, the static variable must be initialized:

class Pool {
   private:
      static Pool* instance;
      Pool() {}

   public:
      static Pool * getInstance() {
         if (!instance) instance = new Pool();
         return instance;
      }   
};
Pool * Pool::instance = NULL;

 The further problem is that MT4/MQL4 then gives a helpful runtime warning, upon termination, about the fact that the instance of the class hasn't been explicitly deleted.

 The following version is simpler, but suffers from the same issue that there's no way of cleaning up the object reference, and therefore MT4/MQL4 complains:

class Pool {
   private:
       Pool() {}
       
   public:     
      static Pool * getInstance() {
         static Pool * instance = new Pool();
         return instance;
      }
};
 
jjc:

That documentation isn't exactly super-clear about the fact that, like in C++, the static variable must be initialized:

 The further problem is that MT4/MQL4 then gives a helpful runtime warning, upon termination, about the fact that the instance of the class hasn't been explicitly deleted.

 The following version is simpler, but suffers from the same issue that there's no way of cleaning up the object reference, and therefore MT4/MQL4 complains:

 

Thank you!
 
jjc:

The further problem is that MT4/MQL4 then gives a helpful runtime warning, upon termination, about the fact that the instance of the class hasn't been explicitly deleted. 

I can't see an alternative to doing the following:

class Pool {
   private:
      static Pool* instance;
      Pool() {}

   public:
      static Pool * getInstance() {
         if (!instance) instance = new Pool();
         return instance;
      }   
      static void Release() {
         delete instance;
         instance = NULL;
      }
};
Pool * Pool::instance = NULL;

...

void OnDeinit(const int reason)
{
    Pool::Release();
}
... at which point, unless you are part of the 0.001% of MQL4 developers working as part of a team and sharing code on a large project, it becomes increasingly less clear what you have achieved compared to simply having a single instance of a class in a global variable.
 
jjc:

... at which point [...]

If we want to get cute, then we can template it as follows:

#define SINGLETON(T) class T : public Singleton<T>  { private: T() {SingleInstanceConstructor();}  public: static T * getInstance() {if (!instance) instance = new T();return (T*)instance;}
template <typename T>
class Singleton {
   private:
      virtual void SingleInstanceConstructor() = NULL;

   protected:
      static T * instance;
      Singleton() {}
      
   public:
      static void Release() {
         if (instance) {
            delete instance;
            instance = NULL;
         }
      }
};
template <typename T>
T * Singleton::instance = NULL;

 

Any individual singleton class can then be declared more succinctly as follows:

SINGLETON(Pool)
private:
   // Takes the place of the normal constructor; must be declared
   void SingleInstanceConstructor() { ... etc ...}

public:
   // Whatever public functions you need in this singleton...
};


Still need to clean up any singletons which are used, in OnDeinit. 

Reason: