Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange type deduction

Today I saw a really strange type deduction. Here is the code:

unsigned int y = 15;
int k = 5;
auto t = k - y / 2;

Since k is int, I assumed that type of t should be int too. But to my surprise, its type is unsigned int. I cannot find why type is deduced as unsigned int. Any idea why?

like image 824
Afshin Avatar asked May 03 '20 18:05

Afshin


1 Answers

Due to the usual arithmetic conversions if two operands have the same conversion rank and one of the operands has unsigned integer type then the type of the expression has the same unsigned integer type.

From the C++ 17 Standard (5 Expressions, p.#10)

— Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.

Pay attention to that the conversion rank of the type unsigned int is equal to the rank of the type int (signed int). From the C++ 17 Standard (4.13 Integer conversion rank, p.#1)

— The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type

A more interesting example is the following. Let's assume that there are two declarations

unsigned int x = 0;
long y = 0;

and the width of the both types is the same and equal for example to 4 bytes. As it is known the rank of the type long is greater than the rank of the type unsigned int. A question arises what id the type of the expression

x + y

The type of the expression is unsigned long.:)

Here is a demonstrative program but instead of the types long and unsigned int there are used the types long long and unsigned long.

#include <iostream>
#include <iomanip>
#include <type_traits>

int main() 
{
    unsigned long int x = 0;
    long long int y = 0;

    std::cout << "sizeof( unsigned long ) = " 
              << sizeof( unsigned long )
              << '\n';

    std::cout << "sizeof( long long ) = " 
              << sizeof( long long )
              << '\n';

    std::cout << std::boolalpha 
              << std::is_same<unsigned long long, decltype( x + y )>::value
              << '\n';

    return 0;
}

The program output is

sizeof( unsigned long ) = 8
sizeof( long long ) = 8
true

That is the type of the expression x + y is unsigned long long though neither operand of the expression has this type.

like image 66
Vlad from Moscow Avatar answered Nov 15 '22 13:11

Vlad from Moscow