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

 
Alain Verleyen #:

Вы должны быть честными с приоритетом.

Задача была доказать, что && не равносильно operator && (|| не равносильно  operator||) - здесь и далее - речь о перегруженных операторах в разной записи

class A {
public:
    A() {}     A(const A&) {}
    A operator&&(const A&) { Print(3); return this; }
    A operator||(const A&) { Print(4); return this; }
    A operator88(const A&) { Print(3); return this; }
    A operator11(const A&) { Print(4); return this; }
};
A f( int i ) { Print( i ); return A(); }
void OnStart()
{                                           //Результат:
    f(1)         || f(2)          && f(5);  //5-2-3-1-4
    f(1).operator||(f(2)).operator&&(f(5)); //5-2-1-4-3
    f(1).operator11(f(2)).operator88(f(5)); //5-2-1-4-3
}

operator&& ведет себя не как &&, а как функция operator88

А то, что свою роль в этом сыграл приоритет - так это только усиливает доказательство - причина не важна, важен результат. По крайней мере Вы признали, что приоритет все-таки действует на && и не действует на operator&&

Если бы && (||) была бы обычной функцией, то результат был бы одинаковым, а он - разный

А если приоритет сохранился, то почему остальное не может сохранится (кроме ленивости конечно - она принципиально невозможна)

Опять же - не на пустом месте это отменили (until C++17)
 
Alain Verleyen #:

Вы должны быть честными с приоритетом.

Для полноты доказательства, что перегруженный оператор не равносилен методу\функции - возьмем операторы с одинаковым приоритетом:

class A {
public:
    A() {}     A(const A&) {}
    A operator+=(const A&) { Print(3); return this; }
    A operator-=(const A&) { Print(4); return this; }
};
A f( int i ) { Print( i ); return A(); }
void OnStart()
{                                           //Результат:
    f(1)         += f(2)          -= f(5);  //5-2-4-1-3
    f(1).operator+=(f(2)).operator-=(f(5)); //5-2-1-3-4
}
Результат все-равно - разный. Доказательство завершено!
 
A100 # :

Для полноты доказательства, что перегруженный оператор не равносилен методу\функции - возьмем операторы с одинаковым приоритетом:

Результат все-равно - разный. Доказательство завершено!

Доказательство чего? Проверьте, что это дает на C++!

А вы продолжаете сравнивать то, что не сравнимо!

    f(1)         += f(2)         -= f(5);   //5-2-4-1-3   Evaluated from right to left
    f(1).operator+=(f(2).operator-=(f(5))); //5-2-4-1-3   Evaluated from left to right as functions, it needs correct ()

Это лишь доказывает, что порядок последовательности не определен и на него не следует полагаться.

 
fxsaber #:

Утверждаете, что эти два оператора не являются завуалированными методами? Где почитать про это?

https://en.cppreference.com/w/cpp/language/operators

Welcome)))

 
Alain Verleyen #:

Доказательство чего? Проверьте, что это дает на C++!

А вы продолжаете сравнивать то, что не сравнимо!

Это лишь доказывает, что порядок последовательности не определен и на него не следует полагаться.

Доказательство того, что выделено фиолетовым в Википедии: перегрузка операторов не меняет их приоритет и ассоциативность

На С++ результат как выяснилось зависит от компилятора этот получен на C++20 Shell 

 
Ошибка при выполнении:
//Test2.mq5
#property library
    void f2(       string ) export {}
//Test.mq5
#import "Test2.ex5"
    void f2( const string = "2" );
#import
    void f1(       string )        {}
    void f1( const string = "1" );
void OnStart()
{
    f1(); //(1)//нормально
    f2(); //(2)//Error: cannot find 'f2' in 'Test2.ex5'
}

А какая принципиальная разница между (1) и (2) ?

 

Кончайте уже причиндаламаи меряться)))

https://en.cppreference.com/w/cpp/language/operator_precedence

https://en.cppreference.com/w/cpp/language/operators

https://en.cppreference.com/w/cpp/language/eval_order

Вот вам для изучения, погружайтесь в неведомое))) Там хардкор, Будапешт отдыхает)))

PS/ В С++ нельзя полагаться на тест поведения, сделанный на компиляторе. Даже если все компиляторы, доступные вам показали идентичное поведение. А потом, вы, решив супер-пупер ускорить свой код, засунули его в, например,  icc с ключом /Oipo и сильно прихренели от изменившегося поведения (а вот это уже из реального опыта, после этого всем коллективом, пару-тройку недель, выпиливали UB из десятилетнего легаси, пока не добились детерминированного результата).

PSS. И я не просто так всегда топлю за недопустимость вот такого:

union U
{
    uint64_t a;
    double b;
};

void Foo(double a)
{
    // Do something
}

int main()
{
    U a;
    uint64_t b = 100500;
    a.a = 100500;
    Foo(a.b);
    Foo(reinterpret_cast<double&>(b));
}

,хотя прекрасно знаю, что и msvs и gcc абсолютно ожидаемо это обрабатывают, вот только с точки зрения стандарта С++, в обоих случаях UB. Кстати, в случае с С, фишка с union законна.

 
  • &&,  ||, and  , (comma) lose their special sequencing properties when overloaded and behave like regular function calls even when they are used without function-call notation.  (until C++17)

До C++17 operatator&& - обычный метод. 

 
fxsaber #:

До C++17 operatator&& - обычный метод. 

Обрати внимание на это

  • The overloads of operators  && and  || lose short-circuit evaluation.

В любом случае будут оценены оба операнда. То, что ты написал, это как раз в тему к А100, каюсь, не заметил. Да, начиная после c++17 при перегрузке перестает теряться

Every value computation and side effect of the first (left) argument of the built-in logical AND operator &&, the built-in logical OR operator || and the built-in comma operator , is sequenced before every value computation and side effect of the second (right) argument.

Это значит, что стандарт гарантирует последовательность оценки операндов. В нашем случае сначала должно вызываться f(1) и только потом f(2).

PS Я же говорю, Будапешт отдыхает)))

 
Vladimir Simakov #:

всем коллективом, пару-тройку недель, выпиливали UB из десятилетнего легаси, пока не добились детерминированного результата.

В свежей библиотеке написал такое.
  static string Merge_INPUT_STRUCT( const string &Str, const string &Str2[] )
  {
    const int Size = ::ArraySize(Str2);

    string Res = Size ? Str2[0] : NULL;

    if (Size)
      for (int i = 1, Pos = ::StringLen(Str2[0]); i < Size; Pos += ::StringLen(Str2[i++]))
      {
        Pos = ::StringFind(Str, Str2[i], Pos);

        Res += ::StringSubstr(Str, Pos - 1, 1) + Str2[i];
      }

    return(Res);
  }

Это UB?

Причина обращения: