28

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.

Moshe
  • 57,511
  • 78
  • 272
  • 425
  • 1
    Would you please show an example from your code? – Greg Hewgill Sep 26 '11 at 01:38
  • 1
    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. – R. Martinho Fernandes Sep 26 '11 at 01:42
  • 2
    Also good would be which headers are included. – Matt K Sep 26 '11 at 01:54
  • 1
    What is the _verbatim_ error you get? – JohnPS Sep 26 '11 at 03:20
  • @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. – Greg Hewgill Sep 28 '11 at 04:02
  • In an unrelated case, it turned out it was possible to fix "Call to member function ... is ambiguous" using `std::enable_if_t::value, ...` This was where behaviour needed to be different for pointers/nonpointers and the respective overloads were not being matched intuitively. – Evgeni Sergeev Nov 10 '20 at 05:36

4 Answers4

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!

Matt K
  • 13,370
  • 2
  • 32
  • 51
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.

JohnPS
  • 2,518
  • 19
  • 17
  • `abs` isn't a function template. Giving a template argument won't work. A `static_cast(bar)` would compile (but still give a wrong answer) – Matt K Sep 26 '11 at 21:34
  • @mkb - Thanks, I forgot they are simply overloads not template functions specializations. Edited that part out. – JohnPS Sep 30 '11 at 21:04
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>.

fr0stw01f
  • 21
  • 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' – Andiana Feb 28 '16 at 09:50
-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) );
Vineet G
  • 175
  • 1
  • 1
  • 8
  • 1
    "Not sure why this isn't calling the int version of abs" Could it be cause `amountOrdered` and `amountPaid` are doubles? – R. Martinho Fernandes Sep 26 '11 at 01:55
  • 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 :) – Vineet G Sep 26 '11 at 01:58