There are very few basic types, so you can make an overload for each of them. I did this in this library. Everything works great.
#define MACROS(A) void Push( A Val ) { this.Push<A>(Val); } template <typename T> class Queue { public: template <typename T2> void Push( T2 &Val ) { /* Code for T2 */ } MACROS(char) MACROS(short) MACROS(int) MACROS(long) MACROS(uchar) MACROS(ushort) MACROS(uint) MACROS(ulong) MACROS(bool) MACROS(string) MACROS(double) MACROS(float) MACROS(color) MACROS(datetime) }; #undef MACROS void OnStart() { Queue<int> q_int; Queue<MqlTick> q_tick; MqlTick Tick; q_int.Push(1); q_tick.Push(Tick); }
Thanks very much for the share.
Only concern with this is that the code will get bloated for all the different collection types.
So if you use this signature in your templated class:
void Push<int>(const int val) { Array::Push(val, _arr); }
Then this will become the override for all int type queues?
I just need to get a second to try this out.
Does int cover all custom enum types as well?
I think it's best to divide those kind of libraries to three:
1. Base class template, with all methods and data shared for both objects and primitives.
2. A derived class template for objects/structs - derived from 1 with methods for objects
3. A derived class template for primitives - derived from one with the methods for primitives.
Just as prove of concept - Haven't tested this and is shared only to make a point.
* Sure need to take care of index = 0 in Pop() and so on.. But that's not the point of this post..
** Slight change in devision - division to reference / value (instead of points 2. 3.)
template <typename T> class QueueBase { private: T _arr[]; int m_begin,m_end; int m_count; protected: void PushItem(T &val); T m_null; public: void QueueBase() {m_count=0; m_begin=0; m_end=0;} void ~QueueBase() {}; int Size() {return m_count;} T Pop(); T Peek(); }; template <typename T> T QueueBase::Pop() { if(m_count<=0) return m_null; m_count--; return _arr[m_begin++]; } template <typename T> T QueueBase::Peek() { if(m_count<=0) return m_null; return _arr[m_begin]; } template <typename T> void QueueBase::PushItem(T &val) { m_count++; ArrayResize(_arr,m_count); _arr[m_end++]=val; } //+------------------------------------------------------------------+ //| For structs | //+------------------------------------------------------------------+ template <typename T> class QueueRef : public QueueBase<T> { public: void QueueRef() {T null= {0}; m_null=null;} void Push(T &val) {PushItem(val);}; }; //+------------------------------------------------------------------+ //| For objects and primitives | //+------------------------------------------------------------------+ template <typename T> class QueueVal : public QueueBase<T> { public: void QueueVal() {m_null=(T)NULL;} void Push(T val) {PushItem(val);} };
For using
QueueRef<ANYSTRUCT> q_struct; QueueVal<ANYCLASS *> q_class; QueueVal<double>q_dbl; QueueVal<int>q_int; QueueVal<ANYENUM>q_enum;
*-Changed the Push in QueueObj to use the base PushItem
**-Now the structs are handled in QueueRef, and the rest in QueueVal
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Given an example class below, I would like to be able to use it with values, pointers and structs.
This issue is that structs can only be passed by reference which gives me a lot of headaches trying to make my own personal library.
See the simple Queue class below which is templated.
I try to get around the struct issues by making the "PushRef" class.
However I can't compile if I make say a new Queue<MqlRates> class because the Push method will be templated with a struct and give me this issue...
I understand the fix is to just make everything in the Queue class accept a reference.
It's extremely annoying trying to make templated classes that can accept any data struct.
But my question to the all the IQ here is...
Is there any ways to work around this? Some hidden hack I haven't discovered yet?