Такое же имя типа, но не std:: is_same
Использование С++ (gcc 4.8.3) У меня есть 2 типа (T1
и T2
), которые имеют странное свойство, что typeid(T1).name()
и typeid(T2).name()
являются одинаковыми, но
std::is_same<T1, T2>::value
- false
.
Как это может быть? Как я могу подробнее исследовать, что может быть причиной?
Ответы
Ответ 1
Игнорируя полиморфизм, typeid()
дает вам объект, представляющий статический тип выражения. Но есть некоторые элементы, которые игнорируются, когда дело касается типов выражений. Из [expr]:
Если выражение первоначально имеет тип "ссылка на T
" (8.3.2, 8.5.3), тип устанавливается до T
до любой дальнейший анализ. [...] Если prvalue изначально имеет тип "cv T
", где T
- это неквалифицированный не-класс, не-массив типа cv, тип выражение доводится до T
до любого дальнейшего анализа.
В результате любые типы, которые отличаются только квалификацией или ссылкой на верхнем уровне, будут иметь один и тот же тип. Например, типы int
, const int
, int&
volatile const int&&
и т.д. Все дают вам то же самое typeid()
.
В основном, ваш первоначальный мыслительный процесс:
typeid(T) == typeid(U) <==> std::is_same<T, U>
Но правильная эквивалентность:
typeid(T) == typeid(U) <==> std::is_same<expr_type<T>, expr_type<U>>
где:
template <class T>
using expr_type = std::remove_cv_t<std::remove_reference_t<T>>;
Ответ 2
typeid
игнорирует все cv-квалификаторы:
Во всех случаях cv-квалификаторы игнорируются typeid (т.е. typeid (T) == typeid (const T))
(ref)
Это означает, что typeid
игнорирует все ссылки &
и const
(чтобы назвать несколько).
int i = 0;
const int&& j = 1;
if (typeid(i).hash_code() == typeid(j).hash_code()) //returns true
std::cout << "typeid(int) == typeid(const int&&)";
Обратите внимание, что для сравнения 2 typeid
s вы должны использовать либо typeid(T).hash_code()
, либо std::type_index(typeid(T))
, потому что только для этих двух функций гарантируется, что 2 одинаковых typeid
будут одинаковыми. Сравнение ссылок не имеет такой гарантии, например.
Нет гарантии, что тот же экземпляр std:: type_info будет ссылаться на все оценки выражения typeid одного и того же типа, хотя std:: type_info:: hash_code этих объектов type_info будет идентичным, как было бы их std:: type_index.
(ref)
Как упоминалось в @Yakk, вы можете использовать std::remove_reference
и std::remove_cv
для получения желаемого поведения.
std::remove_reference
удаляет все ссылки из T и std::remove_cv
удаляет все const
и volatile
квалификаторы. Вы должны передать T
через эти функции, прежде чем передавать их в std::is_same
, так что std::is_same
сравнивает только базовый тип (если есть) T1
и T2
.