Overloading operators using templates...

S

Starx

I was wondering if someone could help me get around this problem I'm
having. I'm writing a fraction class and would like to overload the
binary arithmetic operators so that when any numerical data type (int,
double, long double, etc.) is used with a fraction it is first
converted to a fraction and then added, the result being a fraction.

So I started with this:

template <class numericType>
friend fraction operator +(const fraction& lhs, const numericType&
rhs);
template <>
friend fraction operator +(const fraction& lhs, const fraction& rhs);

The first function was simply:

{ return lhs + fraction(rhs); }

The second function was a template specialization that did the math
when adding two fractions. This worked great, as long as a fraction
was the first argument I could add it with any other data type that I
had a constructor for. But I also want addition to be commutative so
that "fraction + int" and "int + fraction" do the same thing. To get
that I added this function:

template <class numericType>
friend fraction operator +(const numericType& lhs, const fraction&
rhs);

Which did the same thing as the other function, converted explicitly to
a fraction and then added, relying on the template specialization to
add fractions. But now I get this error:

error C2667: '+' : none of 2 overload have a best conversion

How can I get rid of this? I just want it so that given:
fraction x, y;
int z;

these statements are valid and error free:

x + y;
x + z;
z + x;

I'm running VC++ 6.0
 
L

Larry I Smith

Starx said:
I was wondering if someone could help me get around this problem I'm
having. I'm writing a fraction class and would like to overload the
binary arithmetic operators so that when any numerical data type (int,
double, long double, etc.) is used with a fraction it is first
converted to a fraction and then added, the result being a fraction.

So I started with this:

template <class numericType>
friend fraction operator +(const fraction& lhs, const numericType&
rhs);
template <>
friend fraction operator +(const fraction& lhs, const fraction& rhs);

The first function was simply:

{ return lhs + fraction(rhs); }

The second function was a template specialization that did the math
when adding two fractions. This worked great, as long as a fraction
was the first argument I could add it with any other data type that I
had a constructor for. But I also want addition to be commutative so
that "fraction + int" and "int + fraction" do the same thing. To get
that I added this function:

template <class numericType>
friend fraction operator +(const numericType& lhs, const fraction&
rhs);

Which did the same thing as the other function, converted explicitly to
a fraction and then added, relying on the template specialization to
add fractions. But now I get this error:

error C2667: '+' : none of 2 overload have a best conversion

How can I get rid of this? I just want it so that given:
fraction x, y;
int z;

these statements are valid and error free:

x + y;
x + z;
z + x;

I'm running VC++ 6.0

If class 'fraction' has constructors for each of the
required numeric types (fraction(int), fraction(long),
fraction(double), etc), then you should only need one
friend operator+() method that takes 2 'fraction'
objects. If a numeric is specified on either side
of the "+" (z + x, or x + z), the compiler should
apply the correct conversion constructor before
invoking the operator+().

Here's an example:

#include <iostream>

// a dummy 'fraction' class for experimental purposes
class fraction
{
public:
fraction() : vd(0) {}
fraction(const int v) : vd(v) {}
fraction(const long v) : vd(v) {}
fraction(const double v) : vd(v) {}

fraction operator=(const fraction& oth)
{ vd = oth.vd; vi = oth.vi; }

friend fraction operator+(const fraction& rhs, const fraction& lhs);

int vi;
double vd;
};


fraction operator+(const fraction& rhs, const fraction& lhs)
{ return fraction(rhs.vd + lhs.vd); }

int main()
{
fraction fx(25.34), fy(30), fr;
int iz = 66;
long lz = 530;

std::cout << "fx = " << fx.vd << ", "
<< "fy = " << fy.vd << ", "
<< "iz = " << iz << ", "
<< "lz = " << lz << std::endl;

fr = fx + fy;
std::cout << "fx + fy = " << fr.vd << std::endl;

fr = fx + iz; // 'iz' is converted to a 'fraction'
std::cout << "fx + iz = " << fr.vd << std::endl;

fr = iz + fx; // 'iz' is converted to a 'fraction'
std::cout << "iz + fx = " << fr.vd << std::endl;

fr = lz + fx; // 'lz' is converted to a 'fraction'
std::cout << "lz + fx = " << fr.vd << std::endl;

fr = 99 + fy; // 99 is converted to a fraction
std::cout << "99 + fy = " << fr.vd << std::endl;

fr = fy + 99; // 99 is converted to a fraction
std::cout << "fy + 99 = " << fr.vd << std::endl;

return 0;
}

Regards,
Larry
 
L

Larry I Smith

Larry I Smith wrote:
[snip]
If class 'fraction' has constructors for each of the
required numeric types (fraction(int), fraction(long),
fraction(double), etc), then you should only need one
friend operator+() method that takes 2 'fraction'
objects. If a numeric is specified on either side
of the "+" (z + x, or x + z), the compiler should
apply the correct conversion constructor before
invoking the operator+().
[snip]

Don't forget to include constructors for any required
unsigned types, e.g.: fraction(unsigned int), etc.

Larry
 
S

Starx

My constructor is flagged with the explicit keyword. I did this
because I was also trying to overload the pow function. I wanted to
write different versions for fraction and int powers to optimize the
way it did the math, but if I don't make the constructor explicit it
says those version are ambiguous.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top