Почему строки, возвращаемые функцией name(), определяются реализацией?

Рассмотрим следующий пример:

#include <iostream>
#include <typeinfo>
int main()
{
    int a=9;
    std::cout << typeid(a).name() << '\n';
}

Вывод на g++ 4.8.1: я

Вывод на MSVS 2010: int

Почему вывод зависит от компилятора? В чем причина этого? Почему это оставлено как определенная реализация? Почему бы не сделать одинаковый вывод на всех компиляторах? Стандарт С++ говорит об этом явно?


person Destructor    schedule 02.09.2015    source источник
comment
связанный: заголовок stackoverflow.com/questions/4465872/   -  person Class Skeleton    schedule 02.09.2015


Ответы (5)


Потому что компиляторы представляют типы по-разному и не используют одни и те же внутренние компоненты.

Строка G++ — это искаженное имя типа, возвращать которое (а не разбирать на части) проще и эффективнее. Требование, чтобы компиляторы демонтировали эти строки, добавило бы больше работы. Стандарт оставляет за разработчиками право решать, хотят ли они этого.

Если бы стандарт диктовал это, то он также должен был бы указывать всевозможные вещи, например, говорить ли signed long или просто long и как представлять сложные экземпляры шаблона, которые зависят от других типов и констант. Выгоды от стандартизации этих строк были бы очень небольшими, но объем работы был бы большим.

person Jonathan Wakely    schedule 02.09.2015

Да, стандарт С++ прямо говорит об этом:

18.7.1$9,10 Класс type_info [type.info]

const char* name() const noexcept; 

9 Возвращает: ntbs, определяемый реализацией.
10 Примечания: сообщение может быть многобайтовой строкой с завершающим нулем (17.5.2.1.4.2), подходящей для преобразования и отображения в виде wstring (21.3, 22.4.1.4)

person songyuanyao    schedule 02.09.2015

Стандарт С++ говорит:

Класс type_info описывает информацию о типе, сгенерированную реализацией. Объекты этого класса фактически хранят указатель на имя типа и закодированное значение, подходящее для сравнения двух типов на равенство или порядок сортировки. Имена, правила кодирования и последовательность сортировки для типов не указаны и могут различаться в разных программах.

g++ возвращает вам украшенное имя, которое вы легко можете разобрать.

Также см.: Тип переменной печати в C++

person Rahul Tripathi    schedule 02.09.2015
comment
Кажется, это добавляет шансов принятому ответу: не указано и определено реализацией — это два разных типа поведения. Можете ли вы указать, из какой части какого стандарта взята эта цитата? - person MSalters; 02.12.2016

Чтобы расширить ответ Джонатана Уэйкли, типичным использованием typeid является

if ( typeid(variable1) == typeid(variable2) )
     // same type

но и

if ( typeid(variable1).name() == typeid(variable2).name() )
    // same type

как видите, нет необходимости знать точное имя, определяемое реализацией. Поскольку вам это на самом деле не нужно, стандарт дает свободу реализации для более эффективной реализации, что достаточно хорошо.

Например, сравните _ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_ и std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) : определенно менее подробный и эффективный, чтобы сравнивать и хранить.

person edmz    schedule 02.09.2015

Кроме того, typeid в основном используется с полиморфными типами для обнаружения полиморфных типов объектов во время выполнения:

#include <iostream>
#include <typeinfo>

class B
{
public:
    virtual ~B() {}
};

class D1 : public B
{

};

class D2 : public D1
{

};

int main()
{
    B* b1 = new D2;
    if (typeid(*b1) == typeid(B))
    {
        std::cout << "*b1 is B\n";
    }
    if (typeid(*b1) == typeid(D1))
    {
        std::cout << "*b1 is D1\n";
    }
    if (typeid(*b1) == typeid(D2))
    {
        std::cout << "*b1 is D2\n";
    }
}

Это напечатает

*b1 is D2

Поэтому он не предназначен для печати имен типов объектов.

person Hrant    schedule 02.09.2015