Strange type deduction
Asked Answered
I

1

6

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?

Ibo answered 3/5, 2020 at 18:38 Comment(3)
does this answer your question? How do promotion rules workMillhon
Any C++ developer should learn these rules.Cogitate
@Cogitate the problem is that this special case of equal rank contradicts normal math. For example in my code t==-2 mathematically, so you expect that if (t>0) {} fails. but it succeeds.Ibo
M
6

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.

Marna answered 3/5, 2020 at 18:40 Comment(5)
So this is from C++17?Ibo
@Ibo The quotes from the C++ 17 Standard but the same is valid for all C++ Standards and for the C Standard.Marna
No, I just checked with -std=c++11 and it's same.Oscillatory
I personally think this specific promotion is somehow strange and people may get unexpected results. I noticed today when I was using std::min(a,b) because it told me that types are not similar.Ibo
@Oscillatory god bless the students....especially the ones who are studying remotely right now... lolIbo

© 2022 - 2024 — McMap. All rights reserved.