2
votes

I'm making a template class for fractions, the numerator and denominator can be of type int, float or double. When overloading the arithmetic or relational operators it gives errors when I try to add two class, say class A and class B

in the header file "fraction.h"

#include<iostream>
using namespace std;

template <class T>
class fraction
{
friend ostream& operator<< <T>(ostream&, const fraction<T>&);
public:
fraction();
fraction<T>(T, T);
friend fraction<T> operator+(const fraction<T>&, const fraction<T>&);
private:
    T numerator;
    T denominator;
};

template <class T>
fraction<T>::fraction()
{
    numerator = 0;
    denominator = 1;
}

template <class T>
fraction<T>::fraction(T num, T denom)
{
    numerator = num;
    denominator = denom;
}
template <class T>
ostream& operator<<(ostream& osObject, const fraction<T>& frac)
{
osObject << frac.numerator << "/" << frac.denominator;
return osObject;
}

template <class T>
fraction<T> operator+(const fraction<T>& fraction1, const fraction<T>&     fraction2)
{
fraction<T> temp;
temp.numerator = fraction1.numerator * fraction2.denominator + fraction1.denominator * fraction2.numerator;
temp.denominator = fraction1.denominator * fraction2.denominator;

return temp;
}

and in cpp file

#include"fraction.h"

int main()
{
    fraction<int> num1(5,6);
    fraction<double> num2(5.1,6.1);
    fraction<double> num3();

    cout << num1+num2; 
}

I expect it to display 10.1/12.1 but instead, it gives Compiler Error C2678 that says binary '+': no operator found which takes a lefthand operand of type 'fraction' (or there is no acceptable conversion). I spend much time trying to solve this problem, and what I understand now that because num1 and num2 are of different types they cannot be added and because the return of '+' operator is not specified to be of any type. How can I solve this problem?

1

1 Answers

6
votes

Your overloaded operator+ function takes two const fraction<T>& arguments. The problem is that the two arguments you use are of different type, the T template for each are different.

To begin solving it you need to use different types for each argument, which means two template arguments. You also need to have a common type for the returned faction object.

Something like

template <typename U, typename V>
fraction<std::common_type_t<U, V>> operator+(const fraction<U>& fraction1, const fraction<V>& fraction2)
{
    fraction<std::common_type_t<U, V>> temp;

    // ...

    return temp;
}

Note that I use different template argument names for both of them. That's because it should be easier to copy-paste for the friend declaration (that must also be updated to match the new function), and you can't shadow a template argument (that is, because the class have an template argument names T the friend function declaration can't have it as well).