Почему преобразование не работает с пользовательскими операторами в C ++? - PullRequest
4 голосов
/ 29 января 2012

Рассмотрим следующий код:

class C {
  public:
    int operator-(int x) {
        return 3-x;
    }
};

class wrapper {
  public:
    operator C() {
        static C z;
        return z;
    }
} wrap;

int main() {
    return wrap-3;
}

выдает эту ошибку на g ++:

test.cpp: In function ‘int main()’:
test.cpp:17:17: error: no match for ‘operator-’ in ‘wrap - 3’

Оператор преобразования работает, потому что эта версия работает:

class wrapper {
  public:
    operator int() {
        static int z=3;
        return z--;
    }
} wrap;

int main() {
    return wrap-3;
}

operator- также, кажется, работает, потому что этот код компилируется:

class C {
  public:
    int operator-(int x) {
        return 3-x;
    }
};

int main() {
    C c
    return c-3;
}

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

Ответы [ 3 ]

5 голосов
/ 29 января 2012

Неявные преобразования не выполняются для первого операнда при сопоставлении функции-члена.Просто сделайте ваш оператор не членом, возможно, другом:

class C {
};

int operator-(C c, int x) {
    return 3-x;
}

From [over.match.oper]:

- Если T1 является полным типом класса,набор кандидатов в члены является результатом квалифицированного поиска T1::operator@ (13.3.1.1.1);в противном случае набор кандидатов в члены является пустым.

1 голос
/ 29 января 2012

Он не компилируется (используя GCC), потому что он должен соединить два пользовательских преобразования, чтобы получить от wrapper до int: сначала в C, затем до int. Стандарт этого не допускает. См. ответ Дэвида Родригеса в другой ветке .

0 голосов
/ 29 января 2012

Когда вы вернетесь Wrap-3; компилятор не знает, чтобы преобразовать оболочку в C для того, чтобы для выполнения расчета он ищет оператора в оболочке или преобразование в оболочку в числовой тип. Только потому, что у С есть оператор, компилятор неявно преобразует в него, вы можете иметь несколько операторов преобразования в оболочке, какой компилятор должен конвертировать в?

Либо в явном виде скажите компилятору преобразовать в C, либо добавьте оператор-обертку следующим образом.

class wrapper {
  public:
    operator C() {
        static C z;
        return z;
    }

    int operator-(int x) {
        return C()-x;
    }
} wrap;
...