How do I fix an "ambiguous" function call?
Asked Answered
O

4

29

I'm working on a C++ program for class, and my compiler is complaining about an "ambiguous" function call. I suspect that this is because there are several functions defined with different parameters.

How can I tell the compiler which one I want? Aside from a case-specific fix, is there a general rule, such as typecasting, which might solve these kinds of problems?

Edit:

In my case, I tried calling abs() inside of a cout statement, passing in two doubles.

cout << "Amount is:" << abs(amountOrdered-amountPaid);

Edit2:

I'm including these three headers:

#include <iostream>
#include <fstream>
#include <iomanip>

using namespace std;

Edit3:

I've finished the program without this code, but in the interest of following through with this question, I've reproduced the problem. The verbatim error is:

Call to 'abs' is ambiguous.

The compiler offers three versions of abs, each taking a different datatype as a parameter.

Oler answered 26/9, 2011 at 1:34 Comment(6)
Would you please show an example from your code?Gavra
It really depends on the situation. You need to post the code and if the compiler error includes which functions are candidates (recent GCCs do) that helps as well.Titanesque
Also good would be which headers are included.Langley
What is the verbatim error you get?Spongin
@Moshe: Perhaps you could include the rest of the message. You said "The compiler offers three versions of abs", but you haven't shown what those messages are.Gavra
In an unrelated case, it turned out it was possible to fix "Call to member function ... is ambiguous" using std::enable_if_t<std::is_pointer<T>::value, ... This was where behaviour needed to be different for pointers/nonpointers and the respective overloads were not being matched intuitively.Bisector
L
23

What's happened is that you've included <cstdlib> (indirectly, since it's included by iostream) along with using namespace std;. This header declares two functions in std with the name abs(). One takes and returns long long, and the other returns long. Plus, there's the one in the global namespace (that returns int) that comes from <stdlib.h>.

To fix: well, the abs() that takes double is in <cmath>, and that will actually give you the answer you want!

Langley answered 26/9, 2011 at 2:8 Comment(3)
TL;DR: avoid using namespace.Oulman
@MatthieuM., I have seen this (sematic) error even when using std::abs() in iOS SDK. The error got removed when I removed std:: and used just abs().Dalmatic
Yeah, the problem is more due to automatic numeric type conversion.Langley
S
5

The abs function included by <cstdlib> is overloaded for int and long and long long. Since you give a double as the argument, the compiler does not have an exact fit, so it tries to convert the double to a type that abs accepts, but it does not know if it should try to convert it to int, long, or long long, hence it's ambiguous.

But you probably really want the abs that takes a double and returns a double. For this you need to include <cmath>. Since the double argument matches exactly, the compiler will not complain.

It seems that <cstdlib> gets included automatically when you include the other headers which should not happen. The compiler should have given error: ‘abs’ was not declared in this scope or something similar.

Spongin answered 26/9, 2011 at 3:49 Comment(2)
abs isn't a function template. Giving a template argument won't work. A static_cast<foo>(bar) would compile (but still give a wrong answer)Langley
@mkb - Thanks, I forgot they are simply overloads not template functions specializations. Edited that part out.Spongin
C
2

Try using fabs defined in <cmath>. It takes float, double and long double as arguments. abs is defined both in <cmath> and <cstdlib>. The difference is abs(int), abs(long) and abs(long long) are defined in <cstdlib> while other versions are defined in <cmath>.

Croaker answered 5/12, 2013 at 13:23 Comment(1)
A common solution to fix this kind of error is use C++ version of the library instead of standard C library, ex: cstdio instead of stdio.h. The C++ libs have name with prefix 'c' and no '.h'Leastways
B
-3

Not sure why this isn't calling the int version of abs but you could try type casting the expression (amountOrdered - amountPaid) as int i.e.

cout <<"Amount is: "<< abs( (int)(amountOrdered - amountPaint) );
Biflagellate answered 26/9, 2011 at 1:52 Comment(2)
"Not sure why this isn't calling the int version of abs" Could it be cause amountOrdered and amountPaid are doubles?Titanesque
You are correct not sure what I was thinking ! @OP compiler is confused which version to call (long or double) because it not sure if it needs to typecast to long or int from double. Mr .R.Martinho - I guess my solution will help the compiler deciding which version to call. So I somewhat stand correct :)Biflagellate

© 2022 - 2024 — McMap. All rights reserved.