126 lines
3.4 KiB
MQL5
126 lines
3.4 KiB
MQL5
|
//+------------------------------------------------------------------+
|
||
|
//| TemplatesExtended.mq5 |
|
||
|
//| Copyright 2021, MetaQuotes Ltd. |
|
||
|
//| https://www.mql5.com |
|
||
|
//+------------------------------------------------------------------+
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| External declarations in templates |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template<typename T>
|
||
|
class ClassType
|
||
|
{
|
||
|
ClassType() // private ctor, used only once in the 'create' method
|
||
|
{
|
||
|
s = &this;
|
||
|
}
|
||
|
static ClassType *s; // pointer to existing object
|
||
|
public:
|
||
|
static ClassType *create() // hard init (ensure object is created)
|
||
|
{
|
||
|
static ClassType single; // local static: singleton per T
|
||
|
return &single;
|
||
|
}
|
||
|
|
||
|
static ClassType *check() // soft init (return existing pointer w/o creation)
|
||
|
{
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
template<typename U>
|
||
|
void method(const U &u);
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
template<typename U>
|
||
|
void ClassType::method(const U &u)
|
||
|
{
|
||
|
Print(__FUNCSIG__, " ", typename(T), " ", typename(U));
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
static ClassType<T> * ClassType::s = NULL;
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Inheritance with templates |
|
||
|
//+------------------------------------------------------------------+
|
||
|
|
||
|
#define RTTI Print(typename(this))
|
||
|
|
||
|
template<typename T, typename B>
|
||
|
class DerivedFrom
|
||
|
{
|
||
|
typedef void(*ppp)(T*);
|
||
|
static void constraints(T* p) { B* pb = p; }
|
||
|
public:
|
||
|
DerivedFrom() { ppp p = constraints; }
|
||
|
};
|
||
|
|
||
|
class Base
|
||
|
{
|
||
|
public:
|
||
|
Base() { RTTI; }
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
class Derived : public T
|
||
|
{
|
||
|
public:
|
||
|
Derived() { RTTI; }
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
class Base1
|
||
|
{
|
||
|
Derived<T> object;
|
||
|
public:
|
||
|
Base1() { RTTI; }
|
||
|
};
|
||
|
|
||
|
template<typename T> // full "specialization"
|
||
|
class Derived1 : public Base1<Base> // (1 of 1 parameter specified)
|
||
|
{
|
||
|
DerivedFrom<T,Base> df(); // constraint: want T based on Base
|
||
|
public:
|
||
|
Derived1() { RTTI; }
|
||
|
};
|
||
|
|
||
|
template<typename T,typename E>
|
||
|
class Base2 : public T
|
||
|
{
|
||
|
public:
|
||
|
Base2() { RTTI; E e = (E)""; } // constraint: stringifiable E expected
|
||
|
};
|
||
|
|
||
|
template<typename T> // partial "specialization"
|
||
|
class Derived2 : public Base2<T,string> // (1 of 2 parameters specified)
|
||
|
{
|
||
|
public:
|
||
|
Derived2() { RTTI; }
|
||
|
};
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Script program start function |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void OnStart()
|
||
|
{
|
||
|
ClassType<string> *object = ClassType<string>::create();
|
||
|
double d = 5.0;
|
||
|
object.method(d);
|
||
|
// OUTPUT:
|
||
|
// void ClassType<string>::method<double>(const double&) string double
|
||
|
|
||
|
Print(ClassType<string>::check()); // 1048576 (example of instance id)
|
||
|
Print(ClassType<long>::check()); // 0 (no instance for T=long)
|
||
|
|
||
|
Derived2<Derived1<Base>> derived2;
|
||
|
// OUTPUT:
|
||
|
// Base
|
||
|
// Derived<Base>
|
||
|
// Base1<Base>
|
||
|
// Derived1<Base>
|
||
|
// Base2<Derived1<Base>,string>
|
||
|
// Derived2<Derived1<Base>>
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|