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

 
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;       
}
 

Ошибка в документации на сайте:

Вычисления на основе таймсерий текущего таймфрейма

int  OnCalculate(
   const int        rates_total,       // размер входных таймсерий
   const int        prev_calculated,   // количество обработанных баров на предыдущем вызове
   const datetime&  time{},            // массив Time
   const double&    open[],            // массив Open
   const double&    high[],            // массив High
   const double&    low[],             // массив Low
   const double&    close[],           // массив Close
   const long&      tick_volume[],     // массив Tick Volume
   const long&      volume[],          // массив Real Volume
   const int&       spread[]           // массив Spread
   );

Фигурные скобки вместо квадратных.

 

Ребята, подскажите, как при Дебаге автоматом видеть значения всех переменных в функции?

  static TICKET_TYPE VirtualOrderSend( const string Symb, const int Type, const double dVolume, const double Price, const int SlipPage, const double SL, const double TP,
                                       const string comment = NULL, const MAGIC_TYPE magic = 0, const datetime dExpiration = 0, color arrow_color = clrNONE )

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


Современные дебагеры могут такое?

 

И как узнать, что вернула функция?

bool f()
{
  return(true);
} // В этом месте нужно знать, что вернулось true.
 
fxsaber:


И как узнать, что вернула функция?

bool f()
{
  return(true);
} // В этом месте нужно знать, что вернулось true.

А разве можно такие вопросы задавать ???