Требуется решение (специализация шаблонной функции)

 

Требуется реализовать примерно такую конструкцию,  чтобы функция могла отдельно обрабатывать переменные стандартных типов, и отдельно объекты структур.  Т.е. нужна специализация шаблонной функции, либо просто сочетание шаблона и перегрузки.  Но MQL ничего этого не поддерживает, в отличие от C++.

template<typename T>
void Write(T& a) {  }  // обработчик для структур

void Write(long& a) {  }  // либо  template<> void Write<long> (long& a) {  }

void Write(int& a) {  }   // либо  template<> void Write<int> (int& a) {  }

void Write(short& a) {  } // либо  template<> void Write<short> (short& a) {  }

Может у кого есть идеи, как тут выкрутиться костыльными способами?  Т.е. каким-то образом отделить структуры от остальных типов.

 
meat:

Требуется реализовать примерно такую конструкцию,  чтобы функция могла отдельно обрабатывать переменные стандартных типов, и отдельно объекты структур.  Т.е. нужна специализация шаблонной функции, либо просто сочетание шаблона и перегрузки.  Но MQL ничего этого не поддерживает, в отличие от C++.

Может у кого есть идеи, как тут выкрутиться костыльными способами?  Т.е. каким-то образом отделить структуры от остальных типов.

Два варианта навскидку: реализовать классы обертки для стандартных типов и генерить шаблонные классы по первому случаю, либо сделать базовый класс для "структур" (а-ля Variant) и внутри него зарезервировать поля стандартных типов и работать с ними по наличию какого-то флага - опять получается по первому случаю.
 
Alexey Navoykov:

Может у кого есть идеи, как тут выкрутиться костыльными способами?  Т.е. каким-то образом отделить структуры от остальных типов.

  1. Для структурной Write добавить второй фальш-параметр.
  2. Поскольку названия стандартных типов знаем, сделать только один шаблонный вариант, а внутри switch (typename(T)).
  3. Поиграться с const.

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

    Ошибки, баги, вопросы

    fxsaber, 2016.10.23 23:52

    Наткнулся у себя на хороший пример
    class A
    {
    public:
      void operator =( const string Value ) const { return; }

      void operator =( const int Value ) { return; }
    };

    void OnStart()
    {
      const A a;

      a = 0; // implicit conversion from 'number' to 'string'
    }
    Не очевидно было в начале, почему предупреждение. Умный компилятор, однако.

 
Alexey Navoykov:

Может у кого есть идеи, как тут выкрутиться костыльными способами?  Т.е. каким-то образом отделить структуры от остальных типов.

Передавать структуры и классы по указателю. Указатели специализируются легко.

sfinae насколько я знаю в MQL нет, так что красиво не получится.

 
Комбинатор:

Передавать структуры и классы по указателю. Указатели специализируются легко.

Это как?
 

Что-то мой древний топик растревожили, да всё без толку :)

fxsaber:
  1. Для структурной Write добавить второй фальш-параметр.
  2. Поскольку названия стандартных типов знаем, сделать только один шаблонный вариант, а внутри switch (typename(T)).
  3. Поиграться с const.

1. Тогда уж проще название функции переименовать :)  Так что не вариант.

2. Ну switch - это, во-первых, рантайм (а значит лишние тормоза), и во вторых, так можно разделить только простые типы, поскольку они свободно приводятся друг к другу. А для структур это не поможет.

3. Ну если передавать именно константную структуру, то может и выйдет, но здесь не шла речь о константности.

Комбинатор:
Передавать структуры и классы по указателю. Указатели специализируются легко.

Возможно вы посланы из будущего, где в MQL уже есть указатели на структуры, но нашей реальности пока такого нет.


А теперь, господа знатоки, внимание, правильный ответ:

struct A
{
 template<typename T>
  static void Func(T& a)  {   }  // обработчик для структур
};

struct B : A
{
  static void Func(short& a) {  }
  static void Func(int& a)   {  }
  static void Func(long& a)  {  }
  static void Func(double& a) {  }  
};


template<typename T>
void Func(T& a)  { B::Func(a); }

Надеюсь в будущем допилят шаблоны функций, чтобы можно было обходится без таких костылей. А если добавят указатели на любые типы данных, то будет вообще замечательно.

А пока только такой вариант нашёл.

 
Alexey Navoykov:

Возможно вы посланы из будущего, где в MQL уже есть указатели на структуры, но нашей реальности пока такого нет.

Значит наврал. Тогда не знаю.
 
Alexey Navoykov:

2. Ну switch - это, во-первых, рантайм (а значит лишние тормоза), и во вторых, так можно разделить только простые типы, поскольку они свободно приводятся друг к другу. А для структур это не поможет.

Не вижу препятствий.

А теперь, господа знатоки, внимание, правильный ответ:

struct A
{
 static template<typename T>
  void Func(T& a)  {   }  // обработчик для структур
};

struct B : A
{
  static void Func(short& a) {  }
  static void Func(int& a)   {  }
  static void Func(long& a)  {  }
  static void Func(double& a)  {  }  
};


template<typename T>
void Func(T& a)  { B::Func(a); }

Надеюсь в будущем допилят шаблоны функций, чтобы можно было обходится без таких костылей. А если добавят указатели на любые типы данных, то будет вообще замечательно.

А пока только такой вариант нашёл.

Этот вариант предложили в первом ответе. Только не понимаю, почему компилятор не ругается. Фактически, одно и то же.

Шаблоны улучшать в данном случае - видится лишним. Нужно просто приоритеты компилятору учитывать. Если явно задан тип в описании функции - вызывать ее. Нет - шаблонный вариант. 

 

Alexey Navoykov:

А пока только такой вариант нашёл.

А стринги, массивы, всякие float, ushort, char и т.п. ?
 
fxsaber:

Не вижу препятствий.

Этот вариант предложили в первом ответе. Только не понимаю, почему компилятор не ругается. Фактически, одно и то же.

Нет, в первом ответе предложили совсем другое.  Там речь шла о шаблонах классах, которых на тот момент даже ещё не было в MQL.  Видимо тот человек был такой же, как Комбинатор, прилетевший из будущего :)   А даже если б и сейчас делать с шаблонами класса, то всё-равно ничего не выйдет, ибо их специализация не поддерживается

Только не понимаю, почему компилятор не ругается.

Я в прошлом сообщении в структуре A поставил static не в том месте. Исправил.

Шаблоны улучшать в данном случае - видится лишним. Нужно просто приоритеты компилятору учитывать. Если явно задан тип в описании функции - вызывать ее. Нет - шаблонный вариант.

 Это по сути и есть та же специализация.

 
Значит, вариант со switch рабочий, хоть и тормозной.
Причина обращения: