Подтвердить что ты не робот

Перегрузка оператора С++: неизвестное преобразование из объекта в ссылку?

Когда я пытаюсь скомпилировать следующее (g++ 4.6.3)

class A {};

A& operator*=( A& a, const A& b )
{
  return a;
}

A operator*( const A& a, const A& b )
{
  return A( a ) *= b;
}

int main( int, char*[] )
{
  A a, b;

  a = a*b;

  return 0;
}

Я получаю сообщение об ошибке

/tmp/test.cxx: In function ‘A operator*(const A&, const A&)’:
/tmp/test.cxx:14:20: error: no match for ‘operator*=’ in ‘(* & a) *= b’
/tmp/test.cxx:14:20: note: candidate is:
/tmp/test.cxx:6:1: note: A& operator*=(A&, const A&)
/tmp/test.cxx:6:1: note:   no known conversion for argument 1 from ‘A’ to ‘A&’

Это меня озадачивает - как можно не знать преобразование из класса в ссылку на этот класс?

Изменение объявления класса A следующим образом не имеет никакого эффекта:

class A
{
public:
  A() {}
  A( const A& ) {}
};

Те же ошибки.

Я был бы чрезвычайно благодарен за подсказки относительно того, что происходит здесь.

4b9b3361

Ответ 1

Как сказал Лукиан, вы не можете привязать временный объект к неконстантной ссылке. Ожидание компилятора заключается в том, что объект перестанет существовать после выражения, поэтому нет смысла его модифицировать.

Чтобы исправить ваш код, удалите временное (сделать аргумент const& не имеет смысла в operator *=):

A operator*(A a, const A& b)
{
    return a *= b;
}

Ответ 2

Когда вы пишете A( a ), вы создаете временный тип A (rvalue), который вы копируете-конструкцию с a. С++ утверждает, что значение rvalue не может быть передано как не const-ссылка. Visual Studio немного небрежно об этом правиле, но gcc и т.п. Применяют его.

Чтобы исправить, попробуйте это (это точно то же самое, но вы создаете lvalue, называя эту переменную). Подробнее о l- и r-value здесь

A operator*( A a, const A& b )
{
   return a *= b;
}