Устойчивость std::typeinfo::name()

Приветствую всех.Александреску в 8ой главе "Фабрики объектов" пишет следующее:
Способ, которым реализована функция type_info: -.name, позволяет применять ее лишь для отладки. Нет никакой гарантии, что данная строка действительно представляет собой имя класса, и, что еще хуже, нет никакой гарантии, что эта строка является единственной в рамках приложения. (Да, пользуясь функцией std:: type_info::name, вы можете  получить два класса с одним и тем же именем.) И совсем убийственный аргумент: нет  гарантии, что имя типа постоянно. Никто не может обещать, что оператор typeid(Line).name() вернет то же самое имя при повторном выполнении программы. Живучесть реализации — важное качество фабрик, а функция std::type_info::name  является неустойчивой. 
Смущают выделенные аргументы в пользу неустойчивости typeid::name(). Я так понимаю, речь о том, что стандарт не даёт гарантий, но компиляторы всё-таки должны, как мне кажется, гарантировать постоянство и устойчивость работы этой функции. По-крайней мере я использую msvc++ и ничего из вышеперечисленного пока не вылезало на практике. Кто-нибудь имеет прецеденты, подтверждающие слова уважаемого автора?
14 ответов

В gcc по typeid(SomeClass).name() вылазит как правило что-то вроде KAFSomeClass1. Эти пугающие символы слева и справа от имени заставляют согласиться с автором. И вообще, если сказано, что нет гарантии, значит нет гарантии. И рассуждения "ну вроде бы по-моему должно" не к месту. Если полагаться на такие доводы, то и созданное творение "вроде бы должно будет" работать.


 Эти пугающие символы слева и справа от имени заставляют согласиться с автором.
Хорошо, с первым аргументом можно согласиться. Компилятор от MS возвращает "class ClassName".
 Если полагаться на такие доводы, то и созданное творение "вроде бы должно будет" работать.
Я полагаюсь на то, что вижу в дизассемблере и на то, что программа работает и ничего из описанного выше я пока не наблюдал. 


Кто-нибудь имеет прецеденты, подтверждающие слова уважаемого автора?
Слова автора подтверждает страндарт.Вот:
The class type_info describes type information generated by the implementation. Objects of this classeffectively store a pointer to a name for the type, and an encoded value suitable for comparing two types forequality or collating order. The names, encoding rule, and collating sequence for types are all unspecifiedand may differ between programs.
и вот:
       const char* name() const;7 Returns: an implementation-defined NTBS.8 Notes: The message may be a null-terminated multibyte string (17.3.2.1.3.2), suitable for conversion and     display as a wstring (21.2, 22.2.1.5)
Следовательно эта функция ничего НЕ гарантирует и автор полностью прав.
Я полагаюсь на то, что вижу в дизассемблере и на то, что программа работает и ничего из описанного выше я пока не наблюдал. 
В случае если писать под одну конкретную сборку одного конкретного компилятора, то этот подход имеет право на жизнь, однако если программа должна собираться разными версиями, возможно разных компиляторов, то такой подход неизбежно приведет к краху.Отладчик может лишь помочь найти логические ошибки. Он не увеличит вероятность угадывания того, как в компиляторе реализованы implementation-defined и unspecified требования стандарта.


 an encoded value suitable for comparing two types for equality or collating order
Александреску пишет:
нет никакой гарантии, что эта строка является единственной в рамках приложения.
Следовательно мы не можем использовать typeid::name() для сравнения и сортировки, если нет гарантии, что return value уникален в рамках приложения. Но стандарт это разрешает. 
однако если программа должна собираться разными версиями, возможно разных компиляторов, то такой подход неизбежно приведет к краху.
Гипотетические случаи возможны. На практике кто-нибудь встречал вот это:
нет никакой гарантии, что эта строка является единственной в рамках приложения.
Особенно вот это:
нет  гарантии, что имя типа постоянно.
Компиляторы ведь тоже не дураки пишут. RTTI - статические данные, интересно как они могут быть не постоянны? Только в случае, если заполняются в Run-Time какими-то служебными механизмами, которые генерируют данные по разным исходным параметрам. В exe compiled by vc++ RTTI хранится в секции .data и, следовательно, изменяться не может. 


Гипотетические случаи возможны. На практике кто-нибудь встречал вот это:Цитата(W4FhLF @  26.7.2008,  13:59 Найти цитируемый пост)нет никакой гарантии, что эта строка является единственной в рамках приложения.Особенно вот это:Цитата(W4FhLF @  26.7.2008,  13:59 Найти цитируемый пост)нет  гарантии, что имя типа постоянно.
Да.. Такого не встречал. Меня тоже это смутило при прочтении... 


Следовательно мы не можем использовать typeid::name() для сравнения и сортировки, если нет гарантии, что return value уникален в рамках приложения. Но стандарт это разрешает. 
Нет не разрешает. У объектов этого класса есть перегруженные операторы сравнения и метод before при помощи которых можно сравнивать и сортировать объекты этих классов. Вот про что говорит стандарт."encoded value" -  это не то-же самое, что возвращает метод name(). Это даже не то-же самое, что и "pointer to a name for the type"Про то, что возвращает метод name() сказано только что его поведение зависит от компилятора и может быть практически любым.
RTTI - статические данные, интересно как они могут быть не постоянны?
А не кто говорит что они меняются. Но символьное имя которое возвращает name() может не иметь никакого отношения к RTTI-данным которые реально требуются программе для работы механизма RTTI.
Гипотетические случаи возможны. На практике кто-нибудь встречал вот это:
Я сомневаюсь, что кто-то пытался использовать name() для целей в которых уникальность была-бы критична.Кстати с учетом того, что написано в стандарте даже следующая версия VС++ может начать выдавать в качестве результата метода name() вообще все что угодно.


Нет не разрешает. У объектов этого класса есть перегруженные операторы сравнения и метод before при помощи которых можно сравнивать и сортировать объекты этих классов. Вот про что говорит стандарт.
Точно, невнимательно прочитал. Сейчас прошёлся дизассемблером, компилятор от MS, для сравнения объектов вот так:
    someclass b(4), b1();    std::cout << (typeid(b) == typeid(b1)) << std::endl;
сравниваются две строки вида: $$A6A?AVsomeclass. Когда вызывается name() возвращается только someclass.
А не кто говорит что они меняются.
Никто не может обещать, что оператор typeid(Line).name() вернет то же самое имя при повторном выполнении программы. 
Мне конкретно вот это интересно. Встречал кто-нибудь на практике или нет. Знаю, что в студии (2005-2008) такого произойти не может.
 следующая версия VС++ может начать выдавать в качестве результата метода name() вообще все что угодно.
Может, но в этом нет логики. 


W4FhLF, такого может не быть ни в одном из существующих компиляторов, но такая возможность реализации есть, вот о ней Александреску и предупреждает. Написал это скорее всего, чтобы совсем отбить желание использоватьь name()


такого может не быть ни в одном из существующих компиляторов
Это вряд ли. Такой факт, скорее всего, был бы широкоизвестен.


Каковы ваши доказательства?
Он ведь сказал "может не быть", а не "такого нет". 


В плане RTTI в С++ обычно своё велосипедное решение (возможно с кодогенератором) лучше, ибо: надёжнее, функциональнее, удобнее.


Я когда-то столкнулась с таким случаем, хотя и немного из другой оперы:В большом приложении случайно возникают 2 класса с одинаковыми именами (в глобальном namespace).  Они совершенно никак не пересекаются по файлам и вроде бы жить друг другу не мешают (все это в рамках одной большой DLL, естественно). И никто ничего не подозревает. И линкер (MSVC) все нормально собирает... А потом для одного из них начинаем использовать typeid, неважно для чего (оба класса с виртуальными функциями)... вот тут как повезет: может, сразу полезут ошибки (выполнения), и тогда ты догадаешься, куда смотреть. А может, и не сразу... Вот я повеселилась-то при отладке-то... В общем, после того случая я завела жесткую дисциплину именования классов.Кстати, насчет самостоятельных велосипедов: скажем, MFC-шному RUNTIME_CLASS, в общем-то вполне удобному несмотря на примитив - вообще накласть на все namespace'ы вместе взятые. И линкер ни фига не поможет. А вот с typeid - это все же надо чтобы очень не повезло (чтобы функций с одинаковыми сигнатурами не было ну и т.д.) - и понятно, что делать, чтобы избегать.Свое уникальное решение для каждого случая, когда нужна фабрика, изобретать - слишком хлопотно, да и тяжело потом зоопарк поддерживать. Так что лучше что-то стандартное - но аккуратно, и понимая, куда наступаешь...


W4FhLF, сейчас столкнулся с похожей проблемой определения типа. Долго рассказывать в чем суть, но. Что меня удивило. MSDN пишет, что name() - для вывода, на консоль, еще куда-ть, а для сравненй лучше использовать raw_name().Правда, под дебагером в raw_name бред какой-то, а в name - именно тип, который мне нужен и сравнивал я рещультат name().Проверял на структурах. Проблем не было.


Что меня удивило. MSDN пишет, что name() - для вывода, на консоль, еще куда-ть, а для сравненй лучше использовать raw_name().
Этому есть простое объяснение. name возвращает имя типа (понятное человеку), а raw_name - некоторую уникальную строку, сопоставляемую типу. Строка, возвращаемая raw_name, обычно намного короче и потому сравнивается быстрее.