Проблема перевода с МТ4 на МТ5. Или, точнее, невозможность без'ошибочного исполнения некоторых алгоритмов в МТ5. - страница 10

 
Vict:

Странно, но не додумался раньше сделать:

Избавит от некоторой массы проверок на ошибки, вроде выделения памяти.

не вариант, советник удалится с графика, а нужно лишь "выйти в ОС" до следующего тика из любого места программы


скорее всего можно изящно в макрос все завернуть, чтобы где нужно безопасно вызывать функции связанные с недоступностью данных на текущем тике, вот "болванка"

void OnStart()
  {
   for(int i=0;i<10;i++)
     {
      double o=Open(i);
      if(o>0.0) printf("%d : %f",i,o);
      else
        {
         printf("Error № %d ",(int)o);
         return;
        }
     }
  }
//+------------------------------------------------------------------+

double Open(int shift)
  {
   ResetLastError();
   double result=iOpen(NULL,0,shift);
   int err=GetLastError();
   if(err>0) result=-err;
   return(result);
  }
//+------------------------------------------------------------------+

для читаемости кода хотелось бы просто так писать:

void OnStart()
  {
   for(int i=0;i<10;i++)
     {
      double o=Try( Open(i),"Текст сообщения" );
      printf("%d : %f",i,o);
     }
  }


этот  Try  реально в макрос обернуть  и "выйти в ОС"  в случает неудачи?

 
Igor Makanu:

этот  Try  реально в макрос обернуть  и "выйти в ОС"  в случает неудачи?

#define Try(VAR, EXPR, MES)          \
   VAR = EXPR;                       \
   if (VAR <= 0.0) {                 \
     printf("Error: %s ", MES);      \
     return;                         \
   }

double o;
Try(o, Open(i), "something goes wrong");

Не?

Я всякие минимакросы частенько пишу пряму в начале функции, в конце делаю undefine. Естественно, если действие повторяется часто, иначе бессмысленно.

#define MYERR_HANDLER(INDEX)                                \
{                                                           \
   Alert(__FILE__, " ", __LINE__, "-", INDEX, ": error");   \
   this.state = obst_error;                                 \
   return obev_no_event;                                    \
}

А про аборт вы зря так, при некторых ошибках - идеально.

 
Vict:

Не?

да!

но в идеале хотелось бы вместо:

double o;
Try(o, Open(i), "something goes wrong");

так:

double o = Try(Open(i), "something goes wrong");

не вопрос если нужно сигнатуру функции Open() сделать другой... но в таком виде я получу то что очень уж хотелось бы! ;)

----------------------

PS: как вариант даже глобально описанные переменные Tryerror или bool Tryresult устроили бы - цель одной строкой "безопасный вызов", если этот вызов завершился с ошибкой выйти из тела OnTick()

 
Igor Makanu:

так:

Сомневаюсь, что так можно, даже в плюсах (можно кинуть исключение, но return вряд ли). Но всякое бывает, может кто удивит ...

 

Ну так, навскидку:

Try(double, o, Open(i), "something goes wrong");

наверное это максимум в данной ситуации.

 

Совсем туплю, можно ведь

double Try_helper;
#define Try(EXPR, MES)               \
   Try_helper = EXPR;                \
   if (Try_helper <= 0.0) {          \
     printf("Error: %s ", MES);      \
     return;                         \
   }

double o = Try(Open(i), "something goes wrong");

Не компилировал, но должно работать.

 
Vict:

Совсем туплю, можно ведь

Не компилировал, но должно работать.

Шайтан - машина!!! Заработало!!!

проверил и смоделировал ошибку ( shift>5 )

double Try_helper;
#define Try(EXPR, MES)               \
   Try_helper = EXPR;                \
   if (Try_helper <= 0.0) {          \
     printf("Error: %s ", MES);      \
     return;                         \
   }

void OnStart()
  {
   for(int i=0;i<10;i++)
     {
      
      double o = Try(Open(i), "something goes wrong");
      printf("%d : %f",i,o);
     }
  }
//+------------------------------------------------------------------+

double Open(int shift)
  {
   ResetLastError();
   double result=iOpen(NULL,0,shift);
   int err=GetLastError()>0;
   if(err>0) result=-err;
   if(shift>5) result = -999;
   return(result);
  }
//+------------------------------------------------------------------+

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 0 : 1.115010

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 1 : 1.114670

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 2 : 1.114590

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 3 : 1.114400

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 4 : 1.115240

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 5 : 1.115450

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) Error: something goes wrong 


Круто! а код макроса то реально простым оказался


СПАСИБО! - однозначно Вы волшебник!  ;)

 

Пожалуйста, пользуйтесь на здоровье.

Макрос выше обладает одним минусом - тип хелпера жёстко зашит, нельзя передать в Try функцию возвращающую string, а потом double не создвая двух макросов. У меня возник спортивный интерес - а как это обойти (написать один макрос для любых типов. В мкл без вариантов, в c++, хотя там это и не очень надо, но всё же)? Никто не желает предложить свой вариант (ну ведь надо поддерживать себя в форме)?

 
Vict:

Пожалуйста, пользуйтесь на здоровье.

Макрос выше обладает одним минусом - тип хелпера жёстко зашит, нельзя передать в Try функцию возвращающую string

почему нельзя? знак + никто не отменял!

сейчас так Ваш макрос причесал, как планирую юзать:

int    _GetLastError;
double _Try_helper;
string _Try_FUNCSIG;
#define Try(FUNC,MSG, EXCEPT) _Try_helper=FUNC;if(_GetLastError>0){printf("%s : error № %d %s ",_Try_FUNCSIG,_GetLastError,MSG);EXCEPT;}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   for(int i=0;i<10;i++)
     {

      double o = Try(Open(i), "something goes wrong"+Txt(),return);
      printf("%d : %f",i,o);
     }
  }
//+------------------------------------------------------------------+

double Open(int shift)
  {
   _Try_FUNCSIG=__FUNCSIG__;
   ResetLastError();
   double result=iOpen(NULL,0,shift);
   _GetLastError=GetLastError();
   if(shift>5)_GetLastError=999;
   return(result);
  }
//+------------------------------------------------------------------+
string Txt()
{
return(" Txt ");

теперь параметр макроса EXCEPT - это действие по исключению, прекрасно работает как return так и просто ; - если решил распринтовать в лог, но не выходить из тела OnTick()

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 0 : 1.113350

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 1 : 1.114180

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 2 : 1.115110

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 3 : 1.115010

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 4 : 1.114670

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 5 : 1.114590

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) double Open(int) : error № 999 something goes wrong Txt  

 
Igor Makanu:

Ну я о том, чтобы вот так заюзать:

string f(int) {return "hello world";}
double f(double) {return 35;}

int main()
{
   double d = Try(f(0.), "double error");
   string s = Try(f(0), "stirng error");
   cout << s << "-" << d << endl;  // hello world-35
   return 0;
}

Что-то народ здесь не азартный. Ну да ладно

template <typename T> T Try_helper;
#define Try(EXPR, MES)                                  \
   Try_helper<decltype(EXPR)> = EXPR;                   \
   if (Try_helper<decltype(EXPR)> == decltype(EXPR){}) {\
      printf("%s\n", MES);                              \
      return 1;                                         \
   }
Причина обращения: