Привет всем.
Есть простенький код:
struct sStruct { int A; };
sStruct Get(void) { sStruct s = {0}; return s; }
int main()
{
Get().A=1;
return 0;
}
Компилирую разными компиляторами:
------------------
Comeau C/C++ 4.3.10.1
MODE:strict errors C++ C++0x_extensions
error: expression must be a modifiable lvalue
Get().A=1;
^
------------------
VC 2008
Intel C++ Compiler 11.1.061
CB 2007
Ни ошибок, ни предупреждений.
------------------
Может кто-нибудь прокомментировать это с точки зрения стандарта ?
Кто прав ?
Заранее спасибо.
Здравствуйте, Omnipresent, Вы писали:
O>Привет всем.
O>Есть простенький код:
O>O>struct sStruct { int A; };
O>sStruct Get(void) { sStruct s = {0}; return s; }
O>int main()
O>{
O> Get().A=1;
O> return 0;
O>}
O>
O>Компилирую разными компиляторами: Ни ошибок, ни предупреждений.
O>Может кто-нибудь прокомментировать это с точки зрения стандарта ?
Этот вопрос упирается в понимание таких сущностей языка как
lvalue и
rvalue, описанных в п. 3.10 стандарта. Любой тип результата кроме
void и ссылки считается
rvalue.
3.10/5
The result of calling a function that does not return a reference is an rvalue. User defined operators are functions, and whether such operators expect or yield lvalues is determined by their parameter and return types.
Стандартом допускается модификация членов для
rvalue объектов-классов:
3.10/10
An lvalue for an object is necessary in order to modify the object except that an rvalue of class type can also be used to modify its referent under certain circumstances. [Example: a member function called for an object (9.3) can modify the object. ]
Для лучшего понимания
lvalue и
rvalue полезно почитать почитать
эту статьюАвтор(ы): Павел Кузнецов
Дата: 02.01.2004
lvalue и rvalue — что это такое.
.
Omnipresent:
O>Может кто-нибудь прокомментировать это с точки зрения стандарта ?
В текущем стандарте внятного объяснения нет.
"— If E2 is a non-static data member, and the type of E1 is “cq1 vq1 X”, and the type of E2 is “cq2 vq2 T”, the expression designates the named member of the object designated by the first expression. If E1 is an lvalue, then E1.E2 is an lvalue
[Чем будет E1.E2, если E1 — rvalue, не сказано]." (5.2.5/4)
Эта проблема давно рассмотрена в
DR 421. Если следовать предложенному уточнению, то данный код некорректен вследствие ограничения, указанного в 5.17/1:
"There are several assignment operators, all of which group right-to-left.
All require a modifiable lvalue as their left operand, and the type of an assignment expression is that of its left operand."
OK, спасибо большое за комменты.
Я не сильно большой знаток стандарта; пользуясь здравым смыслом, я ожидал для этого кода если не ошибки, то по крайней мере хотя бы предупреждения (типа "temporary used in assignment"). Еще интереснее выглядела разница между результатами компиляции в разных компиляторах. Теперь всё более-менее ясно: Камю (как самый продвинутый) дает ошибку, остальные скромно следуют старой (порочной IMHO, но всё еще формально стандартной) трактовке.
Здравствуйте, Omnipresent, Вы писали:
O>Я не сильно большой знаток стандарта; пользуясь здравым смыслом, я ожидал для этого кода если не ошибки,
Так в C++ здравым смыслом и не пахнет. Например, код
Get() = Get();
будет вполне корректным и по действующему и по черновику нового стандарта.