2

Look about this code (for example) :

#include <iostream>
void print(unsigned int value);
void print(float value);

int main() {
    print('a');
    print(0);
    print(3.14159);
    return 0;
}

I get the next error:

'print(char)' is ambiguous

What is really the problem here? I understood that more than one function appropiate to any call from the main (to print function). But what is really the rules in function overloading (How can I know what appropiate to what, between which types exists casts and etc.)

How can I know that more than one function appropiate to the call? (more example: that not obvious how to understand that the two functions appropiate to the call)

#include <iostream>

void print(unsigned int value);
void print(int value);

int main() {
    print(2.5);
}
Software_t
  • 576
  • 1
  • 4
  • 13
  • `unsigned int x = 5; print(x);` Solves the problem. – Raindrop7 Mar 12 '18 at 21:37
  • @Raindrop7 prefer to get a explanation than a private example. After you edited you comment: yes, I know that it's solves the problem but it's not explains the rules in function overloading. – Software_t Mar 12 '18 at 21:38
  • Assume nothing about appropriate existing casts. If possible make sure your types match exactly, and if you can't do that then at least ensure that the type size and sign match. (e.g. `unsigned int` and `uint32_t` for a platform-specific implementation, or `char` and `int8_t` as a generic example) – Patrick Roberts Mar 12 '18 at 21:39
  • 3
    A good reading: http://en.cppreference.com/w/cpp/language/overload_resolution – Amadeus Mar 12 '18 at 21:40
  • _How can I know that more than one function appropiate to the call?_ Compiling the code and seeing if compiler complains about it. When it complains, it is your responsability to teach it how to proceed – Amadeus Mar 12 '18 at 22:02
  • _"But what is really the rules in function overloading"_ You can't expect somebody to explain the full rules as an answer here, get a book or find a good tutorial on C++. – Jonathan Wakely Mar 12 '18 at 22:09
  • @JonathanWakely Can you recommend about a good book ? – Software_t Mar 12 '18 at 22:10
  • See [The Definitive C++ Book Guide and List](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282) – Jonathan Wakely Mar 12 '18 at 22:11
  • @Jor.Mal - The C++17 Standard has an entire chapter named "Overloading". It contains 33 pages! Not easy to create a quick summary. :-) – Bo Persson Mar 12 '18 at 23:31

2 Answers2

5

When you are working with function overload there is a lot of work that the compiler does behind the scenes to perform function overloading resolution. The details are to great to list here, however I can provide some links that may be of use and try to describe some of the more important parts.


There are 3 possible results:

  • A match is found. The call is resolved to specific overload
  • No match found. The arguments can not be matched to any overload
  • An ambiguous match is found. Arguments matched more than one overload

The basic order of what the compiler will do is this:

  • Find exact match based on parameter list
  • Tries to find a match through promotion
  • Tries to find a match through standard conversion
  • Tries to find a match through user-defined conversion

So how is it determined if a call is ambiguous?

Since every overload has to have unique parameters and due to the fact that all standard conversions and all user-defined conversions are considered equal; if a function call matches more than one valid declaration-definition candidate through standard or user-defined conversion then the result will be ambiguous.


From Your Example:

void print( unsigned int value );
void print( float value );

print( 'a' );
print( 0 );
print( 3.14159 ); 

In the case of print( 'a' ); C++ can not find an exact match. It will first try to promote 'a' to an int, but there is no print(int) function that is declared-defined. It will then try to use standard conversion, it can convert 'a' to both an unsigned int and a floating point value. And since all standard conversions are considered equal, this results in ambiguity.


To resolve this ambiguity you can either simply declare-define the needed versions of print( type ); or you can explicitly cast the type to one of the provided overload parameter types.

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
1

The errors you get because of missing version of the print:

print('a'); // calling print(int)
print(0);   // calling print(int) 
print(3.14159); // calling print(double) not float

As you can see print(int) and print(double) are missing also print(char) is missing you get those errors. When print(char) for example is not provided then the compiler search for print(int) thus it casts the passed in value to an integer.

To solve it you either add the version of overloaded print or cast explicitly the value passed in:

1- Overload the print:

void print(int value){ cout << "int: " <<  value << endl;}
void print(unsigned int value){ cout << "ui: " <<  value << endl;}
void print(float value){cout << "float: " << value << endl;}
void print(char c){ cout << "Char: " << c << endl;}
void print(double value){cout << "double: " << value << endl;}

2- Casting:

print((unsigned int)'a'); // or (float)
print((unsigned int)0);  // or (float)
print(3.14159f); // or (float)3.14159 or (unsigned int)3.14159
  • Keep in mind that print(3.14159); is a call to print(double); not to float to do it for float: print(3.14159f);
Raindrop7
  • 3,889
  • 3
  • 16
  • 27