ошибка: требуется lvalue при перегрузке оператора ++ / - и т. д. - PullRequest
2 голосов
/ 19 апреля 2011

Я перенес свой код в компилятор Ubuntu 4.4.1 g ++. При перегрузке operator ++ (int), как показано ниже, выдает ошибку для (T*), но отлично работает для (T*&). В моей более ранней версии (linux-64, но не помню точную версию) она работала нормально и с (T*).

Любая причина, , почему ?

template<typename T>
struct Wrap
{
  void *p;  // Actually 'p' comes from a non-template base class
  Wrap<T>& operator ++ ()
  {
    ((T*)p) ++;  // throws error; if changed to (T*&) then ok!
    return *this;
  }
// ...
};
int main ()
{
  Wrap<int> c;
  ++c;  // calling prefix increment
}

Ответы [ 2 ]

2 голосов
/ 19 апреля 2011

Результатом приведения типа не является lvalue, поэтому его нельзя присваивать, а (встроенный) ++ является формой присваивания.Это была ошибка в компиляторе, если он когда-либо работал.

Со ссылкой он компилируется (в действительности это то же самое, что и *(T**)&p), но из-за правил наложения имен (компилятор может предполагать, что указатели (и ссылки)разные типы не указывают на один и тот же объект) формально он недействителен, хотя он будет работать на всех известных компиляторах.

Самый простой способ:

p = static_cast<void *>(static_cast<T *>(p) + 1)

(никогда не используйте Cв стиле C ++) и полагаться на то, что компилятор сможет скомпилировать его точно так же, как ++.Однако, если у вас есть аргумент шаблона, доступный при определении указателя (в примере кода, который вы делаете), гораздо лучше просто использовать правильно типизированный указатель (я бы сказал, он также будет работать с указателями на члены, но они не имеют значимого значения).++).

1 голос
/ 19 апреля 2011

Похоже, вы смешиваете свои префиксные и постфиксные приращения подписей.Кроме того, зачем использовать void *, если вы знаете, что ваш тип T?

Соответствующие подписи см. Ниже: http://www.codeguru.com/forum/showthread.php?t=231051

...