Pregunta

El siguiente código se compila, pero tiene un comportamiento diferente para el tipo char que para los tipos int.

En particular

   cout << getIsTrue< isX<int8>::ikIsX  >() << endl;
   cout << getIsTrue< isX<uint8>::ikIsX  >() << endl;
   cout << getIsTrue< isX<char>::ikIsX  >() << endl;

da como resultado 3 instancias de plantillas para tres tipos: int8, uint8 y char. ¿Qué da?

Lo mismo no es cierto para ints: int y uint32 que dan como resultado la misma creación de instancias de plantilla y firmaron int en otro.

La razón parece ser que C ++ ve char, char firmado y unsigned char como tres tipos diferentes. Mientras que int es lo mismo que un int con signo. ¿Es correcto o me falta algo?

#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;

}

Estoy usando g ++ 4.algo

¿Fue útil?

Solución

Aquí está su respuesta del estándar:

  

3.9.1 Tipos fundamentales [basic.fundamental]

     Los

objetos declarados como caracteres ( char ) serán lo suficientemente grandes como para almacenar cualquier miembro del conjunto de caracteres básico de la implementación. Si un carácter de este conjunto se almacena en un objeto de carácter, el valor integral de ese objeto de carácter es igual al valor de la forma literal de un solo carácter de ese carácter. Está definido por la implementación si un objeto char puede contener valores negativos. Los caracteres se pueden declarar explícitamente como unsigned o firmado . Charla llana , char firmada y char firmada son tres tipos distintos. A char , un firmado char y un unsigned char ocupan la misma cantidad de almacenamiento y tienen los mismos requisitos de alineación ( basic.types ); es decir, tienen la misma representación de objeto. Para los tipos de caracteres, todos los bits de la representación del objeto participan en la representación del valor. Para los tipos de caracteres sin signo, todos los patrones de bits posibles de la representación del valor representan números. Estos requisitos no son válidos para otros tipos. En cualquier particular   implementación, un simple objeto char puede tomar los mismos valores que un char firmado o un unsigned char ; cuál está definido por la implementación.

Otros consejos

Para preguntas como esta, me gusta consultar el documento de Fundamentos para C, que a menudo también proporciona respuestas a los misterios de C ++, que a veces surgen para mí cuando leo el Estándar. Tiene esto que decir al respecto:

  

Se especifican tres tipos de caracteres: con signo, sin formato y sin signo. Un carácter simple puede representarse como firmado o no, dependiendo de la implementación, como en la práctica anterior. El tipo de caracteres con signo se introdujo para poner a disposición un tipo de entero con signo de un byte en aquellos sistemas que implementan caracteres simples como sin signo. Por razones de simetría, la palabra clave con signo se permite como parte del nombre de tipo de otros tipos integrales.

Justificación de C

Mientras que la mayoría de los tipos integrales como short y int están predeterminados para ser firmado , char no tiene un valor predeterminado señalización en C ++.

Es un error común con el que se encuentran los programadores de C ++ cuando usan char como un tipo entero de 8 bits.

es correcto, char , unsigned char y igned char son tipos separados. Probablemente hubiera sido bueno si char fuera solo un sinónimo de igned char o unsigned char dependiendo de la implementación de su compilador, pero el estándar dice son tipos separados.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top