Предложение - кастинг структур от базовых к производным - страница 3

 
fxsaber:

Формально наследуем структуру от себя же.

нет. не самый конечно удачный пример использования паттерна, но.

это наследование не от себя же, а от чего-то сразу адаптированного к типу. это лаконичное добавление функционала.

 
TheXpert:

нет. не самый конечно удачный пример использования паттерна, но.

это наследование не от себя же, а от чего-то сразу адаптированного к типу. это лаконичное добавление функционала.

Поэтому и написал "формально". Ничего о структуре A неизвестно, но при этом она вовсю используется в базовом классе, от которого и происходит.


Вот пример, работоспособность которого мне непонятна

struct A
{
  int a;
  
  void f() { B obj; obj.b = 0; }
};

struct B : A { int b; };


Здесь ратовали за чтение кода сверху-вниз. Но здесь даже снизу-вверх читая, все равно не ясно, как может в базовом классе появляться объект производного со своими полями?

 

Для простого обнаружения неверного вызова можно так (да, костыль и всё такое)

// comparable.mqh
//#define TCOMPARE_CHECK
#ifdef TCOMPARE_CHECK
   template<typename T>
   struct TComparable { 
      protected: TComparable() {}
      public:    int CompareTo(const T & obj) const { return obj.CompareTo(obj); }
   };
   #define TCOMPARABLE(T, VIS) : VIS TComparable<T>
   template<typename T>
   int Compare(const TComparable<T> &a, const TComparable<T> &b)  {Alert("TCOMPARE_CHECK mode !!!!!!!!!!!"); return 0; }
#else
   #define TCOMPARABLE(T, VIS)
   template<typename T>
   int Compare(const T &a, const T &b)  { return a.CompareTo(b); }
#endif
// end of comparable.mqh


struct A TCOMPARABLE(A, public)
{ 
  double a;
  A(double value) { a=value; }
  int CompareTo(const A & obj) const { return a>obj.a ? 1 : a<obj.a ? -1 : 0; }
};

void OnStart()
{
   //A a=10, b=20;
   int a=10, b=20;
   int result= Compare(a, b);
}

Когда получена ошибка и об отсутствующем члене и непонятно куда копать, делаем дефайн TCOMPARE_CHECK и получаем понятное 'a' - parameter conversion not allowed  в месте вызова с интом.

А вообще игра свеч не стоит по-моему, я бы в мкл использовал обобщёную Compare() и не парился.

 
pavlick_:

Для простого обнаружения неверного вызова можно так (да, костыль и всё такое)

Когда получена ошибка и об отсутствующем члене и непонятно куда копать, делаем дефайн TCOMPARE_CHECK и получаем понятное 'a' - parameter conversion not allowed  в месте вызова с интом.

У меня многие шаблоны изначально через дефайны вызывается, со всевозможными проверками )  Правда далеко не везде получается так делать (например в методах класса).  А уж шаблонные классы - это вообще отдельная песня.  Компилятор в них даже не показывает тип, с которым раскрыт шаблон, в случае ошибки в нём.  Приходится делать дополнительные шаблонные методы внутри класса и переносить код в них,  т.к. там типы отображаются нормально.  В общем MQL - это настоящее испытание стойкости духа )

Кстати, в вашем примере обнаружение будет простым только если переменная не прошла перед этим через цепочку других шаблонов )  Иначе придётся распутывать клубок )   По сути передача безымянного T в шаблоны - это зло.   В C++ с этим можно жить, т.к. во-первых компилятор всегда покажет место вызова, а во-вторых можно делать проверку корректности методами SFINAE.  В MQL же это превращается просто в пытку

 
Alexey Navoykov:
У меня многие шаблоны изначально через дефайны вызывается, со всевозможными проверками )  Правда далеко не везде получается так делать (например в методах класса).  А уж шаблонные классы - это вообще отдельная песня.  Компилятор в них даже не показывает тип, с которым раскрыт шаблон, в случае ошибки в нём.  Приходится делать дополнительные шаблонные методы внутри класса и переносить код в них,  т.к. там типы отображаются нормально.  В общем MQL - это настоящее испытание стойкости духа )

Даже не представляете, насколько хотелось бы увидеть исходник какого-нибудь Вашего проекта. Думаю, было бы очень полезно подсмотреть различные идеи/подходы.

Потому как в отрыве от применения очень сложно понять пользу обсуждаемого.

 
fxsaber:

Сделал рабочим ваш код. Его смысл должен быть известен автору.

"Виртуальный метод своими руками" - в этом смысл.

 
fxsaber:

Даже не представляете, насколько хотелось бы увидеть исходник какого-нибудь Вашего проекта. Думаю, было бы очень полезно подсмотреть различные идеи/подходы.

Потому как в отрыве от применения очень сложно понять пользу обсуждаемого.

Ну вот пример макроса с синтаксической проверкой корректности переменных:

template<typename T1, typename T2>
int __StructCompare(T1& a, T2& b)
{
  char arr1[];  StructToCharArray(a, arr1);
  char arr2[];  StructToCharArray(b, arr2);
  return ArrayCompare(arr1, arr2);
}


#define StructCompare(a, b) (1 ? __StructCompare(a, b) : FileWriteStruct(0, a)+FileWriteStruct(0, b))
 
Alexey Navoykov:

Ну вот пример макроса с синтаксической проверой корректности переменных:

Такой код, наверное, может помочь, когда очень замысловато что-то написано и совсем не очевидно распутать последовательность шаблонов, макросов и специализаций.

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

 
fxsaber:

Такой код, наверное, может помочь, когда очень замысловато что-то написано и совсем не очевидно распутать последовательность шаблонов, макросов и специализаций.

Замысловатость кода - понятие относительное. Причём она обычно пропорциональна давности последнего общения с этим кодом )   Пока работаешь с ним, то помнишь, где что находится и где искать ошибку.  А спустя время - это уже лабиринт.  Особенно если компилятор плохо помогает поисках.

 
Alexey Navoykov:

Замысловатость кода - понятие относительное. Причём она обычно пропорциональна давности последнего общения с этим кодом )   Пока работаешь с ним, то помнишь, где что находится и где искать ошибку.  А спустя время - это уже лабиринт.  Особенно если компилятор плохо помогает поисках.

В общем, от разговоров к делу хорошо бы - что-нибудь в КБ.