Баг компилятора при параметре шаблона = void* - страница 6

 
Alexey Navoykov:

Да всё нормально работает, чего вы выдумываете:

В логе получаем:

void A::~A()
void B::~B()

И чего я вообще повёлся на это...

Ну тогда извиняюсь, не знал что так можно, МКЛ сильно не C++. В плюсах удаление void* это UB.

 

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

Новая версия платформы MetaTrader 5 build 1930: Плавающие окна графиков и .Net библиотеки в MQL5

Alexey Navoykov, 2018.12.15 02:44

Уважаемые разработчики. Ранее в одной из веток обсуждалась недоработка компилятора, допускающая неявный кастинг базового класса к производному, но видимо это осталось незамеченным вами.  Это серьёзная проблема, затрудняющая контроль ошибок и становящаяся постоянной головной болью при активном использовании ООП.  Такой кастинг должен быть только явным.  Это общее правило и в С++, и в C#.

class A {  };

class B : public A { };

A* a = new A;

B* b = a;  // Нет ошибки компиляции!

void f(B*) {  }

void OnInit()
{ 
  f(a);  // Нет ошибки компиляции!
}  

А здесь как быть?

class A {  };

class B : public A { };

A* a = new A;

void* v = a;

B* b = v;  // Нет ошибки компиляции!


Такое поведение тоже считать ошибкой?

 
Alexey Navoykov:

Если стилизатор делает из удобочитаемого кода трудночитаемый - может ну его нафиг такой стилизатор?

Как по мне, стилизатор хорош только тогда, когда ВСЕ его правила можно гибко настроить под себя.

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

 
fxsaber:
Про доп. скобки
((A*)(b.GetPtr())).f(); // Доп. скобки, чтобы подчеркнуть, что именно имелось в виду, не полагаясь на приоритеты.

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

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

 
Alexey Navoykov:

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

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

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

А для самоконтроля во время написания. Нафиг мне при написании в щекотливом месте полагаться на чьи-то приоритеты, еще и осознавая, что пишется кроссплатформенный код (и не обязательно только MT4/5), могущий переноситься на другие языки? Доп. скобки полностью исключили влияние приоритетов языка. Все становится абсолютно однозначно. Благодаря этому появляется 100% надежность, что в этом месте ничего не поломается после очередного билда.


Более того, когда буду читать этот скобочный ад, то буду вынужден потратить время на абсолютное понимание того, что точно имел в виду здесь. И насчет наглядности

bool a = (1 < 2) && (3 < 4);
bool b = 1 < 2 && 3 < 4;

спросим, какой из вариантов нагляднее?

 
fxsaber:

Такое поведение тоже считать ошибкой?

Конечно. Это то же самое.

Вот и получается, что там где реально возможна проблема и нужны как минимум предупреждения (а вообще ошибка компиляции), то ничего не выдаётся.  Зато с навязыванием скобочек они предупреждений не жалеют )  А некоторые тут предлагают даже запретить компиляцию без скобочек, да ещё и подзатыльниками угрожают )  Вот так и живём...

 
Alexey Navoykov:

Конечно. Это то же самое.

Вот и получается, что там где реально возможна проблема и нужны как минимум предупреждения (а вообще ошибка компиляции), то ничего не выдаётся.  Зато с навязыванием скобочек они предупреждений не жалеют )  А некоторые тут предлагают даже запретить компиляцию без скобочек, да ещё и подзатыльниками угрожают )  Вот так и живём...

Так все таки и Вам нужны предупреждения? Что за двойные стандарты: в обоих местах поведение однозначное, но со скобками Вы против предупреждений, а здесь - ЗА?

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

Так под кого из нас подстраивать правила выноса предупреждений?

 
Ilya Malev:

Про StringConcatenate не знал, жаль что в МТ5 её переделали и без string s уже не использовать. А на четверке заметно быстрее StringFormat выходит

Да и вообще почему-то в пятерке эта операция "опрощения" указателя через строку почти вдвое медленнее, хотя в основном там все работает быстрее, иногда на порядок

возможно что StringConcatenate() почему то 32 разрядная, фиг его знает, разработчики уже писали, что Метаэтиторы, что в 5, что в 4-ке одинаковые, может из за совместимости "обернули"

можете еще с dynamic_cast< > поэкспериментировать, я вчера пробовал Вашу задачку решить, но проблема, что MQL не дает указатели разыменовать, можно получить указатель через  dynamic_cast<C_myclass >( func( ) )  на функцию в конкретном методе класса тем самым вызвав ее, можно через  dynamic_cast< > получить указатель на класс, но что делать с таким указателем? - можно переприсвоить void *ptr , но смысла нет, все равно разыменовать нельзя указатель 

 
pavlick_:

Если хочется отправить на свалку CArayObject, то нужно сделать обвертку (вроде такой https://www.mql5.com/ru/forum/170952/page110#comment_9894796) над базовым классом и помещать их в массив (возможно ваш), но тогда уже вам void* не понадобится.

Я не против void*, он нужен, но в другом качестве.

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

Кстати, Вы похоже не в курсе, что if(p) delete p не тождественно в mql "если ссылка указывает на существующий динамический объект, удалить его"

class A{};

void OnStart()
 {
  A *a=new A;
  if(a) Print("Кукареку!");
  if(CheckPointer(a)==POINTER_DYNAMIC) Print("Динамический объект существует и может быть удален");
  else                                 Print("Объект не существует, либо он автоматический");
  delete a;
  if(a) Print("Кукареку!");
  if(CheckPointer(a)==POINTER_DYNAMIC) Print("Динамический объект существует и может быть удален");
  else                                 Print("Объект не существует, либо он автоматический");
 }
 
fxsaber:

И насчет наглядности

спросим, какой из вариантов нагляднее?

Ну если вам так отформатировал стилизатор:

1 < 2 && 3 < 4;

то, повторюсь, все вопросы к этому стилизатору. Так что незачем валить с больной головы на здоровую.  Я бы никогда так не оформил у себя в коде.  А сделал бы так:

1<2 && 3<4
либо
1 < 2  &&  3 < 4
Причина обращения: