How to use CHashMap with custom struct?

 

I would like to use CHashMap to store key/value pair where key will be string and value will be a struct variable.

Trying with below code, but its not compiling.

// Include additional header
#include <Generic/HashMap.mqh>

// User defined struct
struct MyStruct
{
      string symbol;
      double volume;
      double rate;
};

CHashMap <string, MyStruct> SymbolMap;

And below is the error.

'MyStruct' - objects are passed by reference only    HashMap.mqh    36    45

How to fix the compile error?


Thanks.

 
This is one of the major limitations of MQL. You are forced to use a workaround.

The underlying issue is with return values of functions. Since they can only return fundamental types, there is no way out. You will have to adapt the template or the usage. Either extend the template to take both reference type of struct and the struct type itself as specification, or use an external array with the structs and only map the index of the array in the hash map.
 

Use class instead of struct to gain the benefit of object pointers.

// Include additional header
#include <Generic/HashMap.mqh>

// User defined struct
class MyStruct
  {
public:
   string            symbol;
   double            volume;
   double            rate;
  };

CHashMap <string, MyStruct *> SymbolMap;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   // set
   MyStruct *st = new MyStruct();
   if(SymbolMap.TrySetValue("MyKey",st))
     {
      st.symbol = "EURUSD";
      st.volume = 0.1;
      st.rate = 1.12345;
     }

   // get
   MyStruct *st_out = NULL;
   if(SymbolMap.TryGetValue("MyKey",st_out))
     {
      Print(st_out.symbol);
      Print(st_out.volume);
      Print(st_out.rate);
     }
  }
//+------------------------------------------------------------------+

Edit: you can check this script for more complete usage. https://www.mql5.com/en/code/25667
Export Summary Grouped by Symbols
Export Summary Grouped by Symbols
  • www.mql5.com
The script exports summary of closed trades grouped by each currency pair to .csv file
 
That's a good idea.

When using pointers, use a wrapper to utilize smart pointers.

This will help you with new and delete so you keep track of existing objects.

Do not forget to think about memory fragmentation.

Edit:
Here you can use class and struct interchangeable. You do not seem to need the advantages of a class in this case.
 
amrali:

Use class instead of struct to gain the benefit of object pointers.

Edit: you can check this script for more complete usage. https://www.mql5.com/en/code/25667

Hi amrali,

Many thanks for your suggestion.

I have already implemented according to your way.

Class is better than Struct in this case.

 

Thanks everyone for your valuable comments.

 
Could you please elaborate why a class is better than a struct in this case.

This might be very useful information for others to read.
 
Dominik Egert:
Could you please elaborate why a class is better than a struct in this case.

This might be very useful information for others to read.
You just can't use a struct with CHashMap, because struct doesn't support pointers in mql.
 
Dominik Egert:
That's a good idea.

When using pointers, use a wrapper to utilize smart pointers.

This will help you with new and delete so you keep track of existing objects.

Do not forget to think about memory fragmentation.

Edit:
Here you can use class and struct interchangeable. You do not seem to need the advantages of a class in this case.

While smart (owning) pointers help with proper memory management, raw (non-owning) pointers are still useful for the organizational purposes in data structures (like CHashMap). A smart pointer is automatically deleted when it goes out of scope. But for the HashMap we need to control the lifetime of our pointers, so I see raw pointers are better here. 

Edit:

(An alternative solution is a smart container, like CArrayObj. It is auto-cleaning container of pointers. The container's destructor ~CArrayObj() automatically handles the memory cleanup).

However, insertions, deletions and search in CArrayObj are slower than in CHashMap.

My other script for MT4 https://www.mql5.com/en/code/25710 uses CArrayObj (smart container) as MQL4 does not have CHashMap.

Export Summary Grouped by Symbols (MT4)
Export Summary Grouped by Symbols (MT4)
  • www.mql5.com
The script exports summary of closed trades grouped by each currency pair to .csv file
Reason: