Когда объект не может быть преобразован в ссылку? - PullRequest
7 голосов
/ 15 января 2009

Я хочу скомпилировать следующую строку кода из http://code.google.com/p/enhsim:

enh::eout << enh::setw(26);

gcc выдает следующую ошибку:

error: no match for 'operator<<' in 'enh::eout << enh::setw(26)'

Но класс EnhSimOutput (экземпляром которого является enh::eout) объявляет:

EnhSimOutput& operator<< (setw& p);

Эта проблема исчезнет, ​​если я реализую версию операции, которая принимает объект по значению:

EnhSimOutput& operator<< (setw p);

или, если я создаю объект enh::setw как локальный, т. Е .:

enh::setw wValue(26);
enh::eout << wValue;

У меня такой вопрос: почему gcc не выбирает версию оператора «по ссылке» для начала?

Разработчики, написавшие этот код, явно сделали его компиляцией, но по умолчанию gcc отказывается это делать. Почему существует разница между объектом, объявленным отдельно как локальная переменная, и локально созданным встроенным?

Ответы [ 2 ]

13 голосов
/ 15 января 2009

Значение enh::setw(26); является значением r . На самом деле, временные подобные люди - это ценности. R-значения имеют особые свойства. Одна из них заключается в том, что их адрес не может быть получен (&enh::setw(26); является недопустимым), и они обычно не могут связываться со ссылками на неконстантные (некоторые временные могут связываться со ссылками на неконстантные , но к ним применяются особые правила: вызов функций-членов для временных объектов и перехват объектов исключений по ссылке на неконстантные. В последнем случае временное четное является lvalue ).

Существует два вида выражений: lvalues ​​, которые обозначают объекты (которые в свою очередь могут хранить значение) или функции, и rvalues ​​, которые предназначены для представления значений, считываемых из объект или представленный временными, числовыми литералами и константами перечислителя. В C ++ 03, чтобы иметь возможность передавать такие значения в функцию, которая принимает ее значение по ссылке, существует правило, что они могут быть приняты ссылкой на const: setw const& p примет его. То есть вы должны объявить своего оператора следующим образом:

EnhSimOutput& operator<< (setw const& p);

Это немного прискорбно, потому что вы не можете устранить неоднозначность константных l-значений (объекты, которые вы создали в стеке, например, const enh::setw e(26);) и неконстантных или константных r-значений (например, enh::setw(26);, что является неконстантным временным) , Кроме того, если вы согласитесь, параметр не может вызывать неконстантные функции-члены, потому что это ссылка на const. По этой причине C ++ 1x, следующая версия C ++, вводит новый тип ссылок, так называемые rvalue-reference , который исправляет это.


Компилятор Microsoft Visual C ++ связывает rvalues ​​со ссылками на non-const, но при этом выдает предупреждение (для его отображения необходимо использовать как минимум уровень предупреждения 4). Это прискорбно, потому что возникают проблемы при портировании на другие компиляторы, более строгие в соответствии стандарту.

3 голосов
/ 15 января 2009

Я предполагаю, что EnhSimOutput& operator<< (setw& p); проходит по неконстантной ссылке, но значение 26 является "const" в том смысле, что его нельзя изменить. Попробуйте установить его на EnhSimOutput& operator<< (const setw& p);

или попробуйте

int nNumber = 26;  
enh::eout << enh::setw(nNumber);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...