简体   繁体   中英

make_signed<unsigned long>::type is int?

I'm 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 long. I know that int and long in VS10 are both 4-byte integers. But even if a signed long fits into an int, int for me is not the signed integer type corresponding to unsigned long. So my question: is this a bug/technical inaccuracy or do the specifications of the standard allow this result?

C++11 20.9.7.3 [meta.trans.sign] describes make_signed :

If T names a (possibly cv-qualified) signed integer type (3.9.1) then the member typedef type shall name the type T ; otherwise, if T names a (possibly cv-qualified) unsigned integer type then type shall name the corresponding signed integer type, with the same cv-qualifiers as T [ emphasis added ]; otherwise, type shall name the signed integer type with smallest rank (4.13) for which sizeof(T) == sizeof(type) , with the same cv-qualifiers as T .

Requires: T shall be a (possibly cv-qualified) integral type or enumeration but not a bool type.

I would consider "the corresponding signed integer type" of unsigned long to be long . I don't think there's much room for interpretation.

EDIT: There's no room for interpretation since the standard defines "corresponding signed integer type". 3.9.1/2 states:

There are five standard signed integer types : “ signed char ”, “ short int ”, “ int ”, “ long int ”, and “ long long int ”. ...

and 3.9.1/3:

For each of the standard signed integer types, there exists 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 amount of storage and has the same alignment requirements (3.11) as the corresponding signed integer type; that is, each signed integer type has the same object representation as its corresponding unsigned integer type. ...

The corresponding signed integer type of unsigned long int is clearly long int .

MAYBE your test might be flawed? I'm not sure as you posted no code.. However, for such a test, DO NOT use the size to determine what type is being returned. Such a test is inaccurate when a long can be same size as int.

For example:

#include <type_traits>
#include <iostream>
#include <typeinfo>

std::make_signed<unsigned long>::type x;

int main()
{
    std::cout<<(sizeof(x) == sizeof(int));
}

is implementation defined and can return true if the long is the same size as the 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 a long and it will print I if x is an int .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM