Оператор отрицания и сравнение

Давайте возьмем несколько примеров кода:

! 4 > 0;

Из стандарта C ++ мы знаем, что сначала будет выполнено отрицание, чем сравнение. Но если мы немного расширим этот пример:

#include <iostream>

class Test
{
public:
bool operator!() const
{
std::cout << "operator!" << std::endl;
return false;
}

bool operator>(const int &) const
{
std::cout << "operator>" << std::endl;
return false;
}
};int main(int argc, char * argv[])
{
Test t;
std::cout << "t > 0;" << std::endl;
t > 0;
std::cout << "! t > 0;" << std::endl;
! t > 0;
std::cout << "!t.operator>(0)" << std::endl;
! t.operator>(0);

return 0;
}

Выход этой программы будет:

t > 0;
operator>
! t > 0;
operator!
!t.operator>(0)
operator>
  1. Первый звонок (контрольный звонок) вполне понятен. Мы проверяем, вызван ли нужный нам оператор.
  2. Второй звонок является доказательством того, что я сказал первым. сначала вызывается оператор отрицания, а затем по результату (bool) оператор>.
  3. Третий звонок — вот что меня беспокоит.

И тут всплывает мой вопрос. Зачем SomeObjInstance > 0 звонок отличается от SomeObjInstance.operator>(0), Я знаю, что не принято вызывать операторов вторым способом (в качестве участников), но почему эти вызовы отличаются? Я всегда так думал SomeObjInstance > 0 переводится под капотом на членский вызов SomeObjInstance.operator>(0) или вызов функции bool operator>(const Test &, int) если член оператора нет.

Где это поведение описано в стандарте C ++, или, может быть, это какое-то неопределенное поведение?

3

Решение

Оператор членского доступа .* имеет более высокий приоритет, чем оператор отрицания !,

Где это поведение описано в стандарте C ++, или, может быть, это какое-то неопределенное поведение?

Скорее всего, это соответствующий пункт:

13.5 Перегруженные операторы [over.oper]

5) операторские функции обычно не вызываются напрямую; вместо этого они вызываются для оценки операторов, которые они реализуют (13.5.1 — 13.5.7). Однако их можно вызывать явно, используя идентификатор оператора-функции в качестве имени функции в синтаксисе вызова функции (5.2.2).

В вашем первом примере t > 0; он будет использовать соответствующий оператор с приоритетом для операторов реляционного сравнения. Тем не менее, в вашей второй версии t.operator>(0) Вы используете это как вызов функции. Тем самым Test::operator> используется в качестве функции-члена, что приведет к описанному вами поведению, поскольку оно теряет свои операторские характеристики («однако их можно вызывать явно, используя идентификатор оператора-функции в качестве имени функции в синтаксисе вызова функции»).

Смотрите также:

6

Другие решения

Просто на минуту наденьте шляпу компилятора. Вам необходимо проанализировать и оценить выражение в соответствии с четким набором правил (включая приоритет оператора). Тот факт, что оценка включает в себя вызов функции-члена ( operator>() ), который также был бы вызван, если бы выражение использовало оператор > — И что? Вы хотите сделать специальный случай и предположить, что в этом случае приоритет по умолчанию должен быть изменен? И как далеко вы готовы пойти с этим? Например. если этот метод вызывается косвенно или указателем на функцию? Я думаю, что это усложнит логику компилятора и все же позволит привести не интуитивные примеры, аналогичные вашему первоначальному вопросу.

2

. а также () иметь более высокий приоритет, чем !, Синтаксис оператора анализируется как

(!t) > 0;

в то время как явный вызов анализируется как

!((t.operator>)())
1
По вопросам рекламы [email protected]