Здравствуйте, Аноним, Вы писали:
А>Как подсказывает название, static_cast преобразует выражения одного статического типа в объекты и значения другого статического типа.
В статье есть очевидная ошибка при описании преобразований указателей на члены класса.
Во-первых, преобразование 'Base::*' -> 'Derived::*' (при условии, что классы 'Base' и 'Derived' являются соответственно предком и потомком) является стандартным преобразованием и никакого явного каста не требует. "Обратным" преобразованием к этому преобразованию будет преобразование 'Derived::*' -> 'Base::*', которое как раз таки и выполняется при помощи 'static_cast'. Ситуация с указателями на члены в точности обратна (симметрична) ситуации с указателями на объекты: указатели на объекты — covariance, указтели на члены — contravariance.
Во-вторых, утверждение о том, что приведение 'Base::*' -> 'Derived::*' приводит к неопределенному поведению, если исходный указатель не указывет на член класса 'Derived', совешенно не верно. Ни стандартное приведение 'Base::*' -> 'Derived::*', ни приведение 'Derived::*' -> 'Base::*', выполняемое при помощи 'static_cast' никогда не приводят к неопределенному поведению (при условии, что классы 'Base' и 'Derived' являются соответственно предком и потомком). Неопределенное поведение может возникнуть на этапе разадресации указателя на отсутствующий член класса, но не на этапе приведения типа.
Best regards,
Андрей Тарасевич
Re: Deep C++. Operation: static_cast. Перевод - Igor Sukhare
RS>Авторы : RS>Robert Schmidt
RS>Аннотация : RS>Как подсказывает название, static_cast преобразует выражения одного статического типа в объекты и значения другого статического типа.
Исходя из статьи можно предположить то, что любой тип можно избавить от cv-модификаторов с оспользованием одного лишь static_cast'а, в результате я попробовал скомпилировать следующий код:
Здравствуйте, SergioSV, Вы писали:
SSV>Исходя из статьи можно предположить то, что любой тип можно избавить от cv-модификаторов с использованием одного лишь static_cast'а
Избавить-то можно, но ценой undefined behavior:
const volatile int t0 = 5;
const volatile int *t1 = &t0;
int *t2 = *static_cast<int **>(static_cast<void *>(&t1));
int &t3 = *t2;
Формально такая цепочка преобразований не подпадает под правило во втором предложении 5.2.9/10:
A value of type pointer to object converted to “pointer to cv void” and back to the original pointer type will have its original value
а значит, это подпадает под второе предложение 1.3.12:
Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior.
Также не следует забывать про 7.1.5.1/7:
If an attempt is made to refer to an object defined with a volatile-qualified type through the use of an lvalue with a non-volatile-qualified type, the program behaviour is undefined
Re[3]: Deep C++. Operation: static_cast. Перевод - Igor Sukh
Здравствуйте, Masterkent, Вы писали:
M>Здравствуйте, SergioSV, Вы писали:
SSV>>Исходя из статьи можно предположить то, что любой тип можно избавить от cv-модификаторов с использованием одного лишь static_cast'а
M>Избавить-то можно, но ценой undefined behavior:
С этим вопросом вроде разобрался:
1. Исходя из стандарта 98-года получаем (5.2.9/10):
An rvalue of type "pointer to cv void" can be explicitly converted to a pointer to object type. A value of type pointer to object converted to “pointer to cv void” and back to the original pointer type will have its original value.
Т.е., выходит, что преобразование "(возможно cv-квалифицированный) void * в любой T *" не запрещено.
2. Исходя из Working Draft, Standard for Programming Language C++ (2005-10-19), получаем (5.2.9/11):
An rvalue of type “pointer to cv1 void” can be converted to an rvalue of type “pointer to cv2 T,” where T is an object type
and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. A value of type pointer to object converted
to “pointer to cv void” and back, possibly with different cv-qualification, shall have its original value. [ Example:
T* p1 = new T;
const T* p2 = static_cast < const T*>( static_cast < void *>( p1 ));
bool b = p1 == p2 ; / / b will have the value true.
—end example ]
Т.е., преобразование "(возможно cv-квалифицированный) void * в любой T *" разрешено, но с оговорками:
An rvalue of type “pointer to cv1 void” can be converted to an rvalue of type “pointer to cv2 T,” where T is an object type
and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.
Re[3]: Deep C++. Operation: static_cast. Перевод - Igor Sukh
Здравствуйте, SergioSV, Вы писали:
SSV>1. Исходя из стандарта 98-года получаем (5.2.9/10):
В настоящий момент действующим стандартом C++ является ISO/IEC 14882:2003(E) aka C++03, а стандарт 98-го года недействителен:
ISO/IEC 14882:2003(E) / Foreword
This second edition cancels and replaces the first edition (ISO/IEC 14882:1998), which has been technically revised.
В C++03 данное преобразование описывается так:
5.2.9/10
An rvalue of type “pointer to cv1 void” can be converted to an rvalue of type “pointer to cv2 T,” where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. A value of type pointer to object converted to “pointer to cv void” and back to the original pointer type will have its original value.
Re[2]: Deep C++. Operation: static_cast. Перевод - Igor Sukh
Здравствуйте, Vain, Вы писали:
V>Здравствуйте, Robert Schmidt, Вы писали:
Насколько я понимаю, это всего лишь перевод статьи, и касаемо данного ляпа специально сделана ремарка:
(С точки зрения стандарта, эти примеры недопустимы: static_cast не может приводить указатели несвязанных типов, каковыми являются int и float — прим. RSDN.)