почему я не могу использовать фиктивный параметр в постфиксном операторе ++, например someClassObject ++ 5? - PullRequest
12 голосов
/ 04 июня 2019

Я знаю, что могу использовать фиктивный int в операторе постфикса ++ как someClassObject.operator++(5), но почему не могу использовать его как someClassObject++5? Я спрашиваю об этом, потому что operator+ можно использовать как someClassObject1 + someClassObject2.

{
public:

    test(int x, string y) : x(x), y(y){}
    test() :x(0), y("") {};

    //skiping some code for copy constructor and assignment operator overload

    test operator++(int x)
    {
        test a(*this);
        a.x += x;
        ++(*this);
        return a;
    }

    friend ostream& operator<<(ostream& ost, const test& test)
    {
        ost << test.x << " , " << test.y;
        return ost;
    }


    int x;
    string y;
};

int main()
{
    test t1(5, "testing");
    int x = 10;
    cout << t1.operator++(x) << endl;
    //the above line of code works but the line below gives error.
    t1++x;
    return 0;
}

Я ожидал, что и t1.operator++(5), и t1++5 будут работать одинаково.

Ответы [ 2 ]

11 голосов
/ 04 июня 2019

Из-за правила максимальный munch выражение

t1++x

равно проанализировано как

t1 ++ x

и сгруппированы как

(t1 ++) x

Это не имеет смысла;скорее как t1 x не имеет смысла.

0 голосов
/ 04 июня 2019

Я знаю, что могу использовать фиктивный int в операторе постфикса ++ в качестве someClassObject.operator ++ (5), но почему не могу использовать его как someClassObject ++ 5?

Потому что стандарт так говорит ™.

Из-за того, как код C ++ анализируется и компилируется, постфиксы ++ и -- работают немного по-другому.

Давайте посмотрим на стандарт C ++ 11 [черновик] .

13.5.1 Унарные операторы [over.unary]

[...] См. 13.5.7 для объяснения постфиксных унарных операторов ++ и --.

Хорошо, поэтому ++ и -- считаются унарными операторами (т.е. принимает один операнд). Что-то вроде 1 ++ 2 подразумевает, что ++ является бинарным оператором (то есть принимает два операнда). Но здесь нет бинарного оператора ++. Оператор postfix ++ должен быть перегружен как один, но на самом деле он не разрешается как единое целое. Давайте вернемся немного назад через стандарт.

13.3.1.2 Операторы в выражениях [over.match.oper]

Если любой из операндов имеет тип, который является классом или перечислением, может быть объявлена ​​пользовательская операторная функция, которая реализует этот оператор , или для преобразования операнда может потребоваться пользовательское преобразование к типу, который подходит для встроенного оператора. В этом случае разрешение перегрузки используется для определения, какую операторную функцию или встроенный оператор следует вызывать для реализации оператора . Поэтому запись оператора сначала преобразуется в эквивалентную запись вызова функции, как показано в таблице 11 (где @ обозначает один из операторов, охватываемых указанным подпунктом).

 Table 11 — Relationship between operator and function call notation 
Subclause  | Expression | As member function | As non-member function
                           [...]
13.5.2     | a@b        | (a).operator@(b)   | operator@ (a, b)
                           [...]
13.5.7     | a@         | (a).operator@(0)   | operator@ (a, 0)

(выделение добавлено)
someClassObject - это класс, и объявлена ​​пользовательская операторная функция (test operator++(int x)), поэтому данный конкретный пункт применим к вашему случаю.

Во-первых, я включил строку с подпунктом 13.5.2, чтобы устранить любые сомнения. §13.5.2 имеет дело с бинарными операторами. Но, как мы установили, в C ++ нет бинарного оператора ++, а единственный постфиксный оператор ++ - унарный. Так что этот ряд не применяется.

Последний ряд более интересен. В соответствии с этим приращение постфикса будет «преобразовано», скажем, с obj++ до obj.operator++(0). Это означает, что int уже пройдено из-за разрешения перегрузки.

Просто для полноты, вот §13.5.7:

13.5.7 [over.inc]

Определяемая пользователем функция с именем operator++ реализует оператор префикса и постфикса ++. Если эта функция является функцией-членом без параметров или не-функцией с одним параметром класса или типа перечисления, она определяет оператор приращения префикса ++ для объектов этого типа. Если функция является функцией-членом с одним параметром (который должен иметь тип int) или функцией, не являющейся членом, с двумя параметрами (второй из которых должен иметь тип int), она определяет оператор приращения постфикса ++ для объектов этого типа. Когда приращение постфикса вызывается в результате использования оператора ++, аргумент int будет иметь значение ноль.


Я спрашиваю об этом, потому что operator+ можно использовать как someClassObject1 + someClassObject2.

+ может быть как унарным, так и двоичным оператором. Вот почему +2 и 1 + 2 являются допустимыми выражениями. Но ++ - унарный оператор (даже если он перегружен как бинарный).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...