Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ auto on int16_t casts to integer

I am pretty new to C++17 and am attempting to understand the decltype keyword and how it pairs with auto.

Below is a snippet of code that produces an unexpected result.

#include <typeinfo>
#include <iostream>
#include <algorithm>

using namespace std;

int main() {

  int16_t mid = 4;
  auto low = mid - static_cast<int16_t>(2);
  auto hi = mid + static_cast<int16_t>(2);

  int16_t val;
  cin >> val;

  val = std::clamp(val,low,hi);

  return 0;
}

Surprisingly, the compiler tells me there is a mismatch in clamp and that low and high are int. If I change auto to int16_t all is good in the world and all the types are int16_t as expected.

The question I'm posing is, why does auto cast low and hi to int when all of the types are int16_t? Is this a good use case for decltype?

Even after reading cppreference.com, I don't fully understand how decltype works, so excuse my ignorance.

like image 471
Max Avatar asked Apr 12 '19 04:04

Max


People also ask

What does casting to an int do?

Casting to an int will truncate toward zero. floor() will truncate toward negative infinite. This will give you different values if bar were negative.

Can we convert int to double in C?

The %d format specifier expects an int argument, but you're passing a double . Using the wrong format specifier invokes undefined behavior. To print a double , use %f .

What is UINT8 in Cpp?

A UINT8 is an 8-bit unsigned integer (range: 0 through 255 decimal).


1 Answers

The problem isn't with auto here. When you subtract two int16_t values, the result is an int. We can demonstrate it with this code here:

#include <iostream>
#include <cstdint>
using namespace std;

template<class T>
void print_type(T) {
    std::cout << __PRETTY_FUNCTION__ << std::endl; 
}

int main() {
    int16_t a = 10;
    int16_t b = 20;
    print_type(a);
    print_type(b);
    print_type(a - b); 
    return 0;
}

a and b are both short ints, but when you add or subtract them it produces a regular int. This is to help prevent overflow / and is also for backwards compatibility.

like image 132
Alecto Irene Perez Avatar answered Sep 18 '22 06:09

Alecto Irene Perez