Особенности языка mql5, тонкости и приёмы работы - страница 221

 
fxsaber #:

Не знаю, как сохранить функционал (подполе и метод) и удобное использование. Возможно, этот вариант подойдет под ваши задачи.


Применение.

That was so quick and now it works just fine, thank you!


To Russia with love❤️! ;-)

 
Когда-то в MQL5 можно было легко написать такой макрос.
class MqlRatestime
{
public:
  static void f( MqlRates &Value ) { Print(Value.time); }
};

class MqlTicktime
{
public:
  static void f( MqlTick &Value ) { Print(Value.time); }
};

void OnStart()
{  
  MqlRates Rates;
  MqlTick Tick;
  
  MACROS(Rates, time); // MqlRatestime::f(Rates);
  MACROS(Tick, time);  // MqlTicktime::f(Tick);
}


В текущей версии MQL5 возможно ли такое? Мне не хватило находчивости преодолеть эту преграду:

template declarations are allowed on global, namespace or class scope only
 
fxsaber #:
Когда-то в MQL5 можно было легко написать такой макрос.


В текущей версии MQL5 возможно ли такое? Мне не хватило находчивости преодолеть эту преграду:

Не понял задачу - нужно чтобы класс MqlRatestime (шаблон для него) объявлялся внутри макроподстановки?
 
mktr8591 #:
Не понял задачу - нужно чтобы класс MqlRatestime (шаблон для него) объявлялся внутри макроподстановки?
Мне кажется, надо иметь разную макроподстановку для параметров разного типа.
Только я не понимаю, зачем это делать с помощью макроподстановки, а не перегрузки функций.
 
mktr8591 #:
Не понял задачу - нужно чтобы класс MqlRatestime (шаблон для него) объявлялся внутри макроподстановки?

Нет, классы уже объявлены. В комментариях указано, какой результат нужно получить. На вход в макрос идет объект, а на выходе вызывается класс, содержащий название типа этого объекта.

 
Sergey Gridnev #:
Мне кажется, надо иметь разную макроподстановку для параметров разного типа.
Только я не понимаю, зачем это делать с помощью макроподстановки, а не перегрузки функций.

Задача родилась из этой.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Особенности языка mql5, тонкости и приёмы работы

fxsaber, 2022.02.11 15:44

ArraySortStruct_Define(MqlRates, open)
ArraySortStruct_Define(MqlRates, high)
ArraySortStruct_Define(MqlRates, time)

void OnStart()
{
  MqlRates Rates[];
  
  CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары
  
  Print("\nБары без сортировки - как получили.");
  ArrayPrint(Rates);
  
  Print("\nСортируем по open-цене.");
  ArraySortStruct(MqlRates, Rates, open);
  ArrayPrint(Rates);

  Print("\nСортируем по high-цене.");
  ArraySortStruct(MqlRates, Rates, high);
  ArrayPrint(Rates);

  Print("\nСортируем по времени.");
  ArraySortStruct(MqlRates, Rates, time);
  ArrayPrint(Rates);
}

Выделил цветом входной параметр, в котором вынужден указывать тип. В макросе получается из-за этого три входных. А хотелось бы два - без типа.

 
fxsaber #:

Нет, классы уже объявлены. В комментариях указано, какой результат нужно получить. На вход в макрос идет объект, а на выходе вызывается класс, содержащий название типа этого объекта.

Как решить эту задачу не знаю.

А чтобы ArraySortStruct с двумя параметрами - вот так работает:

#define ArraySortStruct(ARRAY, FIELD) SortOnField_##FIELD::SORT::Sort(ARRAY)

ArraySortStruct_Define(SortOnField_, open)
ArraySortStruct_Define(SortOnField_, high)
ArraySortStruct_Define(SortOnField_, time)


void OnStart()
  {

   MqlRates Rates[];

   CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары

   Print("\nБары без сортировки - как получили.");
   ArrayPrint(Rates);

   Print("\nСортируем по open-цене.");
   ArraySortStruct(Rates, open);
   ArrayPrint(Rates);

   Print("\nСортируем по high-цене.");
   ArraySortStruct(Rates, high);
   ArrayPrint(Rates);

   Print("\nСортируем по времени.");
   ArraySortStruct(Rates, time);
   ArrayPrint(Rates);
  }
 
mktr8591 #:

А чтобы ArraySortStruct с двумя параметрами - вот так работает:

Вы правы, Спасибо! Перемудрил я на ровном месте. Оставлю Ваш вариант для сортировки.

// Сортировка массива структур и указателей на объекты по полю.
#define ArraySortStruct_Define(FIELD)                                            \
namespace SortOnField_##FIELD                                                    \
{                                                                                \
  class SORT                                                                     \
  {                                                                              \
  private:                                                                       \
    template <typename T>                                                        \
    static void Swap( T &Array[], const int i, const int j )                     \
    {                                                                            \
      const T Temp = Array[i];                                                   \
                                                                                 \
      Array[i] = Array[j];                                                       \
      Array[j] = Temp;                                                           \
                                                                                 \
      return;                                                                    \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static int Partition( T &Array[], const int Start, const int End )           \
    {                                                                            \
      int Marker = Start;                                                        \
                                                                                 \
      for (int i = Start; i <= End; i++)                                         \
        if (Array[i].##FIELD <= Array[End].##FIELD)                              \
        {                                                                        \
          SORT::Swap(Array, i, Marker);                                          \
                                                                                 \
          Marker++;                                                              \
        }                                                                        \
                                                                                 \
       return(Marker - 1);                                                       \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static void QuickSort( T &Array[], const int Start, const int End )          \
    {                                                                            \
      if (Start < End)                                                           \
      {                                                                          \
        const int Pivot = Partition(Array, Start, End);                          \
                                                                                 \
        SORT::QuickSort(Array, Start, Pivot - 1);                                \
        SORT::QuickSort(Array, Pivot + 1, End);                                  \
      }                                                                          \
                                                                                 \
      return;                                                                    \
    }                                                                            \
                                                                                 \
  public:                                                                        \
    template <typename T>                                                        \
    static void Sort( T &Array[], int Count = WHOLE_ARRAY, const int Start = 0 ) \
    {                                                                            \
      if (Count == WHOLE_ARRAY)                                                  \
        Count = ::ArraySize(Array);                                              \
                                                                                 \
      SORT::QuickSort(Array, Start, Start + Count - 1);                          \
                                                                                 \
      return;                                                                    \
    }                                                                            \
  };                                                                             \
}

#define ArraySortStruct(ARRAY, FIELD) SortOnField_##FIELD::SORT::Sort(ARRAY)


Применение.

ArraySortStruct_Define(open)
ArraySortStruct_Define(high)
ArraySortStruct_Define(time)

void OnStart()
{
  MqlRates Rates[];
  
  CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары
  
  Print("\nБары без сортировки - как получили.");
  ArrayPrint(Rates);
  
  Print("\nСортируем по open-цене.");
  ArraySortStruct(Rates, open);
  ArrayPrint(Rates);
  
  Print("\nСортируем по high-цене.");
  ArraySortStruct(Rates, high);
  ArrayPrint(Rates);
  
  Print("\nСортируем по времени.");
  ArraySortStruct(Rates, time);
  ArrayPrint(Rates);
}


ЗЫ Жаль, по подполю или методу не получается.

 
Может для кого то это не новость, но для меня неожиданно.
Если DLL используется одновременно в разных программах MT5,
то имейте ввиду, что она загружается единожды первой запущенной программой которая её использует.
То есть окружение DLL находится в одном общем процессе, независимо от того, сколько раз вы её импортируете.
 В чём же фишка? В том, что глобальные указатели используемые в DLL, находятся в пространстве одного общего процесса.
И это очень удобно.
 
Roman #:
Может для кого то это не новость, но для меня неожиданно.
Если DLL используется одновременно в разных программах MT5,
то имейте ввиду, что она загружается единожды первой запущенной программой которая её использует.
То есть состояние DLL находится в одном общем процессе, независимо от того, сколько раз вы её импортируете.
 В чём же фишка? В том, что глобальные указатели используемые в DLL, находятся в пространстве одного общего процесса.
И это очень удобно.

Это не новость, они так всегда от рождения работают.

только если данные больше чем __atomic__ надо доступ обкладывать/защищать критическими секциями (или mutex в терминал std::thread)