Char!= (подпись char), char!= (без знака char)
Приведенный ниже код компилируется, но имеет различное поведение для типа char, чем для типов int.
В частности,
cout << getIsTrue< isX<int8>::ikIsX >() << endl;
cout << getIsTrue< isX<uint8>::ikIsX >() << endl;
cout << getIsTrue< isX<char>::ikIsX >() << endl;
приводит к 3 экземплярам шаблонов для трех типов: int8, uint8 и char. Что дает?
То же самое не относится к ints: int и uint32, которые приводят к тому же экземпляру шаблона, и подписали int other.
Причина в том, что С++ видит char, подписанный char и unsigned char как три разных типа. Если int совпадает с подписанным int. Это правильно или я что-то упускаю?
#include <iostream>
using namespace std;
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef signed int int32;
typedef unsigned int uint32;
typedef signed long long int64;
typedef unsigned long long uint64;
struct TrueType {};
struct FalseType {};
template <typename T>
struct isX
{
typedef typename T::ikIsX ikIsX;
};
// This int==int32 is ambiguous
//template <> struct isX<int > { typedef FalseType ikIsX; }; // Fails
template <> struct isX<int32 > { typedef FalseType ikIsX; };
template <> struct isX<uint32 > { typedef FalseType ikIsX; };
// Whay isn't this ambiguous? char==int8
template <> struct isX<char > { typedef FalseType ikIsX; };
template <> struct isX<int8 > { typedef FalseType ikIsX; };
template <> struct isX<uint8 > { typedef FalseType ikIsX; };
template <typename T> bool getIsTrue();
template <> bool getIsTrue<TrueType>() { return true; }
template <> bool getIsTrue<FalseType>() { return false; }
int main(int, char **t )
{
cout << sizeof(int8) << endl; // 1
cout << sizeof(uint8) << endl; // 1
cout << sizeof(char) << endl; // 1
cout << getIsTrue< isX<int8>::ikIsX >() << endl;
cout << getIsTrue< isX<uint8>::ikIsX >() << endl;
cout << getIsTrue< isX<char>::ikIsX >() << endl;
cout << getIsTrue< isX<int32>::ikIsX >() << endl;
cout << getIsTrue< isX<uint32>::ikIsX >() << endl;
cout << getIsTrue< isX<int>::ikIsX >() << endl;
}
Я использую g++ 4.something
Ответы
Ответ 1
Вот ваш ответ со стандартом:
3.9.1 Основные типы [basic.fundamental]
1 Объекты, объявленные как символы char), должны быть достаточно большими, чтобы хранить любой элемент базового набора символов реализации. Если символ из этого набора сохраняется в символьном объекте, целочисленное значение этого символьного объекта равно значению односимвольной литеральной формы этого символа. Определяется реализация, может ли объект char содержать отрицательные значения. Символы могут быть явно объявлены без знака или подписаны. Обычная char, подписанная char и unsigned char - три разных типа. A char, подписанный char и неподписанный char занимают одинаковое количество хранения и имеют одинаковые требования к выравниванию (basic.types); то есть они имеют одно и то же представление объекта. Для типов символов в представлении значения участвуют все биты представления объекта. Для неподписанных типов символов все возможные битовые шаблоны представления значений представляют числа. Эти требования не подходят для других типов. В любом конкретном
реализация, простой объект char может принимать те же значения, что и подписанный char или unsigned char; какой из них определяется реализацией.
Ответ 2
Для таких вопросов, как это, я хотел бы изучить документ Rationale для C, который часто дает ответы на тайны С++, которые иногда возникают у меня при чтении стандарта. Об этом он говорит:
Указаны три типа char: signed, plain и unsigned. Простой char может быть представлен как подписанный, так и неподписанный, в зависимости от реализации, как в предыдущей практике. Был введен тип подписанный char, чтобы сделать доступным однобайтовый целочисленный тип со знаком в тех системах, которые реализуют plain char как unsigned. По соображениям симметрии ключевое слово, подписанное, разрешено как часть имени типа других интегральных типов.
Обоснование для C
Ответ 3
В то время как большинство интегральных типов, таких как short
и int
по умолчанию, являются signed
, char
не имеет знака по умолчанию в С++.
Это распространенная ошибка, с которой сталкиваются программисты на С++, когда они используют char
как 8-битный целочисленный тип.
Ответ 4
которые правильны, char
, unsigned char
и signed char
являются отдельными типами. Вероятно, было бы неплохо, если бы char
был просто синонимом для signed char
или unsigned char
в зависимости от реализации ваших компиляторов, но стандарт говорит, что они являются отдельными типами.