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);
}
9
  • unsigned int x = 5; print(x); Solves the problem. Commented Mar 12, 2018 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. Commented Mar 12, 2018 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) Commented Mar 12, 2018 at 21:39
  • 3
    A good reading: en.cppreference.com/w/cpp/language/overload_resolution Commented Mar 12, 2018 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 Commented Mar 12, 2018 at 22:02

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.