Post MT5 Updates errors [template<typename Object>]

 

Hi all,

A few moments ago I restarted the MT5 platform on request for an update and upon starting Metaeditor5, all my classes with template<typename Object> have stopped working I get

"'Object' - unexpected token, probably type is missing? Objects.mqh 171 1'*' - semicolon expected Objects.mqh"

I have not done anything at all except restart the platform.  I wrote the container below years ago, and now it has suddenly started bugging out.  This is rather disconcerting.  I would really appreciate any advice.  Has anyone faced this problem before, and how can I resolve it?

//+------------------------------------------------------------------+
//| Objects.mqh                                                      |
//+------------------------------------------------------------------+
#define MAX_CAPACITY 50000
//+------------------------------------------------------------------+
//| Class CObjects.                                                  |
//| Puprose: Class of dynamic array of pointers to instances         |
//|          of Object class and its derivatives.                    |
//|          Derives from class CObjects.                            |
//+------------------------------------------------------------------+
template<typename Object>
class CObjects {
 protected:
   int               _total;
   int               _capacity;

   Object*           _data[MAX_CAPACITY];

   bool              IsPtr(const void*) const;
   int               Move(const int, const int, int);

 public:
                     CObjects(void);
                    ~CObjects(void);
   //---
   int               Total(void) const;
   int               Capacity(void) const;
   //---
   int               Available(void) const;
   //---
   void              Clear(void);
   //--- methods of filling array
   bool              Add(Object*);
   bool              Add(const CObjects*);
   //---
   bool              Insert(Object*, const int);
   bool              Insert(const CObjects*, const int);
   //---
   bool              Assign(const CObjects*);
   //--- method of access to thre array
   Object*           Get(const int) const;
   Object*           operator[](const int) const;
   //--- methods of changing
   bool              Update(const int, Object*);
   bool              Shift(const int, const int);
   //--- methods of deleting
   Object*           Detach(const int);
   bool              Delete(const int);
   bool              Delete(const int, int);
};
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
template<typename Object>
CObjects::CObjects(void) :
   _total(0),
   _capacity(MAX_CAPACITY) {
}
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
template<typename Object>
CObjects::~CObjects(void) {
   if(_total > 0) Clear();
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
template<typename Object>
int CObjects::Total(void) const {
   return(_total);
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
template<typename Object>
int CObjects::Available(void) const {
   return(_capacity - _total);
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
template<typename Object>
int CObjects::Capacity(void) const {
   return(_capacity);
}
//+------------------------------------------------------------------+
//| Adding an item to end of array                                   |
//+------------------------------------------------------------------+
template<typename Object>
bool CObjects::Add(Object* item) {
   if(!IsPtr(item)) return(false);
   _data[_total++] = item;
   return(true);
}
//+------------------------------------------------------------------+
//| Adding an item to end of array from another array                |
//+------------------------------------------------------------------+
template<typename Object>
bool CObjects::Add(const CObjects* src) {
   if(!IsPtr(src)) return(false);
//---
   int total = src.Total();
   for(int i = 0; i < total; i++)
      _data[_total++] = src._data[i];
   return(true);
}
//+------------------------------------------------------------------+
//| Inserting an item in specified position                          |
//+------------------------------------------------------------------+
template<typename Object>
bool CObjects::Insert(Object* item, const int pos) {
   if(pos < 0) return(false);
   if(!IsPtr(item)) return(false);
//---
   _total++;
//---
   if(pos < _total - 1) {
      int count = _total - pos - 1;
      if(Move(pos + 1, pos, count) < 0)
         return(false);
      _data[pos] = item;
   } else _data[_total - 1] = item;
//---
   return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in specified position                         |
//+------------------------------------------------------------------+
template<typename Object>
bool CObjects::Insert(const CObjects* src, const int pos) {
   if(!IsPtr(src)) return(false);
//---
   int total = src.Total();
//---
   if(Move(total + pos, pos, _total - pos) < 0)
      return(false);
//---
   for(int i = 0; i < total; i++)
      _data[i + pos] = src._data[i];
//---
   return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array                            |
//+------------------------------------------------------------------+
template<typename Object>
bool CObjects::Assign(const CObjects* src) {
   if(!IsPtr(src)) return(false);
//---
   int total = src._total;
//---
   Clear();
//---
   if(total > _capacity) {
      ::printf("%s: src is has too many items", __FUNCTION__);
      return(false);
   }
//---
   for(int i = 0; i < total; i++) {
      _data[i] = src._data[i];
      _total++;
   }
//---
   return(true);
}
//+------------------------------------------------------------------+
//| Access to data in specified position                             |
//+------------------------------------------------------------------+
template<typename Object>
Object* CObjects::Get(const int idx) const {
   if(idx < 0 || idx >= _total)
      return(NULL);
   return(_data[idx]);
}
//+------------------------------------------------------------------+
//| Access to data in specified position                             |
//+------------------------------------------------------------------+
template<typename Object>
Object* CObjects::operator[](const int idx) const {
   if(idx < 0 || idx >= _total)
      return(NULL);
   return(_data[idx]);
}
//+------------------------------------------------------------------+
//| Updating item in specified position                              |
//+------------------------------------------------------------------+
template<typename Object>
bool CObjects::Update(const int idx, Object* item) {
   if(idx < 0) return(false);
   if(!IsPtr(item)) return(false);
   if(idx >= _total) return(false);
//---
   if(IsPtr(_data[idx]))
      delete(_data[idx]);
   _data[idx] = item;
//---
   return(true);
}
//+------------------------------------------------------------------+
//| Moving item from specified position on specified shift           |
//+------------------------------------------------------------------+
template<typename Object>
bool CObjects::Shift(const int idx, const int shift) {
   if(idx < 0) return(false);
   if(idx + shift < 0) return(false);
   if(idx + shift >= _total) return(false);
//---
   if(shift == 0) return(true);
//---
   Object* tmp = _data[idx];
//---
   _data[idx] = NULL;
//---
   if(shift > 0) {
      if(Move(idx, idx + 1, shift) < 0)
         return(false);
   } else {
      if(Move(idx + shift + 1, idx + shift, -shift) < 0)
         return(false);
   }
//---
   _data[idx + shift] = tmp;
//---
   return(true);
}
//+------------------------------------------------------------------+
//| Deleting item from specified position                            |
//+------------------------------------------------------------------+
template<typename Object>
bool CObjects::Delete(const int idx) {
   if(idx >= _total) return(false);
//---
   if(idx < _total - 1) {
      int count = _total - idx - 1;
      if(idx >= 0 && Move(idx, idx + 1, count) < 0)
         return(false);
   } else if(IsPtr(_data[idx]))
      delete _data[idx];
//---
   _total--;
//---
   return(true);
}
//+------------------------------------------------------------------+
//| Detach item from specified position                              |
//+------------------------------------------------------------------+
template<typename Object>
Object* CObjects::Detach(const int idx) {
   if(idx >= _total) return(NULL);
//---
   Object* result = _data[idx];
//---
   _data[idx] = NULL;
//---
   int count = _total - idx - 1;
   if(idx < _total - 1 && Move(idx, idx + 1, count) < 0)
      return(NULL);
//---
   _total--;
//---
   return(result);
}
//+------------------------------------------------------------------+
//| Deleting range of elements                                       |
//+------------------------------------------------------------------+
template<typename Object>
bool CObjects::Delete(const int from, int to) {
   if(from < 0 || to < 0) return(false);
   if(from > to || from >= _total) return(false);
//---
   if(to >= _total - 1) to = _total - 1;
//---
   if(Move(from, to + 1, _total - to - 1) < 0)
      return(false);
//---
   for(int i = to - from + 1; i > 0; i--, _total--) {
      if(IsPtr(_data[_total - 1]))
         delete(_data[_total - 1]);
   }
//---
   return(true);
}
//+------------------------------------------------------------------+
//| Clearing of array without release of memory                      |
//+------------------------------------------------------------------+
template<typename Object>
void CObjects::Clear(void) {
   for(int i = 0; i < _total; i++) {
      if(IsPtr(_data[i]))
         delete(_data[i]);
      _data[i] = NULL;
   }
//---
   _total = 0;
}
//+------------------------------------------------------------------+
//| Helpers                                                          |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
template<typename Object>
bool CObjects::IsPtr(const void* IsPtr) const {
   return(::CheckPointer(IsPtr) == POINTER_DYNAMIC);
}
//+------------------------------------------------------------------+
//| Moving memory within a single array                              |
//+------------------------------------------------------------------+
template<typename Object>
int CObjects::Move(const int dst, const int src, int count) {
   if(dst < 0) return(-1);
   if(src < 0 || count < 0) return(-1);
//---
   if(src + count > _total)
      count = _total - src;
//---
   if(count < 0) return(-1);
   if(dst == src || count == 0) return(dst);
//---
   if(dst + count > _total) {
      if(_capacity < dst + count)
         return(-1);
      _total = dst + count;
   }
//---
   if(dst < src) {
      for(int i = 0; i < count; i++) {
         if(IsPtr(_data[dst + i]))
            delete(_data[dst + i]);
         _data[dst + i] = _data[src + i];
         _data[src + i] = NULL;
      }
   } else {
      for(int i = count - 1; i >= 0; i--) {
         if(IsPtr(_data[dst + i]))
            delete(_data[dst + i]);
         _data[dst + i] = _data[src + i];
         _data[src + i] = NULL;
      }
   }
//---
   return(dst);
}
//+------------------------------------------------------------------+


Thank you all in advance,

Shep

 

Which MT5 Build do you have ?

https://www.mql5.com/en/forum/445154
MT5 Release 3672 potentially breaks CObject?
MT5 Release 3672 potentially breaks CObject?
  • 2023.04.08
  • www.mql5.com
Sorry if this is the wrong place - but I couldn't find anywhere else to post a bug alert...
 
Alain Verleyen #:

Which MT5 Build do you have ?

https://www.mql5.com/en/forum/445154

Hi Alain,

I have MT5 build 3674. I believe the latest version.  So if it's the build, is there a way to role back maybe.  What would you suggest please?

Thanks for the quick response Alain.

Kind regards,
Shep

 
Alain Verleyen #:

Which MT5 Build do you have ?

https://www.mql5.com/en/forum/445154

Hi Alain,

Quick update.  I rolled back the installation to an earlier build and my code compiles now.  At least now I understand the reason for the compilation failures and now need to develop a plan to deal with these potential errors caused by updates - maybe consider stopping automatic updates.

Thanks for help.
Shep

 

Shephard Mukachi #:

... maybe consider stopping automatic updates.

I have the suspicion that MQ-demo accounts are automatically updated (or annoying by request window) no matter whether you have defined to use only release versions - but not demo and real accounts of real brokers.
 
Same issue with template functions.
 
Carl Schreiber #:
I have the suspicion that MQ-demo accounts are automatically updated (or annoying by request window) no matter whether you have defined to use only release versions - but not demo and real accounts of real brokers.
Carl, you could be right. Honestly, it gave me a fright because I'm a few hours to launching my system. I wasn't expecting that at all and started imagining all sorts of horror where the systems just stops working soon after going live. 

After many hours of searching, I experimented with installing an older version, suddenly the errors disappeared. I'll also find a non MQ demo account for next couple of days before I launch, for the peace of mind.

Thanks Carl
 
amrali #:
Same issue with template functions.
Indeed, my entire code base went crazy - I use templates extensively.
 

Forum on trading, automated trading systems and testing trading strategies

General rules and best practices of the Forum.

Alain Verleyen, 2023.04.09 13:27

Official releases always have a public announcement.

It's the broker who decided which release to push to their clients.

The betas are entirely Metaquotes responsibility (brokers can't push them). The main server for betas is MetaQuotes-demo. This server is used by Metaquotes when they approach the release dates to conduct larger beta tests, as they know a lot of active developers use it for their tests.

If you don't want to be a beta-tester, never use MetaQuotes-demo server.


 
Alain Verleyen #:

That is sound advice Alain.  I was not aware of it.  Thanks.

Reason: