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

 
A100:
Что мешает для не имеющих смысла операторов перегрузить их как для объектов или просто не реализовывать?
 

Сейчас так и сделано (перегружено как для объектов) и всё вроде бы устраивает. Но возникает противоречие между имеющими смысл (== и !=) и остальными

class A {
public:
        bool operator ==( A* a ) { Print( __FUNCTION__ ); return ( true  );  }
        bool operator !=( A* a ) { Print( __FUNCTION__ ); return ( true  );  }
//остальные
        bool operator >>( A* a ) { Print( __FUNCTION__ ); return ( true  );  }
        bool operator +( A* a )  { Print( __FUNCTION__ ); return ( false  ); }
        bool operator !()        { Print( __FUNCTION__ ); return ( true   ); }
//... и т.д.
};

поскольку

void OnStart()
{
        A *a = new A;
        if ( a == a ) Print( "1" ); //сравнение указателей как чисел
        if ( a >> a ) Print( "3" ); //вызывается operator<<( A *)
}

Которое предлагаетcя устранить путем сравнения указателей только посредством специальной функции

void OnStart()
{
        A *a = new A;
        if ( isEqualPoiner( a, a ) ) Print( "1" ); //сравнение указателей как чисел
        if ( a == a )               Print( "2" ); //вызывается operator==( A *)
        if ( a >> a )               Print( "3" ); //вызывается operator<<( A *)
}
 

Специальная функция для сравнения указателей может быть оформлена например так

template<typename T1, typename T2>
bool isEqualPointer( T1 *t1, T2 *t2 ) { return ( ulong(t1) == ulong(t2) ); }
 
A100:

У меня к вам нескромный вопрос. А вы делиться своими наработками будете?

Вы один из немногих, кто активно и постоянно использует шаблоны и макросы. И у вас наверное большой объем наработанного кода.

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

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

 

Как я использую шаблоны? - Для сокращения записи. Например в MQL отсутствует операция запятая. Допустим есть запись

int f2( string str )
{
        Print( str );
        return ( 0 );
}

bool f( int a )
{
        if ( a == 5 )
                return ( true )
        f2( "abc" );
        return ( false );
}
тогда имея шаблон
template<typename T1, typename T2>
T2 opComma( T1 expression, T2 assignment_expression ) { return ( assignment_expression ); }

вместо 4-х строк получаем - одну

bool f( int a )
{
        return ( a == 5 ? true : opComma( f2( "abc" ), false ) );
}
 

Как я использую макросы? - опять же - для сокращения записи. Например в MQL отсутствуют шаблоны классов. Не беда - используем макрос

#define Macro( type ) \
class A {       \
public:         \
/*...еще много строк...*/ \
        type a; \
};

//осталось написать
Macro(  uint )
Macro( ulong )
 
Опять же для сокращения записи - определив однажды
#define MDT( dt_struct, dt )     \
        MqlDateTime dt_struct;   \
        ZeroMemory( dt_struct ); \
        TimeToStruct( dt, dt_struct );

впоследствии достаточно будет объявить

datetime dt;
MDT( dt_struct, dt )
 

 Побитовое копирование например реализую через шаблоны, поскольку в нем могут участвовать сразу несколько типов

template<typename T1, typename T2>
T2 BitwiseCopying( T1 type1, T2 )
{
struct Union1 {
        T1      type1;
};
struct Union2 {
        T2      type2;
};
        Union1 union;
        union.type1 = type1;
        return ( ((Union2)union).type2 );
}
void f()
{
        ulong ul = 0x16;
        double d = BitwiseCopying( ul, double(0)); //побитовое копирование из ulong в double
        float f = 36.6;
        uint ui = BitwiseCopying( f,    uint(0));  //побитовое копирование из float в uint

}
 
A100:

Если принять обращение к функциям-членам только через (*a), то это не даст явных преимуществ, а наоборот - приведет к невозможности простого и понятного множественного применения операторов.

попробуйте переписать это с учетом Вашего предложения

А вместо указателя использовать сам объект нельзя, поскольку operator <<(...) может вернуть только указатель на объект.

Вы вероятно не правильно меня поняли.  Я же не говорил о том, чтобы запретить текущую реализацию.  Я просил сделать дополнительную возможность взятия ссылки либо указателя на объект, дабы не зависеть от прихотей компилятора.  А как поступать в каждом конкретном случае - уже сам решу.  Если мне потребуется сверхнадёжная программа, то вполне можно сделать и так, как вы описали.  Да, замороченно. Но зато если потом метаквотсы вдруг введут специальное действие оператора << для указателей, то нам это уже не страшно.

 
meat:

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

Если (b) - объект, то дополнительная возможность (&b) в дополнении к существующей GetPointer( b ) понятна - это приближение синтаксиса к С++.

Если (a) - указатель, то дополнительная возможность (*a) в дополнении к существующей (a) дает наверное разумный компромис

class A {
        bool operator==(A *);
        A *operator<<(A *);
        A *operator>>(A *);
};

void f()
{
        A *a = new A();
        if (  a ==  a ); //сравнение указателей
        if ( *a == *a ); //вызов operator==(A *)
        a << a >> a;     //вызов operator<<(A *) и operator>>(A *)
        *a << *a;        //вызов operator<<(A *)
}
С одной стороны устраняется противоречие, с другой - не нарушается существующий порядок