8

Why is this cause a compiler error, stating that my references are ambiguous? I have a float, int and string, which should all create separate function signatures, right?

Here is what I have so far:

#include <iostream>
#include <string>
using namespace std;

int plus(int a, int b);
float plus(float a, float b);
string plus(string a, string b);

int main(void)
{
    int n = plus(3, 4);
    double d = plus(3.2, 4.2);
    string s = plus("he", "llo");
    string s1 = "aaa";
    string s2 = "bbb";
    string s3 = plus(s1, s2);
}

int plus(int a, int b) {
    return a+b;
} // int version

float plus(float a, float b) {
    return a+b;
} // float version

string plus(string a, string b) {
    return a+b;
} // string version
MarJamRob
  • 3,395
  • 7
  • 22
  • 31
  • In this call double d = plus( 3.2, 4.2 ); which function do you expect to be called with floats or ints? – Slava Feb 23 '13 at 06:17
  • Which lines are causing the error? – Barmar Feb 23 '13 at 06:18
  • @Barmar On `int n = plus(3, 4);` `double d = plus(3.2, 4.2);` `string s = plus("he", "llo");` and `string s3 = plus(s1, s2);` all function calls to plus. – MarJamRob Feb 23 '13 at 06:20

2 Answers2

19

First, don't use using namespace std;. In this case, there happens to be a struct called std::plus—oh, wait, never mind, that's actually called plus and its constructor is thrown into the bucket for overload resolution with your function called plus.


Second, you have an ambiguity because 3.2 and 4.2 are of type double and can convert equally well to float or int.

This is a simplification, but when it comes to passing numbers to an overloaded function, C++ basically uses these rules:

  1. If all the arguments exactly match one of the overloads, then use that one.
  2. If all the arguments can be promoted to match one of the overloads, then use that one.
  3. If all the arguments can be numerically converted to match one of the overloads, then use that one.

If you have multiple candidates at a specific level, then that is an ambiguity. Crucially, a double does not promote to a float—that would be a downgrade. So it has to use a standard conversion to a float, which ties with the standard conversion to an int, so those two overloads are ambiguous.

John Calsbeek
  • 35,947
  • 7
  • 94
  • 101
4

Call the float overload like this:

double d = plus(3.2f, 4.2f);

A constant like 3.2 actually has type double.

user1610015
  • 6,561
  • 2
  • 15
  • 18