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:
- If all the arguments exactly match one of the overloads, then use that one.
- If all the arguments can be promoted to match one of the overloads, then use that one.
- 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.