typeinfo vs no typeinfo

Landstreicher

Возникло 2 варианта написания программы. В одном исползуется typeid/typeinfo, в другом - нет.
Первое решение более просто и логично, второе - более грязно (в смысле хаков) и подвержено ошибкам. Помогите выбрать между ними. Конкретно интересуют такие вопросы:
1. Насколько эти typeid/typeinfo поддерживаются компиляторами? Программа должна быть переносима, и если какой-то известный компилятор ее не поддерживает, то происходит облом. Помимо GCC, ICC и MSVC, интересуют также всякие комприляторы под коммерческие UNIX типа HPUX, AIX итп.
2. Насколько быстро работает этот typeid? Я смотрел в двух компиляторах: GCC и MSVC. GCC ложит ссылку на typeinfo просто в элемент таблицы виртуальных методов (vptr поэтому typeid сводится фактически к 2 инструкциям вида mov (%eax %eax; mov -4(%eax %ecx. Это очень быстро, отлично. Однако, MSVC (6.0) генерирует вызов какой-то функции типа call __RTtypeid. Что это за функция и насколько быстро она работает? Есть ли какая-нибудь информация как работает механизм typeinfo на других платформах/компиляторах.
3. Можно ли сравнивать не сами typeinfo, а указатели на них? В стандарте C++ написано что для проверки типа нужно вызывать typeinfo::operator == . Однако в GCC структуры typeinfo выделяются статически, и у всех объектов одного типа typeinfo одинаковый, поэтому можно сравнивать указатели на typeinfo (что быстрее: сравнения typeinfo ~ strcmp). Но тут тоже есть подводные камни. Например, если у меня есть шаблон, то его описание (.h-файл) включается в несколько .cpp-файлов. В результате в каждом .o-файле инстанционируется шаблон, и генерится typeinfo. Может быть (это только гипотеза что typeinfo у объектов шаблонного класса созданных в разных .cpp-файлах будет разный. Тогда придется сравнивать сами объекты, а не указатели на них. Интересна любая информация по этому вопросу.

rosali

Насколько эти typeid/typeinfo поддерживаются компиляторами?
Ну это же стандарт. Насколько стандарт поддерживается компиляторами?
поэтому typeid сводится фактически к 2 инструкциям вида mov (%eax %eax; mov -4(%eax %ecx ... вызов какой-то функции типа call __RTtypeid
В этом самом __RTtypeid в частности проверяется, что указатель действительно указывает на объект полиморфного типа и т.д. Странно если gcc этого не делает. Вобщем не быстро оно работает,... а ты уверен что тебе быстро надо?
Можно ли сравнивать не сами typeinfo, а указатели на них? В стандарте C++ написано ... Однако ...
Не, ну это говорит человек, которому так важна переносимость, ты уж определись важна или нет.

Marinavo_0507

> В этом самом __RTtypeid в частности проверяется, что указатель действительно указывает на объект полиморфного типа и т.д.
А как это можно проверить?

rosali

Хехе, ну там куку какую-нибудь проверить, например, в надежде что случайностей не бывает. Там кажись даже в начале проверяется что по этому адресу вообще обратиться можно. И еще зачем-то exception handling нагорожен. Microsoft, хуле!

Landstreicher

Ассемблерный листинг в студию!

Landstreicher

> Вобщем не быстро оно работает,... а ты уверен что тебе быстро надо?
Сколько примерно тактов? Зависит ли от числа классов в системе? Если зависит то как?
> Не, ну это говорит человек, которому так важна переносимость, ты уж определись важна или нет.
К большому сожалению, переносимость и соотвествие стандарту - две различные вещи, иногда из-за требований переносимости приходится нарушать стандарт, так как компилятор ему не соотвествует.

rosali

320-330 тактов, когда раскачагарится (instruction cache и т.п.)
Зависит ли от числа классов в системе?
Без понятия.
переносимость и соотвествие стандарту - две различные вещи, иногда из-за требований переносимости приходится нарушать стандарт, так как компилятор ему не соотвествует.
Вообще есть такая дрянь - stlport - можешь глянуть.
На, короче, ботай.
  
__RTtypeid:
7C359EE0 push 30h
7C359EE2 push 7C380F48h
7C359EE7 call __SEH_prolog (7C34230Bh)
7C359EEC mov eax,dword ptr [inptr]
7C359EEF test eax,eax
7C359EF1 jne __RTtypeid+2Ah (7C359F0Ah)
7C359EF3 push offset string "Attempted a typeid of NULL point"... (7C380F24h)
7C359EF8 lea ecx,[ebp-28h]
7C359EFB call bad_typeid::bad_typeid (7C358B12h)
7C359F00 push offset __TI2?AV@ (7C389244h)
7C359F05 lea eax,[ebp-28h]
7C359F08 jmp $L18742+18h (7C359F75h)
7C359F0A and dword ptr [ebp-4],0
7C359F0E mov eax,dword ptr [eax]
7C359F10 mov esi,dword ptr [eax-4]
7C359F13 mov dword ptr [pCompleteLocator],esi
7C359F16 push 8
7C359F18 push dword ptr [esi+0Ch]
7C359F1B call dword ptr [__imp__Is8 (7C37A1CCh)]
7C359F21 test eax,eax
7C359F23 jne __RTtypeid+52h (7C359F32h)
7C359F25 mov eax,dword ptr [esi+0Ch]
7C359F28 or dword ptr [ebp-4],0FFFFFFFFh
7C359F2C call __SEH_epilog (7C342346h)
7C359F31 ret
7C359F32 push offset string "Bad read pointer - no RTTI data!"... (7C380F00h)
7C359F37 lea ecx,[ebp-34h]
7C359F3A call __non_rtti_object::__non_rtti_object (7C358B4Eh)
7C359F3F push offset __TI3?AV__non_r@ (7C389224h)
7C359F44 lea eax,[ebp-34h]
7C359F47 jmp $L18742+18h (7C359F75h)
$L18741:
7C359F49 mov eax,dword ptr [ebp-14h]
7C359F4C mov eax,dword ptr [eax]
7C359F4E mov eax,dword ptr [eax]
7C359F50 xor ecx,ecx
7C359F52 cmp eax,0C0000005h
7C359F57 sete cl
7C359F5A mov eax,ecx
$L18752:
7C359F5C ret

Dasar

typeinfo и скорость - в целом вещи, не совместимые.
Везде советуют, что если нужна скорость, то лучше сделать без typeinfo.
Оставить комментарий
Имя или ник:
Комментарий: