Почему myClassObj ++++ не вызывает ошибку компиляции: для '++' требуется l-значение, как для типа buildin? - PullRequest
8 голосов
/ 14 июля 2011

Почему myint ++++ прекрасно компилируется с компилятором VS2008 и компилятором gcc 3.42 ??Я ожидал, что компилятор скажет, что нужно lvalue, пример см. Ниже.

struct MyInt
{
    MyInt(int i):m_i(i){}

    MyInt& operator++() //return reference,  return a lvalue
    {
        m_i += 1;
        return *this;
    }

    //operator++ need it's operand to be a modifiable lvalue
    MyInt operator++(int)//return a copy,  return a rvalue
    {
        MyInt tem(*this);
        ++(*this);
        return tem;
    }

    int     m_i;
};

int main()
{
    //control: the buildin type int
    int i(0);
    ++++i;  //compile ok
    //i++++; //compile error :'++' needs l-value, this is expected

    //compare 
    MyInt  myint(1);
    ++++myint;//compile ok
    myint++++;//expecting compiler say need lvalue , but compiled fine !? why ??
}

Ответы [ 6 ]

8 голосов
/ 14 июля 2011

Нет, перегруженные операторы не являются операторами - они являются функциями.Таким образом, GCC правильно принимает:

myobj++++; эквивалентно myobj.operator++(0).operator++(0); Вызов функции-члена (включая перегруженный оператор) для временного объекта типа класса разрешен.

3 голосов
/ 14 июля 2011

Поскольку для пользовательских типов перегрузки операторов в буквальном смысле являются просто вызовами функций и поэтому подчиняются семантике вызовов функций.

2 голосов
/ 14 июля 2011

Если вы хотите эмулировать встроенное поведение, на самом деле есть очень простое решение: сделать возвращаемое значение const:

MyInt const operator++(int) { … }

Несколько лет назад велись споры о том, определен ли пользовательоператоры должны точно моделировать встроенное поведение.Я не уверен, какая школа мысли в настоящее время имеет преимущество, но способ возврата operator++(int) const был способом достижения этого.

1 голос
/ 14 июля 2011

Проблема в том, что требования оператора постинкремента для целочисленных типов и для пользовательских типов различаются.В частности, определенный пользователем постинкрементный оператор, реализованный как функция-член, позволяет использовать значения r.

Если вы реализовали оператор как свободную функцию:

MyInt operator++(MyInt [const][&] x, int)

Тогда требования этого конкретногооператор будет извлечен из фактической подписи.Если первый аргумент принимается значением, то он принимает rvalues ​​напрямую, если он принимает аргумент const &, тогда он принимает rvalues, если конструктор копирования доступен, если аргумент принимается не константным &, тогда этот оператор будеттребовать lvalues.

1 голос
/ 14 июля 2011

myint ++ возвращает что-то похожее на MyInt (2).Итак, это похоже на выполнение MyInt (2) ++.Временный класс создается в функции operator ++, и вы увеличиваете временный класс.После того, как он возвращен, он удаляется, как только заканчивается следующий оператор (здесь это второй оператор ++).

1 голос
/ 14 июля 2011

В конце концов, MyInt::operator++(int) - это просто еще один метод. Применяются те же правила. Поскольку вы можете вызывать методы для rvalues, вы можете вызывать operator++(int) для rvalues.

...