Call of overloaded is ambiguous ошибка

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

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-

  1. The number of arguments.
  2. Order of arguments.
  3. 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:

  1. Typecast char to float.
  2. 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;

}

Output

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

}

Output

Overloaded 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-

  1. Typecast float to int.
  2. 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;

}

Output

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

}

Output

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

}

Output

Overloaded function with two int parameter called 
21
Overloaded function with one int parameter called 
10

Time Complexity: O(1)

Auxiliary Space: O(1)

Problem:

You are trying to compile a C/C++ program but you see an error message like

srcmain.cpp:127:21: error: call of overloaded 'abs(uint32_t)' is ambiguous

that refers to a line like

long timedelta = abs(millis() - startTime);

Solution:

Cast the argument to abs() to int or another suitable type:

long timedelta = abs(((int)millis() - startTime));

That should fix the error.

The reason for the error message is that millis() and startTime are both unsigned integers (uint32_t), hence their difference (millis() - startTime) is also an uint32_t. However it makes no sense to compute the abs() of an unsigned integer since the absolute value of an absolute-value integer is  always the same as the input argument.

Then, the compiler tries to cast the uint32_t to any type that is compatible with abs(), like int, float, double, … but it doesn’t know which of those types is the correct one to cast it to.

By saying call of overloaded abs() the compiler is trying to tell you that there are multBiple argument types with which you can call abs(), including intfloat, double, … – a function with the same name but different argument types is called overloaded.

By saying is ambiguous, the compiler is telling you that it doesn’t know which of those variants of abs() it should call.

Note that the compiler does not know that all overloaded variants of abs() fundamentally do the same thing, so it won’t just cast your uint32_t into any arbitrary type. Also, there are tiny details in how the abs() variants work – for example, float abs(float) will do a different calculation compared to double abs(double) since it computes with 32-bit floating point numbers (float) as opposed to 64-bit floating point numbers (double).

Hence, the compiler can’t just assume that they are all the same and it doesn’t matter which one it calls, even though they represent the same underlying mathematical operation

In the Function overloading tutorial, we have seen how to overload a function by providing the same function with different number, type or sequence of arguments. However some of you may get an error, particularly when dealing with floats. Lets take an example to understand what I am talking about.

In this example we are overloading a function sum. While overloading we gave different types of arguments in both the functions so its a valid case of overloading but still we get compilation error in this program.

#include<iostream>
using namespace std;
int sum(int a,int b){
   return a+b;
}
int sum(float a, float b){
   return a+b;
}
int main(){
   cout<<sum(1.3, 2.7);
   return 0;
}

Output:

error: call to 'sum' is ambiguous

The reason is that while calling sum function we passed floating point value to function, assuming that compiler would treat them as float but the fact is that the compiler treat all the floating points numbers as double until unless you specially specify them as float by providing a “f” suffix at their end.

So to solve the issue we need to suffix the arguments with “f” like this:

#include<iostream>
using namespace std;
int sum(int a,int b){
   return a+b;
}
int sum(float a, float b){
   return a+b;
}
int main(){
   cout<<sum(1.3f, 2.7f);
   return 0;
}

Output:

4

lily19

0 / 0 / 0

Регистрация: 30.09.2016

Сообщений: 11

1

14.10.2016, 14:18. Показов 11024. Ответов 6

Метки нет (Все метки)


помогите пожалуйста, выдает ошибку. не знаю где

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
int main()
{double x,y;
cin>>x;
if( x>113) { y= (pow(sin(x),2)*(log(3*x*x-x*2)/log(0.3))*((x+3)/(abs(x))));}
if(x<113) { y=(abs(x-88.5)*exp((-x)*x));}
else {y=((x+3)/abs(x));}
cout<<"y="<<y;
getchar();
}

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

14.10.2016, 14:18

6

7275 / 6220 / 2833

Регистрация: 14.04.2014

Сообщений: 26,871

14.10.2016, 14:53

2

Работает. Где ошибка?



0



lily19

0 / 0 / 0

Регистрация: 30.09.2016

Сообщений: 11

14.10.2016, 14:57

 [ТС]

3

я писала в dev и в онлайн компиляторе в c++shell. ошибка была показана тут:

C++
1
2
3
if( x>113) { y= (pow(sin(x),2)*(log(3*x*x-x*2)/log(0.3))*((x+3)/(abs(x))));}
if(x<113) { y=(abs(x-88.5)*exp((-x)*x));}
else {y=((x+3)/abs(x));}



0



0 / 0 / 0

Регистрация: 13.10.2016

Сообщений: 5

14.10.2016, 14:59

4

abs замени на fabs



0



lily19

0 / 0 / 0

Регистрация: 30.09.2016

Сообщений: 11

14.10.2016, 19:48

 [ТС]

5

мелочь, а важно..спасибо.мне помогло))

Добавлено через 4 часа 43 минуты
если не сложно… первый раз пишу код логической задачи. ошибок не выдает но я все сделал интуитивно. есть данные которые необходимо ввести и ответ. ответ у меня в итоге не совпал …

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
#include<math.h>
#include<stdio.h>
using namespace std;
int main()
{ bool x,y,z,A,B,D,F,E;
cin>>x>>y>>A>>B>>F>>E;
D= (((log(cos(sqrt(x)+exp((-4)*x)))/log(4))/30) >((x-y)+B)||(3*x+sin(3.14159265359*x)-40 >= ((x-2*y)+!A))&&(tan(x/2)/25==((2*x-y)+B)));
E=((x*x*x*x-40)>((x-3*y)+!A) && ((log(15*x*x)/log(5))>=((3*x-y)+B)));
F=((abs(x+y*y)-40)==((3*x-2*y)+!A)&&25);
z= D||E||F;
cout<<"z="<<z;
getchar();
}



0



Падаван С++

447 / 261 / 89

Регистрация: 11.11.2014

Сообщений: 916

14.10.2016, 19:59

6

Цитата
Сообщение от lily19
Посмотреть сообщение

z= D||E||F;

, какой ответ вы ожидаете в этой строке ?



0



GbaLog-

14.10.2016, 20:12


    Исправить ошибку «call of overloaded ‘abs(double&)’ is ambiguous»

Не по теме:

Цитата
Сообщение от lily19
Посмотреть сообщение

я писала

Цитата
Сообщение от lily19
Посмотреть сообщение

я все сделал

Кто же Вы? :scare:



0



  • Forum
  • General C++ Programming
  • Call of overloaded constructor is ambigu

Call of overloaded constructor is ambiguous

When I try to instantiate objects of class Foo in main() of foo.cpp, I keep getting errors about how the call to the overloaded constructor is ambiguous. The compiler seems to not be able to tell between a non-reference parameter input like int num and a lreference parameter input like int &num. It also seems to not be able to tell between a non-reference parameter input and a rreference parameter input like int &&num. Why would this be? If the passed element is not any kind of reference, doesn’t it make a copy of the original element and then pass the copy? Passing by lreference would mean that a pointer to the original element is passed and that the user could manipulate the original element by manipulating the reference, right? Same goes with rreferences? Why is the compiler confused when I clearly sent it something that has to be moved from one place in memory to another without creating a copy?

Relevant error readout and code that I referenced are listed below:

compiler readout

1
2
3
4
5
6
7
8
9
10
11
In function 'int main()':
27:22: error: call of overloaded 'Foo(int&, int&)' is ambiguous
27:22: note: candidates are:
11:9: note: Foo::Foo(int&&, int&&) <near match>
11:9: note:   no known conversion for argument 2 from 'int' to 'int&&'
8:9: note: Foo::Foo(int&, int&)
5:9: note: Foo::Foo(int, int)
28:18: error: call of overloaded 'Foo(int, int)' is ambiguous
28:18: note: candidates are:
11:9: note: Foo::Foo(int&&, int&&)
5:9: note: Foo::Foo(int, int)

foo.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <utility>

class Foo {
    public:
        Foo( int val1, int val2 ):
            num1{ val1 }, num2{ val2 } { }
        
        Foo( int &val1, int &val2 ):
            num1{ val1 }, num2{ val2 } { }
        
        Foo( int &&val1, int &&val2 ):
            num1{ std::move(val1) }, num2{ std::move(val2) } { }
            
            
    private:
        int num1;
        int num2;

};


int main()
{
    int num = 5;
    int num2 = 6;
    
    Foo foo(num, num2);
    Foo foo2(5, 6);
    
    return 0;
}

lvalue and rvalue reference parameters provide a means to overload functions on the value categories of their arguments.

Consider these two overloads of

f

:

1
2
void f(int&) {}
void f(int&&) {}

An expression like

f(e)

calls the first overload when

e

is an lvalue expression; it calls the second overload when

e

is an rvalue expression.

This third overload of

f

does not care about the value category of

e

.
void f(int) {}
Mixing the three functions leads to ambiguity. Which function should be called when the argument is a rvalue?

Last edited on

So because the third overload does not care about the value category, is there a way to represent a non-reference value without causing ambiguity?

How could these not be ambiguous?

1
2
3
4
5
6
7
void f(int n)        { }
void f(const int& n) { }

int main() {
    int n = 42;
    f(n); // ???
}

@dutch- I understand why it would cause ambiguity. See my question above your comment.

Then your question is senseless.

is there a way to represent a non-reference value without causing ambiguity?

References are not objects, and the type of an expression is never a reference. Given the declaration

int& x = y;

The type of the expression

x

is

int

.
What behavior do you want to see, and why do you think you want to see it?

In one of the constructors, I want a copied value to be passed in as a parameter that isn’t referencing the original value. int &x, for example, would pass a pointer to the callee that can then have its original value modified or assigned to some other value. int &&x would be an rvalue that doesn’t have its own assigned place in memory. Neither of these methods of passing some sort of value, from what I understand, are able to pass a value that is a copy of the original value but that can’t affect the original value if the parametrized value is assigned something new.

My above comment was not meant to imply that I never was asking about why the compiler found ambiguities. I was asking about that and @mbozzi clarified it for me. Then I had a question about how I would represent a parameratized value that would be a copy of another value that cannot be altered by the callee. A reference to a value WOULD be able to be alterted by the callee as the parameratized input is pointing to an already existing place in memory. Changing the data of that parameratized input would change what data was held at that same memory address.

Last edited on

If a copy is needed, just pass-by-value?

void f(int) {}

I think, the ambiguity is because you have overloaded constructors, if you just remove other two constructors (&),(&&), then you can achieve what you are saying.

Given we have may varieties of constructors, I think we have to stick to what’s best for us.

Neither of these methods of passing some sort of value, from what I understand, are able to pass a value that is a copy of the original value but that can’t affect the original value if the parametrized value is assigned something new.

Pardon?
If you don’t want the original objects to be changed, just declare the references const:
Foo(const int& val1, const int& val2):

Anyway that’s not a problem in your code, since you anyway copy them into the class prorperties:
num1{ val1 }, num2{ val2 }

The compiler can tell pointers and not pointers apart, if you really, really, really need that (I’m not suggesting it’s a good idea):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <utility>


class MyClass {
public:
    MyClass( int num1_arg, int num2_arg );
    MyClass( const int * const num1_arg, const int * const num2_arg );

private:
    int num1;
    int num2;
};


MyClass::MyClass( int num1_arg, int num2_arg )
    : num1 { num1_arg }
    , num2 { num2_arg }
{
    std::cout << "Arguments passed by copyn";
}


MyClass::MyClass( const int * const num1_arg, const int * const num2_arg )
    : num1 { *num1_arg }
    , num2 { *num2_arg }
{
    std::cout << "Arguments passed by pointersn";
}


int main()
{
    int num1 = 5;
    int num2 = 6;

    MyClass foo1(num1, num2);
    MyClass foo2(13, 666);
    MyClass foo3( &num1, &num2 );
}

Output:

Arguments passed by copy
Arguments passed by copy
Arguments passed by pointers

@Enoizat- I didn’t think about «const». That qualifier would definitely accomplish what I want it to since it would eliminate ambiguity and serve to provide a non-alterable copy.

Topic archived. No new replies allowed.

Я не знаком с шаблонами. Я только начал изучать это. Почему я получаю ошибки в следующей программе?

#include <iostream>
#include <string>
using std::cout;
using std::string;
template<class C>
C min(C a,C b) {
return a<b?a:b;
}
int main()
{
string a="first string";
string b="second string";
cout<<"minimum string is: "<<min(a,b)<<'n';
int c=3,d=5;
cout<<"minimum number is: "<<min(c,d)<<'n';
double e{3.3},f{6.6};
cout<<"minimum number is: "<<min(e,f)<<'n';
char g{'a'},h{'b'};
cout<<"minimum number is: "<<min(g,h)<<'n';
return 0;
}

Ошибки:

13  [Error] call of overloaded 'min(std::string&, std::string&)' is ambiguous

6   [Note] C min(C, C) [with C = std::basic_string<char>]

Пожалуйста, помогите мне.

11

Решение

Здесь происходит две вещи.

Ваша первая проблема заключается в том, что вы включили только часть сообщения об ошибке. Вот ссылка на код, выполняемый в gcc и clang, и одно из полученных сообщений об ошибке (полностью):

main.cpp:13:34: error: call to 'min' is ambiguous
cout<<"minimum string is: "<<min(a,b)<<'n';
^~~
/usr/include/c++/v1/algorithm:2579:1: note: candidate function [with _Tp = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >]
min(const _Tp& __a, const _Tp& __b)
^
main.cpp:6:3: note: candidate function [with C = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >]
C min(C a,C b) {
^

Есть два кандидата. Один в main.cpp:6:3 (строка 6, символ 3) и один на algorithm:2579:1 (строка 2579, символ 1).

Один из них ты написал, а один из них в #include <algorithm>,

Один из ваших заголовочных файлов включен <algorithm> без тебя об этом. Стандартные заголовки могут делать это, как бы это ни раздражало.

В <algorithm> Eсть std::min шаблон функции. Как std::string это экземпляр класса шаблона в namespace std, шаблон функции std::min обнаруживается с помощью процесса, называемого «поиск с учетом аргументов» или «поиск по Кенигу». (Кандидаты перегрузки функции ищутся локально, а также в пространствах имен аргументов функции, а также в пространствах имен аргументов шаблона для аргументов функции и в пространствах имен вещей, на которые указывают аргументы объекта. функция и т. д.)

Ваша местная функция min также находится в том же пространстве имен, что и тело main,

Оба одинаково хороши, и компилятор не может решить, какой из них вы хотите вызвать. Так что выдает ошибку, сообщающую вам об этом.

И gcc и clang делают error: затем последовательность note:s. Обычно все из note:s после ошибки важны для понимания ошибки.

Чтобы это исправить, попробуйте позвонить ::min (полностью квалифицируя вызов), или переименовав функцию во что-то другое, или сделайте вашу версию более подходящей, чем std::min (сложно, но выполнимо в некоторых случаях), или вызов (min)(a,b), Последний блокирует поиск ADL / Koenig, а также блокирует раскрытие макроса (например, если какая-то ОС вставила #define min макросы в их системные заголовки) (через @ 0x499602D2).

14

Другие решения

Вы столкнулись с именным столкновением с std::min, Скорее всего, он включен в один из других стандартных заголовков библиотеки, которые вы включили, либо <iostream> или же <string>моё предположение, вероятно, последнее. Быстрое решение состоит в том, чтобы переименовать вашу функцию. Например, переименовав его в mymin работает отлично. демонстрация

5

Понравилась статья? Поделить с друзьями:
  • Call of duty ошибка fatal error
  • Call of duty ошибка 103295
  • Call of duty критическая ошибка warzone
  • Call of duty wwii ошибка при запуске приложения 0xc00000906
  • Call of duty wwii ошибка s2 sp64 ship exe windows 10