4

I was studying about overloading and I am completely getting confused with promotions. I looked at few articles in SO (implicit conversion sequence in function overloading) and I am sure some more are available, but could not find the right article. I was also referring to http://www.dcs.bbk.ac.uk/~roger/cpp/week20.htm. I was looking at C++ Programming special edition by Stroustrup and came across following explanation.

Finding the right version to call from a set of overloaded functions is done by looking for a best match between the type of the argument expression and the parameters (formal arguments) of the functions. To approximate our notions of what is reasonable, a series of criteria are tried in order: 1 Exact match [2] Match using promotions; [3] Match using standard conversions [4] Match using user-defined conversions [5] Match using the ellipsis ......

void print(int);
void print(double);
void print(long);
void print(char);
void h(char c, int i, short s, float f)
{
    print(s); // integral promotion: invoke print(int)
    print(f); // float to double promotion: print(double)
}

I wrote below code. I was thinking that if I call the function with value of 1, func1(long) will be called because promotion takes place. But I get error message "error: call of overloaded 'func1(int)' is ambiguous". It is not calling the function with even unsigned char type of variable.

Also if I pass call func1(3.4f), func1(double) is called and promotion takes place as per my expectation. Why 1 is not promoted to long int but why float is promoted to double? What integer promotions takeplace?

    void func1(unsigned char speed)
    {
        cout<<"Func1 with unsigned char: speed =" << speed <<" RPM\n";
    }

   void func1(long speed)
    {
        cout<<"Func1 with long Int: speed =" << speed <<" RPM\n";
    }

    void func1(double speed)
    {
        cout<<"Func1 with double: speed =" << speed <<" RPM\n";
    }

    int main(void)
    {
        func1(1);
        func1(3.4f);
        return(0);
    }
gsamaras
  • 71,951
  • 46
  • 188
  • 305
Rajesh
  • 1,085
  • 1
  • 12
  • 25

1 Answers1

2

The standard specifies:

[C++11: 4.13/1]: ("Integer conversion rank")

Every integer type has an integer conversion rank defined as follows:

  • [..]
  • The rank of long long int shall be greater than the rank of long int, which shall be greater than the rank of int, which shall be greater than the rank of short int, which shall be greater than the rank of signed char.
  • The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type.
  • [..]

which calls for ambiguity in your example.

As for func1(3.4f);, it's just a promotion from float to double, and that's the best match, since the other two overloaded methods have long and unsigned char.

Also check this table:

enter image description here

where a subclause specifies:

[conv.fpprom]: (7.7 Floating-point promotion )

  • A prvalue of type float can be converted to a prvalue of type double. The value is unchanged.
  • This conversion is called floating-point promotion.
Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • Thanks @StoryTeller! Well yes, but isn't a double a better match? – gsamaras Sep 11 '17 at 08:24
  • @StoryTeller thank you for helping me improve my answer. I updated, how does it look now? – gsamaras Sep 11 '17 at 08:29
  • That means in case of integer type, no promotion happens and we need overloaded functions for every integer type? Also if I have func1(char) and func1(unsigned char) how can I see if func1(unsigned char) function is called? Probably I need to pass a character having ASCII value more than 127 which may not be possible from a keyboard! – Rajesh Sep 11 '17 at 08:33
  • You could always cast the parameter @Rajesh. – gsamaras Sep 11 '17 at 08:34