Вообще говоря, есть понятие layout-compatible POD структур, которыми являются структуры Tom'а. Только вот я что-то не нашел по поводу легальности преобразования указателей.
Of course, the code must be complete enough to compile and link.
Re[3]: Приведение указателя между эквивалентными классами
L_L>Вообще говоря, есть понятие layout-compatible POD структур, которыми являются структуры Tom'а. Только вот я что-то не нашел по поводу легальности преобразования указателей.
Как известно, единственное легальное действие с указателем после преобразования — обратное преобразование.
Да здравствует мыло душистое и веревка пушистая.
Re[3]: Приведение указателя между эквивалентными классами
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Вообще говоря, есть понятие layout-compatible POD структур, которыми являются структуры Tom'а. Только вот я что-то не нашел по поводу легальности преобразования указателей.
Да, но контроля со стороны компилятора никакого, ибо reinterpret_cast. В один прекрасный момент foo1 или foo2 станет не POD-ом и система загремит под фанфары.
Re[4]: Приведение указателя между эквивалентными классами
АШ>Да, но контроля со стороны компилятора никакого, ибо reinterpret_cast. В один прекрасный момент foo1 или foo2 станет не POD-ом и система загремит под фанфары.
А вот этого никто не говорил, что они должны стать не под типом. В вопросе под.
Of course, the code must be complete enough to compile and link.
Re[5]: Приведение указателя между эквивалентными классами
Здравствуйте, Lorenzo_LAMAS, Вы писали:
АШ>>Да, но контроля со стороны компилятора никакого, ибо reinterpret_cast. В один прекрасный момент foo1 или foo2 станет не POD-ом и система загремит под фанфары.
L_L>А вот этого никто не говорил, что они должны стать не под типом. В вопросе под.
Не в вопросе, а в примере.
Re[6]: Приведение указателя между эквивалентными классами
Здравствуйте, Lorenzo_LAMAS, Вы писали:
LL> Вообще говоря, есть понятие layout-compatible POD структур, LL> которыми являются структуры Tom'а. Только вот я что-то не нашел LL> по поводу легальности преобразования указателей.
Для layout compatible POD-структур все должно быть в порядке, т.к. они должны
иметь идентичное представление. Также смотри:
C.1.2 clause 3/5 (3.9)
Change: C allows “compatible types” in several places, C++ does not
For example, otherwise-identical struct types with different tag names
are “compatible” in C but are distinctly different types in C++.
Rationale: Stricter type checking is essential for C++.
Effect on original feature: Deletion of semantically well-defined feature.
Difficulty of converting: Semantic transformation. The “typesafe linkage”
mechanism will find many, but not all, of such problems. Those problems
not found by typesafe linkage will continue to function properly, according
to the “layout compatibility rules” of this International Standard.
How widely used: Common.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: Приведение указателя между эквивалентными классами
да вообще-то это был просто вопрос, это не какая-то важная фича которой очень хочется пользоваться. Павел вроде все объяснил уже. Т.е. если структуры не будут extern "C" то как Вы и сказали — хак.
Of course, the code must be complete enough to compile and link.
Re: Приведение указателя между эквивалентными классами
Видел в книжке одной (Арчер вроде, это которая по Visual C++ 7), так он там вообще указатель CFormView приводит к CDialog, для того что бы поюзать некоторые диалоговские функции. Вот так вот. Хотя там были полиморфные классы. Я конечно понимаю что так нельзя, но все же автор то известный.
Re[2]: Приведение указателя между эквивалентными классами
Здравствуйте, Denwer, Вы писали:
D> Видел в книжке одной (Арчер вроде, это которая по Visual C++ 7), так он D> там вообще указатель CFormView приводит к CDialog, для того что бы поюзать D> некоторые диалоговские функции.
Вся архитектура MFC на таком безобразии завязана. Это вольности, допустимые
для конкретной реализации, но не в общем случае.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: Приведение указателя между эквивалентными классами
Здравствуйте, Павел Кузнецов, Вы писали: ПК>Не вполне... Для пущей строгости Тому надо еще extern "C" добавить.
Павел, я попытался убедиться по стандарту, что это действительно так, и не сумел.
Не могли бы Вы повторить детально ход Ваших рассуждений?
Очевидно, что, вследствие 9.2/17, запись
foo2* p = reinterpret_cast<foo2*>( reinterpret_cast<int*>( &foo1_instance ) );
вполне валидна и позволяет гарантированно работать с первым элементом совместимых структур.
Однако я не нашел, как доказать валидность преобразования
foo2* p = reinterpret_cast<foo2*>( &foo1_instance );
независимо от того, extern "C" типы foo1 и foo2, или нет.
Согласно 5.2.10/7, результат такого преобразования "is unspecified".
Более того, хотя стандарт четко определяет, что такое "layout-compatible", мне не вполне понятно, для чего вообще может понадобиться знание того, что два типа layout-compatible.
Скажем, из стандарта не очевидно, что преобразование
union foo_u {
foo1 f1;
foo2 f2;
};
foo2* p = &(reinterpret_cast<foo_u*>( &foo1_instance )->f2);
валидно.
С уважением,
Сергей Дмитриев
Re[7]: Приведение указателя между эквивалентными классами
Здравствуйте, Dmi3evS, Вы писали:
ПК>> Не вполне... Для пущей строгости Тому надо еще extern "C" добавить.
D> Павел, я попытался убедиться по стандарту, что это действительно так, D> и не сумел. Не могли бы Вы повторить детально ход Ваших рассуждений?
Вообще, ни определение layout-compatible структур, ни допустимые с ними операции
в стандарте не проработаны в достаточной степени для каких бы то ни было
"строгих" рассуждений. Например, до TC1 в определении layout-compatible структур
требовалось даже, чтобы структуры имели одно и то же число функций-членов
и статических членов: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#190
Тем не менее, с практической точки зрения, можно ожидать, что некоторые вещи
с layout-compatible структурами работать будут. В частности:
Значения указателей на layout-compatible типы должны иметь одинаковое
представление и alignment requirements (3.9.2/3).
Если две layout-compatible структуры помещены в объединение, то разрешается
писать в одну, а читать из другой (9.2/16).
С любой структурой допускается работать через указатель. В месте использования
указателя может не быть известно, находится ли данная структура в объединении,
или нет. Фактически все это означает, что скопировав каким-то образом значение
указателя на одну структуру в указатель на layout-compatible структуру, мы можем
ожидать, что работая через новый указатель, не получим никаких сюрпризов.
Однако есть по меньшей мере два "но":
Стандарт вполне допускает проверки времени исполнения того, что доступ к
объекту производится через "правильный" указатель. Теоретически можно представить
какую-нибудь ситуацию, где эта гипотетическая возможность могла бы "выстрелить".
reinterpret_cast не гарантирует неизменности значений указателей при подобных преобразованиях.
Как видно из ранее процитированного фрагмента (ненормативной) части стандарта
понятие layout-compatible структур было оставлено для совместимости с C. Для
удобства я еще раз приведу этот фрагмент: C.1.2 clause 3/5 (3.9)
Change: C allows “compatible types” in several places, C++ does not.
For example, otherwise-identical struct types with different tag names are
“compatible” in C but are distinctly different types in C++. Rationale: Stricter type checking is essential for C++. Effect on original feature: Deletion of semantically well-defined feature. Difficulty of converting: Semantic transformation. The “typesafe linkage”
mechanism will find many, but not all, of such problems. Those problems not found
by typesafe linkage will continue to function properly, according to the “layout
compatibility rules” of this International Standard. How widely used: Common.
Т.е. несовместимости типов, не обнаруживаемые на стадии компоновки, по задумке
комитетчиков должны продолжать работать, как и в C. При компоновке не будут
различаться структуры, объявленные как extern "C". Поэтому, держа в голове тот
самый гипотетический случай "навороченных" run-time проверок, я предположил,
что меньшим "хаком" будет преобразование extern "C" layout-compatible структур.
reinterpret_cast — самое слабое место, если рассуждать "строго". Но тут спасает,
что реализации придется уж очень сильно извернуться, чтобы поломать наши примеры.
В самом деле, учитывая идентичность представлений значений указателей на layout-
compatible типы, ничем кроме "диверсии" со стороны разработчиков компилятора,
модификацию этого значения при подобном преобразовании я лично объяснить не могу.
Итого: строго говоря, конечно, стандарт не дает прямых гарантий, что исходный,
или модифицированный примеры будут работать, но, полагаю, что это будет верным
для всех существующих реализаций. Также, из соображений совместимости с C,
маловероятно, что модифицированный (с extern "C") пример когда-нибудь перестанет
работать. Т.е. если под "хаком" понимать практическую работоспособность, это не
"хак"; если абсолютное соответствие букве стандарта — безусловно "хак".
D> Очевидно, что, вследствие 9.2/17, запись D>
D> foo2* p = reinterpret_cast<foo2*>( reinterpret_cast<int*>( &foo1_instance ) );
D>
D> вполне валидна и позволяет гарантированно работать с первым элементом D> совместимых структур.
Подобный "финт" гарантирует работоспособность примера немногим в большей степени,
чем "простой" reinterpret_cast. В самом деле, стандарт не дает никаких гарантий,
что преобразования int* -> foo2* и int* -> foo1* будут давать одинаковые значения
указателей. Естественно, что "испортить" этот пример, также как и "прямой"
reinterpret_cast, разработчики компилятора могут только предпринимая сознательные
усилия. Впрочем, т.к. никаких причин для таких их действий не видно, ожидать, что
они сделают такую пакость, не приходится
D> Согласно 5.2.10/7, результат такого преобразования "is unspecified". D> Более того, хотя стандарт четко определяет, что такое "layout-compatible", D> мне не вполне понятно, для чего вообще может понадобиться знание того, что D> два типа layout-compatible.
Как упоминалось выше, в нормативной части прямо layout-compatible типы
используются для описания семантики объединений, совместимых с C.
D> Скажем, из стандарта не очевидно, что преобразование D>
D> union foo_u {
D> foo1 f1;
D> foo2 f2;
D> };
D> foo2* p = &(reinterpret_cast<foo_u*>( &foo1_instance )->f2);
D>
D> валидно.
Строго говоря, невалидно. Имхо, даже менее валидно, чем оригинальный пример
(если, конечно, рассуждения о степени валидности здесь уместны ), т.к. доступ
к объекту типа foo1 осуществляется через указатель типа foo_u, который даже
не является layout-compatible с foo1. И, если компилятор будет поддерживать
run-time проверки "кошерности" доступа, здесь, имхо, он как раз и должен
будет "выстрелить".
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен