Pre-requisite: Function Overloading in C++
Function overloading is a feature of object-oriented programming where two or more functions can have the same name but different parameters. When a function name is overloaded with different jobs it is called Function Overloading. Two or more functions are said to be overloaded if they differ in any of the following-
- The number of arguments.
- Order of arguments.
- Type of arguments.
In Function overloading, sometimes a situation can occur when the compiler is unable to choose between two correctly overloaded functions. This situation is said to be ambiguous.
Ambiguous statements are error-generating statements and the programs containing ambiguity will not compile. Automatic type conversions are the main cause of ambiguity. In C++, the type of argument that is used to call the function is converted into the type of parameters defined by the function.
Let’s understand ambiguity through a few examples.
Call of overloaded function is ambiguous
Example 1: Call of overloaded ‘test(char)’ is ambiguous
How this ambiguity occurs:
Below is the C++ program to demonstrate the ambiguity.
C++
#include <iostream>
using namespace std;
void test( float f)
{
cout << "Overloaded Function with float "
<< "parameter being called" ;
}
void test( double d)
{
cout << "Overloaded Function with double "
<< "parameter being called" ;
}
int main()
{
test( 'a' );
return 0;
}
|
Output:
prog.cpp: In function ‘int main()’:
prog.cpp:25:11: error: call of overloaded ‘test(char)’ is ambiguous
test(‘a’);
^
prog.cpp:8:6: note: candidate: void test(float)
void test(float f)
^
prog.cpp:15:6: note: candidate: void test(double)
void test(double d)
^
Why ambiguity occurs:
When there is no exact type match, the compiler looks for the closest match. The closest match for “test(‘a’);” will be “void test(int a)”, since it is not present, void test(double d) and void (float f)will cause ambiguity. Both are valid conversions. This confusion causes an error message to be displayed and prevents the program from compiling.
Note:
According to the C language specification, any integer type shorter than int, for example, bool, char, short are implicitly converted to int.
A char fits into an int without overflowing or losing precision, which explains the first code. But an int doesn’t fit into a char (overflow), double (lack of precision), or int* (incompatible type).
How to resolve ambiguity:
There are two ways to resolve this ambiguity:
- Typecast char to float.
- Remove either one of the ambiguity generating functions float or double and add overloaded function with an int type parameter.
Solution 1: Typecast char to float
Below is the C++ program to demonstrate how typecasting char to float resolves the issue.
C++
#include <iostream>
using namespace std;
void test( float f)
{
cout << "Overloaded Function with float "
<< "parameter being called" ;
}
void test( double d)
{
cout << "Overloaded Function with double "
<< "parameter being called" ;
}
int main()
{
test(( float )( 'a' ));
return 0;
}
|
OutputOverloaded Function with float parameter being called
Solution 2: Remove either one of the ambiguity generating functions float or double and add overloaded function with an int type parameter.
Below is the C++ program to demonstrate how adding an overloading function with an int type parameter can resolve the ambiguity in the above code.
C++
#include <iostream>
using namespace std;
void test( int f)
{
cout << "Overloaded Function with "
<< "int type parameter called" ;
}
void test( double d)
{
cout << "Overloaded Function with "
<< "double type parameter called" ;
}
int main()
{
test( 'a' );
return 0;
}
|
OutputOverloaded Function with int type parameter called
Example 2: Call of overloaded ‘test(float)’ is ambiguous
How this ambiguity occurs:
Below is the C++ program to demonstrate what will happen in the scenario when the type of float value is used to call the overloaded function and there is no function with the float or double parameters.
C++
#include <iostream>
using namespace std;
void test( int f)
{
cout << "Overloaded Function with "
<< "int type parameter called" ;
}
void test( long l)
{
cout << "Overloaded Function with "
<< "long type parameter called" ;
}
int main()
{
test(2.5f);
return 0;
}
|
Output:
prog.cpp: In function ‘int main()’:
prog.cpp:25:12: error: call of overloaded ‘test(float)’ is ambiguous
test(2.5f);
^
prog.cpp:8:6: note: candidate: void test(int)
void test(int f)
^
prog.cpp:15:6: note: candidate: void test(long int)
void test(long d)
^
Why ambiguity occurs:
The above code will throw an error because the test(2.5f) function call will look for float function if not present it is only promoted to double, but there is no function definition with double or float type of parameter.
Unless explicitly specified all floating-point literals are automatically of type double in C++. In this ambiguity, the variable of a float type is implicitly converted to double type and if there is no overloaded function of float or double type and the function is called with a float value then the program will throw an error.
Note:
The float is converted to double under the following situations:
- The float is an argument to a function call, corresponding to a parameter type double in a function prototype.
- A binary operator has double and float as two argument types.
- A conditional operator has double and float as a second and third operand.
- The float value is cast to double.
- The float value is assigned to double.
How to resolve ambiguity:
There are two ways to resolve the ambiguity-
- Typecast float to int.
- Remove either one of the ambiguity generating functions int or long and add overloaded function with a double type parameter.
Solution 1: Typecast float to int
Below is the C++ program to demonstrate how typecasting float to int resolves the issue.
C++
#include <iostream>
using namespace std;
void test( int f)
{
cout << "Overloaded Function with "
<< "int type parameter called" ;
}
void test( long l)
{
cout << "Overloaded Function with "
<< "long type parameter called" ;
}
int main()
{
test(( int )(2.5f));
return 0;
}
|
OutputOverloaded Function with int type parameter called
Solution 2: Remove either one of the ambiguity generating functions int or long and add overloaded function with a double type parameter.
Below is the C++ program to demonstrate how to resolve this ambiguity by adding an overloaded function with double type parameters.
C++
#include <iostream>
using namespace std;
void test( double d)
{
cout << "Overloaded Function with "
<< "double type parameter called" ;
}
void test( long l)
{
cout << "Overloaded Function with "
<< "long type parameter called" ;
}
int main()
{
test(2.5f);
return 0;
}
|
OutputOverloaded Function with double type parameter called
Call of overloaded function with different number of arguments
Redefinition of ‘void test(int, int) function:
Let’s look at another ambiguity scenario where ambiguity occurs when it is two-parameter and one of the parameters has a default value set.
C++
#include <iostream>
using namespace std;
void test( int i)
{
cout << "Overloaded function with "
<< "one int parameter called " << endl;
cout << i;
}
void test( int i, int j = 5)
{
int sum;
sum = i + j;
cout << "Overloaded function with "
<< "two int parameter called " << endl;
cout << sum;
}
int main()
{
test(10, 11);
test(10);
return 0;
}
|
Output:
prog.cpp: In function ‘void test(int, int)’:
prog.cpp:17:6: error: redefinition of ‘void test(int, int)’
void test(int i, int j = 5)
^
prog.cpp:8:6: note: ‘void test(int, int)’ previously defined here
void test(int i, int j)
^
prog.cpp: In function ‘int main()’:
prog.cpp:35:10: error: too few arguments to function ‘void test(int, int)’
test(10);
^
prog.cpp:8:6: note: declared here
void test(int i, int j)
^
Why ambiguity occurs:
Here, in the unambiguous call statement test(10, 11) two arguments are specified, therefore there is no ambiguity. In the ambiguous call statement test(10), the compiler gets confused about whether to call the first function test() which takes one argument or to call the second test() function with two arguments out of which one is the default. This causes the program to throw an error.
How to resolve the ambiguity:
One solution to resolve the ambiguity is to remove the default value from the overloaded function with two int parameters. Below is the C++ program to demonstrate the above approach-
C++
#include <iostream>
using namespace std;
void test( int i)
{
cout << "Overloaded function with "
<< "one int parameter called " << endl;
cout << i << endl;
}
void test( int i, int j)
{
int sum;
sum = i + j;
cout << "Overloaded function with "
<< "two int parameter called " << endl;
cout << sum << endl;
}
int main()
{
test(10, 11);
test(10);
return 0;
}
|
OutputOverloaded function with two int parameter called
21
Overloaded function with one int parameter called
10
Time Complexity: O(1)
Auxiliary Space: O(1)