The code below compiles, but has different behavior for the char type than for the int types.
In particular
cout << getIsTrue< isX<int8>::ikIsX >() << endl; cout << getIsTrue< isX<uint8>::ikIsX >() << endl; cout << getIsTrue< isX<char>::ikIsX >() << endl;
result in 3 instantiations of templates for three types: int8, uint8 and char. What gives?
The same is not true for ints: int and uint32 which result in the same template instantiation, and signed int another.
The reason seems to be that C++ sees char, signed char and unsigned char as three different types. Whereas int is the same as a signed int. Is this right or am I missing something?
#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; }
I'm using g++ 4.something
A signed char is a signed value which is typically smaller than, and is guaranteed not to be bigger than, a short . An unsigned char is an unsigned value which is typically smaller than, and is guaranteed not to be bigger than, a short .
The term "unsigned" in computer programming indicates a variable that can hold only positive numbers. The term "signed" in computer code indicates that a variable can hold negative and positive values. The property can be applied to most of the numeric data types including int, char, short and long.
By the C++ standard, a signed char is guaranteed to be able to hold values -127 to 127 (not -128!), whereas a unsigned char is able to hold values 0 to 255.
An unsigned type can only represent postive values (and zero) where as a signed type can represent both positive and negative values (and zero). In the case of a 8-bit char this means that an unsigned char variable can hold a value in the range 0 to 255 while a signed char has the range -128 to 127.
Here is your answer from the standard:
3.9.1 Fundamental types [basic.fundamental]
Objects declared as characters (
char
) shall be large enough to store any member of the implementation's basic character set. If a character from this set is stored in a character object, the integral value of that character object is equal to the value of the single character literal form of that character. It is implementation-defined whether achar
object can hold negative values. Characters can be explicitly declaredunsigned
orsigned
. Plainchar
,signed char
, andunsigned char
are three distinct types. Achar
, asigned char
, and anunsigned char
occupy the same amount of storage and have the same alignment requirements (basic.types); that is, they have the same object representation. For character types, all bits of the object representation participate in the value representation. For unsigned character types, all possible bit patterns of the value representation represent numbers. These requirements do not hold for other types. In any particular implementation, a plainchar
object can take on either the same values as asigned char
or anunsigned char
; which one is implementation-defined.
While most integral types like short
and int
default to being signed
, char
does not have a default signage in C++.
It is neither the type signed char
nor unsigned char
, so implementations may decide whether it is signed.
It's a common mistake that C++ programmers run into when they use char
as an 8 bit integer type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With