c ++ 14 — C ++ Назначить неявно преобразованному lvalue

Рассмотрим этот фрагмент кода C ++:

struct Foo {
float value;

operator float& () {
return this->value;
}
};

int main() {
Foo foo;
foo=1.0f;   //Doesn't compile, foo isn't implicitly converted to a float&

return 0;
}

Почему это не компилируется? Есть ли конкретная причина, по которой это не было включено в стандарт C ++? Или эквивалент действительно существует, и я просто использую его неправильно?

13

Решение

Практически для всех других операторов ваш оператор преобразования будет делать именно то, что вы хотите, и он будет продолжать делать именно то, что вы хотите, даже если вы добавите пользовательские операторы.

struct Foo {
float value;
operator float& () { return this->value; }
Foo &operator+=(Foo);
};
int main() {
Foo foo {};
foo+=1.0; // compiles and works
// equivalent to foo.operator float&()+=1.0;
}

Тем не мение, = особенный, правила для = отличаются по сравнению с большинством других операторов. Как установлено Т.С .:

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

4 Для встроенных операторов присваивания преобразования левого операнда ограничены следующим образом:
(4.1) — не вводятся временные символы для удержания левого операнда, и
(4.2) — пользовательские преобразования не применяются к левому операнду для достижения соответствия типа с крайним левым параметром встроенного кандидата.

Вместе с тем, что любой обычай operator= не может быть определена как глобальная функция, это гарантирует, что foo=bar; где foo это тип класса всегда означает foo.operator=(bar);, ничего больше.

Тот факт, что этот один оператор выделен, не объясняет причину, но дает понять, что это преднамеренное решение, и убедиться, что foo=bar; всегда значит foo.operator=(bar);Ничто иное, само по себе уже не кажется веской причиной.

7

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

Неявное преобразование выполняется только в следующих случаях:

Неявные преобразования выполняются всякий раз, когда выражение какого-либо типа
T1 используется в контексте, который не принимает этот тип, но принимает некоторые
другой тип T2; особенно:

  • когда выражение используется в качестве аргумента при вызове функции, объявленной с параметром T2;
  • когда выражение используется в качестве операнда с оператором, который ожидает T2;
  • при инициализации нового объекта типа T2, включая инструкцию return в функции, возвращающей T2;
  • когда выражение используется в операторе switch (T2 является целочисленным типом);
  • когда выражение используется в операторе if или цикле (T2 — bool).

Ни один из них не имеет место здесь. Вместо этого компилятор пытается найти подходящий operator= работать с double, Чтобы получить эту компиляцию, вам нужно перегрузить этот оператор (вы на самом деле хотите float как видно из кода):

Foo& operator=(float other)
{
value = f;
return *this;
}

И измените свое назначение на foo = 1.0f;

Ваша функция преобразования будет работать, например:

float f = foo;
6

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector