Make_signed <unsigned long> :: type is int?
I am using Visual Studio 2010, and the following code confused me a bit:
#include<type_traits> auto x = std::make_signed<unsigned long>::type(); x will be of type int, but I would have expected a long time. I know that int and long in VS10 are 4 byte integers. But even if the signed long fits into int, int for me is not a sign of the integer type corresponding to unsigned long. So my question is: is this a mistake / technical inaccuracy or do standard specifications allow this result?
C ++ 11 20.9.7.3 [meta.trans.sign] describes make_signed :
If
Tcalls (possibly cv-qualified) an integer type (3.9.1), then the member of typedeftypemust indicate the type ofT; otherwise , ifTcalls (possibly cv-qualified) an unsigned integer type, thentypemust name the corresponding signed integer type with the same cv-qualifiers asT[italics]; otherwise,typemust indicate an integer type with the lowest rank value (4.13) for whichsizeof(T) == sizeof(type), with the same cv-qualifiers asTRequired:
Tmust be an (possibly cv-qualified) integral type or enumeration, but not abooltype.
I would consider the "corresponding signed integer type" unsigned long as long . I do not think there is much room for interpretation.
EDIT: There is no room for interpretation as the standard defines “the appropriate type of integer character”. 3.9.1 / 2:
There are five standard standard integer types: "
signed char", "short int", "int", "long int" and "long long int" ....
and 3.9.1 / 3:
For each standard signed integer type, there is a corresponding (but different) standard unsigned integer type: "
unsigned char", "unsigned short int", "unsigned int", "unsigned long int" and "unsigned long long int", each of which occupies the same storage volume and has the same alignment requirements (3.11) as the corresponding type of integer character; that is, each type of integer character has the same representation of the object as its unsigned integer type ....
The corresponding integer character type is unsigned long int , obviously long int .
Perhaps your test might be ruined? I am not sure, since you did not specify the code. However, for such a test, DO NOT use size to determine which type is being returned. Such a test is inaccurate when a long one can have the same size as an int.
For instance:
#include <type_traits> #include <iostream> #include <typeinfo> std::make_signed<unsigned long>::type x; int main() { std::cout<<(sizeof(x) == sizeof(int)); } an implementation is defined and can return true if long is the same size as int. On most systems, this will return true.
Doing:
#include <type_traits> #include <iostream> #include <typeinfo> std::make_signed<unsigned long>::type x; int main() { std::cout<<typeid(x).name(); } will print L if x is long , and it will print I if x is int .