Ошибки, баги, вопросы - страница 2639

 
Aleksey Vyazmikin:

А ключ портативного режима не требуется случайно?

Руками запускаются все терминалы? 

Руками, да все запускаются. В итоге, так руками и запускал.

Ключ портативного режима ничего не меняет в этом отношении.

Дело в том, что МТ4 выбрасывает окно авторизации, и запуск программы не считается завершённым.

Надо использовать "start" в пакетном файле.

В общем, получается, разобрался я в этом вопросе.

Спасибо за участие!

 
Petros Shatakhtsyan:

Вы так и не поняли в чем дело, видимо невнимательно читаете мои посты. Мое обращение к разработчикам, а не к вам. Я не нуждаюсь вашим дешевым советам.

Успокойтесь и не надо так волноваться.

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

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

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

Ранее, при работе над MQL проектами, информация о дефектах (багах) предоставлялась в порядке их обнаружения.
Сейчас же решено опробовать новый подход - работа до блокирующего дефекта с последующим предоставлением информации о всех обнаруженных. 
 
#ifdef __cplusplus
   #include <iostream>
#endif 

#define PRINT(x) ; Print(#x, ":", string(x))


template<typename T>
class main_wrapper{
public:
   T data;
};

template<typename T>
class external_wrapper{
public:
   T data;
};

template<typename T>
class A{
public:
   class internal_wrapper : public external_wrapper<T> {};
   
   main_wrapper<internal_wrapper> internal_wrapper_0;
   main_wrapper<external_wrapper<T>> external_wrapper_0;
   
   A(){
        main_wrapper<internal_wrapper> internal_wrapper_1;
        main_wrapper<external_wrapper<T>> external_wrapper_1;
   
        #ifdef __MQL5__
            PRINT(__FUNCSIG__);
            PRINT(typename(internal_wrapper_0.data.data));      // (Bug) int  int
            PRINT(typename(external_wrapper_0.data.data));      // (OK)  int  B*
            PRINT(typename(internal_wrapper_1.data.data));      // (Bug) int  int
            PRINT(typename(external_wrapper_1.data.data));      // (OK)  int  B*
        #endif
   }
};

class B{
   char data[10];
};

class C{
   char data[1000];
};


void OnStart()
{ 
   A<int> val_int;
   A<B*> val_ptr;
   
   printf("%d\n", sizeof(main_wrapper<A<B>::internal_wrapper>));  // (Bug) 36  //sizeof(main_wrapper<A<int>::internal_wrapper>) is used
   printf("%d\n", sizeof(main_wrapper<A<C>::internal_wrapper>));  // (Bug) 36  //sizeof(main_wrapper<A<int>::internal_wrapper>) is used
}

int main(){
   OnStart();
   return 1;
}
Очень противный баг MT5(build 2316), блокирующий дальнейшую разработку.
Создаешь сложный несколько раз обернутый объект с внутренним типом "С", а там оказывается совсем другой тип данных, может "B", может "int", что хочешь...

Убил уйму времени и сил, что бы раскопать и понять, что проблема не в коде, а в работе MQL компилятора. (С++ online: https://onlinegdb.com/H1R1fR5ML)
Предположительно, проблема в работе кеша шаблонного класса "main_wrapper" при генерации кода во время компиляции, когда в качестве параметра передается internal class "internal_wrapper" от шаблонного класса "A" для различных типов данных (int, B*, B, C).
Какой первый тип данных будет создан шаблонным классом "main_wrapper<A<TEMPLATE_TYPE>::internal_wrapper>, такой тип данных и будет далее использоваться во всех объектах, данного шаблона в будущем.


Другой баг с генераций кода шаблонного класса будет предоставлен ниже.
 
class A{
public:
   class B{};
};

template<typename T>
class wrapper{
public:
   T data;
};

template<typename T>
class wrapped_B{
public:
   A::B data;
};
   
void OnStart()
{ 
   A::B a;                // OK
   wrapper<A::B> b0;      // 'B' - unexpected token, probably type is missing?  'data' - semicolon expected     
   
   wrapped_B<A::B> b2;    // OK
   
   class local_B : public A::B{};
   wrapper<local_B> b1;   // OK
}


int main(){
   OnStart();
   return 0;
}

Еще один баг MT5(build 2316) с генерацией кода шаблонного класса при использовании internal class.
С++ online: https://onlinegdb.com/HJkKXAqMU

 
template<typename T>
class type_wrapper{
    T data;
};

template<typename T>
class A{
   class type_wrapper : public ::type_wrapper<T>{}; // '::' - syntax error      
};

void OnStart()
{ 
   A<int> a;
}


int main(){
   OnStart();
   return 0;
}

Еще один дефект MT5(build 2316), связанный с internal class - отсутствие возможности явно сослаться на глобальное пространство имен.
С++ online: https://onlinegdb.com/H14NF05G8

 
Sergey Dzyublik:
Очень противный баг, блокирующий дальнейшую разработку.
Создаешь сложный несколько раз обернутый объект с внутренним типом "С", а там оказывается совсем другой тип данных, может "B", может "int", что хочешь...

Убил уйму времени и сил, что бы раскопать и понять, что проблема не в коде, а в работе MQL компилятора. (С++ online: https://onlinegdb.com/H1R1fR5ML)
Предположительно, проблема в работе кеша шаблонного класса "main_wrapper" при генерации кода во время компиляции, когда в качестве параметра передается internal class "internal_wrapper" от шаблонного класса "A" для различных типов данных (int, B*, B, C).
Какой первый тип данных будет создан шаблонным классом "main_wrapper<A<TEMPLATE_TYPE>::internal_wrapper>, такой тип данных и будет далее использоваться во всех объектах, данного шаблона в будущем.


Другой баг с генераций кода шаблонного класса будет предоставлен ниже.
#ifdef __cplusplus
   #include <iostream>
#endif 

#define PRINT(x) ; Print(#x, ":", string(x))


template<typename T>
class main_wrapper{
public:
   T data;
};

template<typename T>
class external_wrapper{
public:
   T data;
};

template<typename T>
class A{
public:
   template<typename T1>
   class internal_wrapper : public external_wrapper<T1> {};
   
   main_wrapper<internal_wrapper<T>> internal_wrapper_0;
   main_wrapper<external_wrapper<T>> external_wrapper_0;
   
   A(){
        main_wrapper<internal_wrapper<T>> internal_wrapper_1;
        main_wrapper<external_wrapper<T>> external_wrapper_1;
   
        #ifdef __MQL5__
            PRINT(__FUNCSIG__);
            PRINT(typename(internal_wrapper_0.data.data));      // (Bug) int  int
            PRINT(typename(external_wrapper_0.data.data));      // (OK)  int  B*
            PRINT(typename(internal_wrapper_1.data.data));      // (Bug) int  int
            PRINT(typename(external_wrapper_1.data.data));      // (OK)  int  B*
        #endif
   }
};

class B{
   char data[10];
};

class C{
   char data[1000];
};


void OnStart()
{ 
   A<int> val_int;
   A<B*> val_ptr;
   
   printf("%d\n", sizeof(main_wrapper<A<B>::internal_wrapper<B>>));  // (Bug) 36  //sizeof(main_wrapper<A<int>::internal_wrapper>) is used
   printf("%d\n", sizeof(main_wrapper<A<C>::internal_wrapper<C>>));  // (Bug) 36  //sizeof(main_wrapper<A<int>::internal_wrapper>) is used
}
А так правильно?
 
Vladimir Simakov:
А так правильно?

Спасибо, действительно введение фиктивного шаблонного параметра, в случаи примера, обходит проблему.
Однако, что касается глобального проекта то тут все немного сложнее: internal class  применялся как альтернатива по отсутствующему typedef typename функционалу с целью упростить как процес разработки так и применения финального класса контейнера.
Возможно, стоит подождать исправлений от разработчиков.
В крайнем случаи, все зависимости придется тащить наружу, надеясь на отсутствие очередной успешной компиляции с undefined behavior при выполнении. 

 

Подводя итог по  internal class функциональности, 
можно однозначно сказать, что для нормального его использования  очень не хватает typedef declaration функциональности, хотя бы ее примитивной формы...
Так вместо вполне компактного и понятного кода С++:

template <class _Tp, class _Allocator>
class vector
    : private __vector_base<_Tp, _Allocator>
{
private:
    typedef __vector_base<_Tp, _Allocator>           __base;
public:
    typedef vector                                   __self;
    typedef _Tp                                      value_type;
    typedef _Allocator                               allocator_type;
    typedef typename __base::__alloc_traits          __alloc_traits;
    typedef typename __base::reference               reference;
    typedef typename __base::const_reference         const_reference;
    typedef typename __base::size_type               size_type;
..............................


Приходится городить забор с #define и наследований через internal class:

template<typename _Tp, typename _Allocator>
class __vector_base{
public:
   class allocator_type    : public _Allocator{}; 
   
protected:
   #define value_type          _Tp
   #define size_type           DEFAULT_SIZE_TYPE
   #define difference_type     size_type
   
   struct pointer          : public allocator_type::pointer{};
   struct iterator         : public allocator_type::pointer{};
............................

   #undef value_type
   #undef size_type
   #undef difference_type
};


И проблем тут на много больше, чем может показаться на первый взгляд.
Проблемы при использовании #define в качестве typedef declaration:

- нет возможности передать тип используемых данных за пределы класса (простые типы данных вообще ни как не передать);
- нужно постоянно контролировать область действия #define, соответствующей #undef парой 

Проблемы при использовании internal class в качестве typedef declaration:
- можно передать тип используемых данных class/struct за пределы класса (простые типы данных вообще ни как не передать);
- при наследовании теряются все конструкторы, их приходится переписывать вручную по сигнатурам с базового класса;
- если класс, в котором используется typedef declaration имеет базовый класс, то через перекрытие пространств имен нет возможности использовать одно и то же название в качестве typedef declaration;
- классы наследуются от классов, структуры от структур, это нужно постоянно контролировать;
 
Ввиду внедрения дефолных операторов присвоения, возникла потребность запрета случайного выполнения присвоения для базового класса.
Для этого разработчики добавили "operator= delete". 
Однако видится не логичным разрыв связки delete/default, так как все опять нужно прописывать вручную.
Может что-то делаю не так?

class Base{
    char base_data[100];
};

template<typename T>
class A : public Base{
   int data_1;
   int data_2;
   int data_3;
   int data_4;
   int data_5;
   int data_6;
   int data_7;
   int data_8;
   int data_9;
   
   char arr_1[];
   char arr_2[];
public:    
   // MQL
   A* operator=(A &obj){
      data_1 = obj.data_1; 
      data_2 = obj.data_2; 
      data_3 = obj.data_3; 
      data_4 = obj.data_4; 
      data_5 = obj.data_5; 
      data_6 = obj.data_6; 
      data_7 = obj.data_7; 
      data_8 = obj.data_8; 
      data_9 = obj.data_9; 
      
      ArrayCopy(arr_1, obj.arr_1);
      ArrayCopy(arr_2, obj.arr_2); 
      
      (Base)this = obj;
      return &this;
   };
   
   // C++
   // A& operator=(A &) = default;
    
   template<typename TT>
   A* operator=(A<TT> &) = delete;
};

void OnStart()
{ 
   A<int> a;
   A<int> b;
   
   A<double> c;
   
   a = b;      
   //a = c;       
}
Причина обращения: