26

How does C++ handle function overloading in this case?

#include <iostream>

void func(int x)
{
   std::cout << "integer";
}

void func(short x)
{
   std::cout << "short";
}

int main(void)
{
   func(3);
}

Output: integer

Why is that?

kocica
  • 6,412
  • 2
  • 14
  • 35
Gaurav
  • 329
  • 3
  • 5
  • 50
    Because `3` is integer. – Piotr Wasilewicz Aug 08 '17 at 09:19
  • 3
    Possible duplicate of [How do I write a short literal in C++?](https://stackoverflow.com/questions/208433/how-do-i-write-a-short-literal-in-c) – jpmc26 Aug 08 '17 at 22:31
  • 1
    The answers are correct, but don’t say why. C++ does this for backward-compatibility with C. Historically, C was designed on 16-bit DEC PDP machines and the first versions of it had no `short` type. As it got ported to new architectures and standardized, C kept the assumption that `int` is the native word length, and the most convenient default size to work with. This is also the reason for `char` and other types narrower than `int` getting automatically converted to `int` in some situations: this is faster on many machines, including the PDP. – Davislor Aug 08 '17 at 23:22
  • Also, no C or C++ standard ever said exactly what the ranges of `int`, `long int` or `long long int` are, and they have been different on different architectures. So a rule that a constant has the narrowest type that can hold it would make the same simple, standard-conforming expression have different behavior on two different compilers. – Davislor Aug 08 '17 at 23:27
  • 2
    @Davislor: And yet that is approximately the rule. Integral literals have the smallest type from `int, long, long long`. The inconsistency is that `short` is missing from that list. – MSalters Aug 09 '17 at 07:39
  • 1
    A quick way to check the type is to output `typeid(3).name()` (you must `#include ` for this to work. The result would be `i` in this case. If you cast it to `short`, you'd see `s` instead. – Jir Aug 09 '17 at 07:56
  • 1
    @MSalters Typically, `int` is the platform's native size. If it doesn't fit in an `int`, you'll have to use a `long` or `long long`. But if it does fit in the native word size, that's what you want to use because it's typically what the platform handles best. – David Schwartz Aug 09 '17 at 08:04
  • 1
    @DavidSchwartz: Of course. Not that it really matters in 2017. No current compiler is going to actually cast `short s = 3` from 32 to 16 bits. The language just defines the forma semantics, and it's those semantics which are the result of 20th century technology. – MSalters Aug 09 '17 at 09:00
  • @MSalters Good point. – Davislor Aug 09 '17 at 10:26
  • 3 is an integer, it will not go to func(short x). It instead goes to func(int x) and returns integer. – Alaa Aug 10 '17 at 12:58

5 Answers5

58

Constants have types too. And without a suffix to indicate otherwise, 3 is simply an int constant. The compiler will choose a larger type if the constant is too big, but it won't go for things smaller than an int by default.

Now, it just so happens, that there is no suffix to make a short constant. You'd need to add a cast if you want that particular overload to be called.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
29

Literal 3 is a constant and implicitly is of type int by the language design.

For your short overloaded function execution you have to use short variable:

short s = 3;
fun(s);

or cast the constant properly:

fun((short)3);
fun(static_cast<short>(3));

Type short hasn't suffix like for example long (long l = 42L;), but you can create one.

kocica
  • 6,412
  • 2
  • 14
  • 35
17

Because 3 is an integer.

fun(static_cast<short>(3));

would call the short version.

Or you can use user-defined literals to make a short: See here

doctorlove
  • 18,872
  • 2
  • 46
  • 62
6

You are doing

fun(3);

and 3 is a literal constant integer so the function that better matches the overload is this one

void fun(int x)
{
    std::cout << "integer";
}

feel free to play a litte with the types and casting those like:

fun(short(3));
fun(int(3));
// C++11
auto x = 3;
fun(x);
ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
6

The constant 3 has it's own type, in this case it's an int. You need to explicitly cast your constant to short if you want your overload to execute

fun((short)3);
Boris
  • 358
  • 2
  • 6