Reputation: 36715
Consider this simple C++-17 program:
#include <iostream>
#include <math.h>
using namespace std;
class Fraction {
public:
int nom;
int den;
Fraction operator+ (const Fraction& other) {
int nn = nom * other.den +
den * other.nom;
int dd = den * other.den;
return Fraction(nn, dd);
}
Fraction(int nn, int dn): nom(nn), den(dn) { }
Fraction(int nn): nom(nn), den(1) { }
operator double() const { return double(nom) / den; }
};
ostream& operator<<(ostream& os, const Fraction& frac) {
return os << frac.nom << '/' << frac.den;
}
int main() {
Fraction f1(1, 4);
cout << "f1 = " << f1 << endl << "f1+2 = " << (f1 + 2) << endl;
return 0;
}
This program yields a compilation error:
main.cpp:35:52: error: use of overloaded operator '+' is ambiguous (with operand types 'Fraction' and 'int')
cout << "f1 = " << f1 << endl << "f1+2 = " << (f1 + 2) << endl;
~~ ^ ~
main.cpp:17:11: note: candidate function
Fraction operator+ (const Fraction& other) {
^
main.cpp:35:52: note: built-in candidate operator+(double, int)
cout << "f1 = " << f1 << endl << "f1+2 = " << (f1 + 2) << endl;
^
However, if I remove either the conversion constructor "Fraction(int nn): nom(nn), den(1) { }" or the conversion operator "operator double() const { return double(nom) / den; }", the program runs fine.
I want to convert both to and from Fraction. What can I do to have both conversions and still have the program compile?
Upvotes: 0
Views: 276
Reputation: 372
From the error, the compiler is complaining as it can't resolve the ambiguity on its own. As it correctly points out there are 2 possible solutions and it doesn't know which one to pick without additional insight from you.
How would you like (f1 + 2)
evaluated, if you want Fraction addition, recommend changing caller to (f1 + Fraction(2))
.
If you instead want double addition, change it to (double(f1)+2)
.
Bottom line, you can continue to have both conversion from fraction to double & integer to fraction construction, but you will need to explicitly specify the behavior you want when there is ambiguity for the compiler.
Upvotes: 2
Reputation: 170055
Make one or both conversion functions explicit
. That will prevent your friendly compiler from implicitly using them when choosing an overload of operator +
based on implicit conversions sequences.
explicit Fraction(int nn): nom(nn), den(1) { }
explicit operator double() const { return double(nom) / den; }
Just bear in mind it prevents all uses of those functions for implicit conversions.
Upvotes: 2