template<typename T>
class type_wrapper{
T data;
};
template<typename T>
class A{
class type_wrapper : public::type_wrapper<T>{}; // '::' - syntax error
};
voidOnStart()
{
A<int> a;
}
int main(){
OnStart();
return0;
}
Еще один дефект 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];
};
voidOnStart()
{
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 usedprintf("%d\n", sizeof(main_wrapper<A<C>::internal_wrapper<C>>)); // (Bug) 36 //sizeof(main_wrapper<A<int>::internal_wrapper>) is used
}
Спасибо, действительно введение фиктивного шаблонного параметра, в случаи примера, обходит проблему. Однако, что касается глобального проекта то тут все немного сложнее: internal class применялся как альтернатива по отсутствующему typedef typename функционалу с целью упростить как процес разработки так и применения финального класса контейнера. Возможно, стоит подождать исправлений от разработчиков. В крайнем случаи, все зависимости придется тащить наружу, надеясь на отсутствие очередной успешной компиляции с undefined behavior при выполнении.
Подводя итог по internal class функциональности, можно однозначно сказать, что для нормального его использования очень не хватает typedef declaration функциональности, хотя бы ее примитивной формы... Так вместо вполне компактного и понятного кода С++:
Приходится городить забор с #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;
};
voidOnStart()
{
A<int> a;
A<int> b;
A<double> c;
a = b;
//a = c;
}
Вот зашел в такую, нужно видеть значения всех входных параметров автоматом (без ручного добавления каждого). А когда вышел из нее, чтобы они автоматом исчезли из списка слежения (без ручного удаления).
Еще один баг MT5(build 2316) с генерацией кода шаблонного класса при использовании internal class.
С++ online: https://onlinegdb.com/HJkKXAqMU
Еще один дефект MT5(build 2316), связанный с internal class - отсутствие возможности явно сослаться на глобальное пространство имен.
С++ online: https://onlinegdb.com/H14NF05G8
Очень противный баг, блокирующий дальнейшую разработку.
Создаешь сложный несколько раз обернутый объект с внутренним типом "С", а там оказывается совсем другой тип данных, может "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>, такой тип данных и будет далее использоваться во всех объектах, данного шаблона в будущем.
Другой баг с генераций кода шаблонного класса будет предоставлен ниже.
А так правильно?
Спасибо, действительно введение фиктивного шаблонного параметра, в случаи примера, обходит проблему.
Однако, что касается глобального проекта то тут все немного сложнее: internal class применялся как альтернатива по отсутствующему typedef typename функционалу с целью упростить как процес разработки так и применения финального класса контейнера.
Возможно, стоит подождать исправлений от разработчиков.
В крайнем случаи, все зависимости придется тащить наружу, надеясь на отсутствие очередной успешной компиляции с undefined behavior при выполнении.
Подводя итог по internal class функциональности,
можно однозначно сказать, что для нормального его использования очень не хватает typedef declaration функциональности, хотя бы ее примитивной формы...
Так вместо вполне компактного и понятного кода С++:
Приходится городить забор с #define и наследований через internal class:
Проблемы при использовании internal class в качестве typedef declaration:И проблем тут на много больше, чем может показаться на первый взгляд.
Проблемы при использовании #define в качестве typedef declaration:
Для этого разработчики добавили "operator= delete".
Однако видится не логичным разрыв связки delete/default, так как все опять нужно прописывать вручную.
Может что-то делаю не так?
Ошибка в документации на сайте:
Вычисления на основе таймсерий текущего таймфрейма
Фигурные скобки вместо квадратных.
Ребята, подскажите, как при Дебаге автоматом видеть значения всех переменных в функции?
Вот зашел в такую, нужно видеть значения всех входных параметров автоматом (без ручного добавления каждого). А когда вышел из нее, чтобы они автоматом исчезли из списка слежения (без ручного удаления).
Современные дебагеры могут такое?
И как узнать, что вернула функция?
И как узнать, что вернула функция?
А разве можно такие вопросы задавать ???