operator overloading question

N

none

Why are you throwing away the imaginary part? Why all the copies? Why
even write the function when the compiler supplied op= does the right
thing?

because it's a complex number = a real number;
complex = real => complex = real + 0i

the 2 copies are there to provide
complex = complex and complex = real

I'm currently trying to figure out what's wrong with this code
so maybe there's some useless parts for the moment.

isn't compiler supplied op= only for complex = complex?
 
D

Daniel T.

none said:
I was able to do what I wanted, but not exactly the way I would
like it to work. I choose this method because I don't want to
make 3 copies for each operators overload (int,complex), (complex,int)
and (complex,complex). This way I only have to build
a function for each operators.

I'm able to do this:

COMPLEX complex;
COMPLEX complex2;

complex.real = 1;
complex.img = 3;

complex2 = (COMPLEX) 3 + complex;
complex = complex2 + (COMPLEX) 5;

but I would like to do:

complex2 = 3 + complex;
complex = complex2 + 5;

template < typename T >
class Complex
{
public:
Complex(): real(0), imag(0) { }
Complex( T r, T i ): real(r), imag(i) { }
T real;
T imag;
};

template < typename T >
Complex<T> operator+( T left, const Complex<T>& right )
{
return Complex<T>( left + right.real, right.imag );
}

template < typename T >
Complex<T> operator+( const Complex<T>& left, T right )
{
return Complex<T>( left.real + right, left.imag );
}

int main(int argc, char* argv[])
{
Complex<int> complex;
Complex<int> complex2;

complex.real = 5;
complex.imag = 2;

complex2 = 1 + complex;
assert( complex2.real == 6 );
assert( complex2.imag == 2 );

complex2 = complex + 1;
assert( complex2.real == 6 );
assert( complex2.imag == 2 );
}
but I get this error:

error C2784: 'class Ccomplex<COMPLEXTYPE> &__cdecl operator +(class
Ccomplex<COMPLEXTYPE> &,class Ccomplex<COMPLEXTYPE> &)' : could not
deduce template argument for 'class Ccomplex<COMPLEXTYPE> &' from
'const int'

Anyone knows how I could do what I want to do?

By the way I forgot about:
int integer = complex; // integer = complex.real
because I think Daniel T. is right and it's not a smart thing
to do and can be very confusing.

here's a sample of my code :

Unfortunately, your code is riddled with errors. Try posting your actual
code and I'll be happy to review it. In general though, you are making
this way harder on yourself than it has to be. There are all kinds of
unnecessary constructs in your code, and other stuff that is missing but
must be there.
// mycomplex.h

template <class COMPLEXTYPE> class Ccomplex;

template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE>& operator + (Ccomplex<COMPLEXTYPE> &dest,
\
Ccomplex<COMPLEXTYPE>
&source);
// also tried
// inline Ccomplex<COMPLEXTYPE> operator + (Ccomplex<COMPLEXTYPE>
dest, \
// Ccomplex<COMPLEXTYPE>
source);

template <class COMPLEXTYPE>
class Ccomplex
{
public:
COMPLEXTYPE real;
COMPLEXTYPE img;

// Constructor
Ccomplex (void)
{
real = 0;
img = 0;
}

// Constructor (conversion operator)
Ccomplex (COMPLEXTYPE val)
{
real = val;
img = 0;
}

// Destructor
~Ccomplex (void) { }

inline Ccomplex<COMPLEXTYPE> operator = (Ccomplex<COMPLEXTYPE>
source);

friend inline Ccomplex<COMPLEXTYPE>& operator +
(Ccomplex<COMPLEXTYPE> &dest, \

Ccomplex<COMPLEXTYPE> &source);
// also tried
// friend inline Ccomplex<COMPLEXTYPE> operator +
(Ccomplex<COMPLEXTYPE> dest, \
//
Ccomplex<COMPLEXTYPE> source);

protected:
};

typedef Ccomplex<int> COMPLEX;




// mycomplex.cpp

#include "complex.h"

template <class COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> Ccomplex<COMPLEXTYPE>::eek:perator =
(Ccomplex<COMPLEXTYPE> source)
{
this->real = source.real;
this->img = source.img;
return *this;
}

template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE>& operator + (Ccomplex<COMPLEXTYPE> &dest,
\
Ccomplex<COMPLEXTYPE>
&source)
{
dest.real = dest.real + source.real;
dest.img = dest.img + source.img;
return dest;
}

template class Ccomplex<int>;

Spurious ';'
template Ccomplex<int>& operator + (Ccomplex<int> &dest, \
Ccomplex<int> &source);

Function above declared but not defined. It's wholly unnecessary anyway.
// program.cpp

#include "complex.h"

int main(FT_INT argc, FT_CHAR* argv[])

FT_INT and FT_CHAR were not declared. Use 'int' and 'char' instead.
{
KCOMPLEX complex;
KCOMPLEX complex2;

KCOMPLEX was not declared. I changed them to COMPLEX.
complex.real = 5;
complex.img = 2;

// WORKS
complex2 = (COMPLEX) 1 + complex;

The above doesn't work. You are creating a temporary and because your
op+ takes its parameters by non-const reference, it can't be used.
 
N

none

 none said:
I was able to do what I wanted, but not exactly the way I would
like it to work. I choose this method because I don't want to
make 3 copies for each operators overload (int,complex), (complex,int)
and (complex,complex). This way I only have to build
a function for each operators.
I'm able to do this:
COMPLEX complex;
COMPLEX complex2;
complex.real = 1;
complex.img  = 3;
complex2 = (COMPLEX) 3 + complex;
complex  = complex2    + (COMPLEX) 5;
but I would like to do:
complex2 = 3 + complex;
complex  = complex2 + 5;

   template < typename T >
class Complex
{
public:
   Complex(): real(0), imag(0) { }
   Complex( T r, T i ): real(r), imag(i) { }
   T real;
   T imag;

};

template < typename T >
Complex<T> operator+( T left, const Complex<T>& right )
{
   return Complex<T>( left + right.real, right.imag );

}

template < typename T >
Complex<T> operator+( const Complex<T>& left, T right )
{
   return Complex<T>( left.real + right, left.imag );

}

int main(int argc, char* argv[])
{
   Complex<int> complex;
   Complex<int> complex2;

   complex.real = 5;
   complex.imag  = 2;

   complex2 = 1 + complex;
   assert( complex2.real == 6 );
   assert( complex2.imag == 2 );

   complex2 = complex + 1;
   assert( complex2.real == 6 );
   assert( complex2.imag == 2 );





}
but I get this error:
error C2784: 'class Ccomplex<COMPLEXTYPE> &__cdecl operator +(class
Ccomplex<COMPLEXTYPE> &,class Ccomplex<COMPLEXTYPE> &)' : could not
deduce template argument for 'class Ccomplex<COMPLEXTYPE> &' from
'const int'
Anyone knows how I could do what I want to do?
By the way I forgot about:
int integer = complex; // integer = complex.real
because I think Daniel T. is right and it's not a smart thing
to do and can be very confusing.
here's a sample of my code :

Unfortunately, your code is riddled with errors. Try posting your actual
code and I'll be happy to review it. In general though, you are making
this way harder on yourself than it has to be. There are all kinds of
unnecessary constructs in your code, and other stuff that is missing but
must be there.




// mycomplex.h
template <class COMPLEXTYPE> class Ccomplex;
template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE>& operator + (Ccomplex<COMPLEXTYPE> &dest,
\
                                          Ccomplex<COMPLEXTYPE>
&source);
// also tried
// inline Ccomplex<COMPLEXTYPE> operator + (Ccomplex<COMPLEXTYPE>
dest, \
//                                          Ccomplex<COMPLEXTYPE>
source);
template <class COMPLEXTYPE>
class Ccomplex
{
 public:
   COMPLEXTYPE real;
   COMPLEXTYPE img;
   // Constructor
   Ccomplex (void)
   {
    real = 0;
    img  = 0;
   }
   // Constructor (conversion operator)
   Ccomplex (COMPLEXTYPE val)
   {
    real = val;
    img  = 0;
   }
   // Destructor
   ~Ccomplex (void) { }
   inline Ccomplex<COMPLEXTYPE> operator = (Ccomplex<COMPLEXTYPE>
source);
   friend inline Ccomplex<COMPLEXTYPE>& operator +
(Ccomplex<COMPLEXTYPE> &dest, \
Ccomplex<COMPLEXTYPE> &source);
   // also tried
   // friend inline Ccomplex<COMPLEXTYPE> operator +
(Ccomplex<COMPLEXTYPE> dest, \
   //
Ccomplex<COMPLEXTYPE> source);

typedef Ccomplex<int> COMPLEX;
// mycomplex.cpp
#include "complex.h"
template <class COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> Ccomplex<COMPLEXTYPE>::eek:perator =
(Ccomplex<COMPLEXTYPE> source)
{
  this->real = source.real;
  this->img  = source.img;
  return *this;
}
template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE>& operator + (Ccomplex<COMPLEXTYPE> &dest,
\
                                          Ccomplex<COMPLEXTYPE>
&source)
{
  dest.real = dest.real + source.real;
  dest.img  = dest.img  + source.img;
  return dest;
}
template class Ccomplex<int>;

Spurious ';'
template Ccomplex<int>& operator + (Ccomplex<int> &dest, \
                                    Ccomplex<int> &source);

Function above declared but not defined. It's wholly unnecessary anyway.


// program.cpp
#include "complex.h"
int main(FT_INT argc, FT_CHAR* argv[])

FT_INT and FT_CHAR were not declared. Use 'int' and 'char' instead.
{
    KCOMPLEX complex;
    KCOMPLEX complex2;

KCOMPLEX was not declared. I changed them to COMPLEX.
    complex.real = 5;
    complex.img  = 2;
    // WORKS
    complex2 = (COMPLEX) 1 + complex;

The above doesn't work. You are creating a temporary and because your
op+ takes its parameters by non-const reference, it can't be used.


    complex  = complex2 + (COMPLEX) 2;
    // DO NOT WORK
    // error C2784: 'class Ccomplex<COMPLEXTYPE> &__cdecl operator +
(class Ccomplex<COMPLEXTYPE> &,
    //               class Ccomplex<COMPLEXTYPE> &)' : could not
deduce template argument for
    //              'class Ccomplex<COMPLEXTYPE> &' from 'const int'
    complex2 = 1 + complex;
    complex  = complex2 + 2;
    return 0;
}- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -

Sorry about the errors, I didn't test before posting it. Here's
a new working, cleaned and tested code. I have removed a lot
of things to make it simplier and I do not use multiple files
anymore for simplicity.

Now this code works fine like this:

COMPLEX complex1,complex2;
complex1 = 2.0 + complex2;
complex2 = complex1 + 4.0;

But I have to use a double notation to prevent compiler error
(ambiguity between int and double), I would like to be able to
write it as 1 + complex. And I also need to declare these
operator + overloads to type cast the values:

inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest, const COMPLEXTYPE source);
inline Ccomplex<COMPLEXTYPE> operator + \
(const COMPLEXTYPE dest, Ccomplex<COMPLEXTYPE> source);

I'm sure there's a better way to do this, I would really like
to be able to declare only one operator overload for each
operators. By the way I think I'm may be missing some important
points about templates, I find the class and typename keywords
really confusion. Should I use typename for member types and
class only for objects? (there's no informations about
templates in any of my C++ books)

for example:
template <class COMPLEXTYPE, typename TYPENAME>
class Ccomplex
{
public:
TYPENAME real;
TYPENAME img;
...
inline Ccomplex<COMPLEXTYPE,TYPENAME> operator = \
(Ccomplex<COMPLEXTYPE,TYPENAME> source);
...
}

or am I doing it the right way?

thanks a lot for your help, your are really helpful!


// ------------------------------------------------------------

template <class COMPLEXTYPE>
class Ccomplex
{
public:
COMPLEXTYPE real;
COMPLEXTYPE img;

// Constructor
Ccomplex (void)
{
real = 0;
img = 0;
}

// Constructor (conversion operator)
Ccomplex (COMPLEXTYPE val)
{
real = val;
img = 0;
}

// Destructor
~Ccomplex (void) { }

inline Ccomplex<COMPLEXTYPE> operator = (Ccomplex<COMPLEXTYPE>
source);

friend inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest, Ccomplex<COMPLEXTYPE>
source);
friend inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest, const COMPLEXTYPE
source);
friend inline Ccomplex<COMPLEXTYPE> operator + \
(const COMPLEXTYPE dest, Ccomplex<COMPLEXTYPE>
source);

protected:
};

typedef Ccomplex<double> COMPLEX;

template <class COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> \
Ccomplex<COMPLEXTYPE>::eek:perator = (Ccomplex<COMPLEXTYPE>
source)
{
this->real = source.real;
this->img = source.img;
return *this;
}

template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest, Ccomplex<COMPLEXTYPE> source)
{
Ccomplex<COMPLEXTYPE> newdest;
newdest.real = dest.real + source.real;
newdest.img = dest.img + source.img;
return newdest;
}

template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest,const COMPLEXTYPE source)
{ return dest + (Ccomplex<COMPLEXTYPE>) source; }
template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
(const COMPLEXTYPE dest, Ccomplex<COMPLEXTYPE> source)
{ return (Ccomplex<COMPLEXTYPE>) dest + source; }

int main(int argc, char* argv[])
{
COMPLEX complex;
COMPLEX complex2;

complex.real = 5;
complex.img = 2;

// WORKS
complex2 = (COMPLEX) 1 + complex;
complex = complex2 + (COMPLEX) 2;

// WORKS but must use double notation to avoid
// template ambiguities between in and double
complex2 = 1.0 + complex;
complex = complex2 + 2.0;

return 0;
}
 
D

Daniel T.

none said:
because it's a complex number = a real number;
complex = real => complex = real + 0i

the 2 copies are there to provide
complex = complex and complex = real

I'm currently trying to figure out what's wrong with this code
so maybe there's some useless parts for the moment.

isn't compiler supplied op= only for complex = complex?

Right, my mistake.
 
N

none

Right, my mistake.- Hide quoted text -

- Show quoted text -

Ok, I was able to make it work the way I wanted to work, this
code now works fine:

complex2 = 1 + complex1;
complex1 = complex2 + 2;

And now I do not have to add 3 overloads for each operators,
only one is fine.

I had to add this conversion operator:

operator COMPLEXTYPE ()
{
return real;
}

I'm not sure why it make it work, because I don't see where
Ccomplex<COMPLEXTYPE> is converted to COMPLEXTYPE.

What do you think does it look fine to you?

Here's the new code:
------------------------------------------------------------

template <class COMPLEXTYPE>
class Ccomplex
{
public:
COMPLEXTYPE real;
COMPLEXTYPE img;

// Constructor
Ccomplex (void)
{
real = 0;
img = 0;
}

// Constructor (conversion operator)
Ccomplex (COMPLEXTYPE val)
{
real = val;
img = 0;
}

// convert Ccomplex to real (COMPLEXTYPE)
operator COMPLEXTYPE ()
{
return real;
}

// Destructor
~Ccomplex (void) { }

// Ccomplex = Ccomplex overload
inline Ccomplex<COMPLEXTYPE> operator = (Ccomplex<COMPLEXTYPE>
source)
{
this->real = source.real;
this->img = source.img;
return *this;
}

// Ccomplex = real (COMPLEXTYPE) overload
inline Ccomplex<COMPLEXTYPE> operator = (COMPLEXTYPE source)
{
this->real = source;
this->img = 0;
return *this;
}

friend inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest, \
Ccomplex<COMPLEXTYPE> source);

protected:
};

typedef Ccomplex<double> COMPLEX;

template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest, Ccomplex<COMPLEXTYPE> source)
{
Ccomplex<COMPLEXTYPE> newdest;
newdest.real = dest.real + source.real;
newdest.img = dest.img + source.img;
return newdest;
}

int main(int argc, char* argv[])
{
COMPLEX complex1;
COMPLEX complex2;

complex1.real = 5;
complex1.img = 2;

// WORKS
complex2 = complex1;

// WORKS
complex2 = (COMPLEX) 1 + complex1;
complex1 = complex2 + (COMPLEX) 2;

// WORKS
complex2 = 1 + complex1;
complex1 = complex2 + 2;

return 0;
}
 
N

none

Right, my mistake.- Hide quoted text -
- Show quoted text -

Ok, I was able to make it work the way I wanted to work, this
code now works fine:

    complex2 = 1 + complex1;
    complex1 = complex2 + 2;

And now I do not have to add 3 overloads for each operators,
only one is fine.

I had to add this conversion operator:

   operator COMPLEXTYPE ()
   {
    return real;
   }

I'm not sure why it make it work, because I don't see where
Ccomplex<COMPLEXTYPE> is converted to COMPLEXTYPE.

What do you think does it look fine to you?

Here's the new code:
------------------------------------------------------------

template <class COMPLEXTYPE>
class Ccomplex
{
 public:
   COMPLEXTYPE real;
   COMPLEXTYPE img;

   // Constructor
   Ccomplex (void)
   {
    real = 0;
    img  = 0;
   }

   // Constructor (conversion operator)
   Ccomplex (COMPLEXTYPE val)
   {
    real = val;
    img  = 0;
   }

   // convert Ccomplex to real (COMPLEXTYPE)
   operator COMPLEXTYPE ()
   {
    return real;
   }

   // Destructor
   ~Ccomplex (void) { }

   // Ccomplex = Ccomplex overload
   inline Ccomplex<COMPLEXTYPE> operator = (Ccomplex<COMPLEXTYPE>
source)
   {
    this->real = source.real;
    this->img  = source.img;
    return *this;
   }

   // Ccomplex = real (COMPLEXTYPE) overload
   inline Ccomplex<COMPLEXTYPE> operator = (COMPLEXTYPE source)
   {
    this->real = source;
    this->img  = 0;
    return *this;
   }

   friend inline Ccomplex<COMPLEXTYPE> operator + \
                (Ccomplex<COMPLEXTYPE> dest, \
                 Ccomplex<COMPLEXTYPE> source);

 protected:

};

typedef Ccomplex<double> COMPLEX;

template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
       (Ccomplex<COMPLEXTYPE> dest, Ccomplex<COMPLEXTYPE> source)
{
  Ccomplex<COMPLEXTYPE> newdest;
  newdest.real = dest.real + source.real;
  newdest.img  = dest.img  + source.img;
  return newdest;

}

int main(int argc, char* argv[])
{
    COMPLEX complex1;
    COMPLEX complex2;

    complex1.real = 5;
    complex1.img  = 2;

    // WORKS
    complex2 = complex1;

    // WORKS
    complex2 = (COMPLEX) 1 + complex1;
    complex1 = complex2 + (COMPLEX) 2;

    // WORKS
    complex2 = 1 + complex1;
    complex1 = complex2 + 2;

    return 0;



}- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -

I just found out a bug in my code, a these lines:

complex2 = 1 + complex1;
complex1 = complex2 + 2;

The imaginary part is set to 0, I'm currently trying to figure out
why.
if complex2 = 1+2i it should be:
complex1 = 1+2i + 2+0i = 3+2i
but in my code it's 3+0i.
 
N

none

Ok, I was able to make it work the way I wanted to work, this
code now works fine:
    complex2 = 1 + complex1;
    complex1 = complex2 + 2;
And now I do not have to add 3 overloads for each operators,
only one is fine.
I had to add this conversion operator:
   operator COMPLEXTYPE ()
   {
    return real;
   }
I'm not sure why it make it work, because I don't see where
Ccomplex<COMPLEXTYPE> is converted to COMPLEXTYPE.
What do you think does it look fine to you?
Here's the new code:
------------------------------------------------------------
template <class COMPLEXTYPE>
class Ccomplex
{
 public:
   COMPLEXTYPE real;
   COMPLEXTYPE img;
   // Constructor
   Ccomplex (void)
   {
    real = 0;
    img  = 0;
   }
   // Constructor (conversion operator)
   Ccomplex (COMPLEXTYPE val)
   {
    real = val;
    img  = 0;
   }
   // convert Ccomplex to real (COMPLEXTYPE)
   operator COMPLEXTYPE ()
   {
    return real;
   }
   // Destructor
   ~Ccomplex (void) { }
   // Ccomplex = Ccomplex overload
   inline Ccomplex<COMPLEXTYPE> operator = (Ccomplex<COMPLEXTYPE>
source)
   {
    this->real = source.real;
    this->img  = source.img;
    return *this;
   }
   // Ccomplex = real (COMPLEXTYPE) overload
   inline Ccomplex<COMPLEXTYPE> operator = (COMPLEXTYPE source)
   {
    this->real = source;
    this->img  = 0;
    return *this;
   }
   friend inline Ccomplex<COMPLEXTYPE> operator + \
                (Ccomplex<COMPLEXTYPE> dest, \
                 Ccomplex<COMPLEXTYPE> source);


typedef Ccomplex<double> COMPLEX;
template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
       (Ccomplex<COMPLEXTYPE> dest, Ccomplex<COMPLEXTYPE> source)
{
  Ccomplex<COMPLEXTYPE> newdest;
  newdest.real = dest.real + source.real;
  newdest.img  = dest.img  + source.img;
  return newdest;

int main(int argc, char* argv[])
{
    COMPLEX complex1;
    COMPLEX complex2;
    complex1.real = 5;
    complex1.img  = 2;
    // WORKS
    complex2 = complex1;
    // WORKS
    complex2 = (COMPLEX) 1 + complex1;
    complex1 = complex2 + (COMPLEX) 2;
    // WORKS
    complex2 = 1 + complex1;
    complex1 = complex2 + 2;
    return 0;
}- Hide quoted text -
- Show quoted text -- Hide quoted text -
- Show quoted text -

I just found out a bug in my code, a these lines:

complex2 = 1 + complex1;
complex1 = complex2 + 2;

The imaginary part is set to 0, I'm currently trying to figure out
why.
if complex2 = 1+2i it should be:
complex1 = 1+2i + 2+0i = 3+2i
but in my code it's 3+0i.- Hide quoted text -

- Show quoted text -

I found out the problem, but I cannot remove this line
because I won't be able to do something like this:

Ccomplex complex1 = 3; // complex1 = 3+0i

inline Ccomplex<COMPLEXTYPE> operator = (COMPLEXTYPE source)
{
this->real = source;
// THIS IS THE PROBLEM:
this->img = 0;
return *this;
}
 
N

none

And I have added this assignment operator as a member
of the class:
inline Ccomplex<COMPLEXTYPE> operator = (COMPLEXTYPE source)
{
  this->real = source;
  this->img  = 0;
  return *this;
}
Why are you throwing away the imaginary part? Why all the copies? Why
even write the function when the compiler supplied op= does the right
thing?
because it's a complex number = a real number;
complex = real => complex = real + 0i
the 2 copies are there to provide
complex = complex and complex = real
I'm currently trying to figure out what's wrong with this code
so maybe there's some useless parts for the moment.
isn't compiler supplied op= only for complex = complex?
Right, my mistake.- Hide quoted text -
- Show quoted text -
Ok, I was able to make it work the way I wanted to work, this
code now works fine:
    complex2 = 1 + complex1;
    complex1 = complex2 + 2;
And now I do not have to add 3 overloads for each operators,
only one is fine.
I had to add this conversion operator:
   operator COMPLEXTYPE ()
   {
    return real;
   }
I'm not sure why it make it work, because I don't see where
Ccomplex<COMPLEXTYPE> is converted to COMPLEXTYPE.
What do you think does it look fine to you?
Here's the new code:
------------------------------------------------------------
template <class COMPLEXTYPE>
class Ccomplex
{
 public:
   COMPLEXTYPE real;
   COMPLEXTYPE img;
   // Constructor
   Ccomplex (void)
   {
    real = 0;
    img  = 0;
   }
   // Constructor (conversion operator)
   Ccomplex (COMPLEXTYPE val)
   {
    real = val;
    img  = 0;
   }
   // convert Ccomplex to real (COMPLEXTYPE)
   operator COMPLEXTYPE ()
   {
    return real;
   }
   // Destructor
   ~Ccomplex (void) { }
   // Ccomplex = Ccomplex overload
   inline Ccomplex<COMPLEXTYPE> operator = (Ccomplex<COMPLEXTYPE>
source)
   {
    this->real = source.real;
    this->img  = source.img;
    return *this;
   }
   // Ccomplex = real (COMPLEXTYPE) overload
   inline Ccomplex<COMPLEXTYPE> operator = (COMPLEXTYPE source)
   {
    this->real = source;
    this->img  = 0;
    return *this;
   }
   friend inline Ccomplex<COMPLEXTYPE> operator + \
                (Ccomplex<COMPLEXTYPE> dest, \
                 Ccomplex<COMPLEXTYPE> source);
 protected:
};
typedef Ccomplex<double> COMPLEX;
template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
       (Ccomplex<COMPLEXTYPE> dest, Ccomplex<COMPLEXTYPE> source)
{
  Ccomplex<COMPLEXTYPE> newdest;
  newdest.real = dest.real + source.real;
  newdest.img  = dest.img  + source.img;
  return newdest;
}
int main(int argc, char* argv[])
{
    COMPLEX complex1;
    COMPLEX complex2;
    complex1.real = 5;
    complex1.img  = 2;
    // WORKS
    complex2 = complex1;
    // WORKS
    complex2 = (COMPLEX) 1 + complex1;
    complex1 = complex2 + (COMPLEX) 2;
    // WORKS
    complex2 = 1 + complex1;
    complex1 = complex2 + 2;
    return 0;
}- Hide quoted text -
- Show quoted text -- Hide quoted text -
- Show quoted text -
I just found out a bug in my code, a these lines:
complex2 = 1 + complex1;
complex1 = complex2 + 2;
The imaginary part is set to 0, I'm currently trying to figure out
why.
if complex2 = 1+2i it should be:
complex1 = 1+2i + 2+0i = 3+2i
but in my code it's 3+0i.- Hide quoted text -
- Show quoted text -

I found out the problem, but I cannot remove this line
because I won't be able to do something like this:

Ccomplex complex1 = 3; // complex1 = 3+0i

   inline Ccomplex<COMPLEXTYPE> operator = (COMPLEXTYPE source)
   {
    this->real = source;
    // THIS IS THE PROBLEM:
    this->img  = 0;
    return *this;
   }- Hide quoted text -

- Show quoted text -

the problem is that
Ccomplex<COMPLEXTYPE> operator + (Ccomplex<COMPLEXTYPE> dest,
Ccomplex<COMPLEXTYPE> source);
never gets called at these line:

complex2 = 1 + complex1;
complex1 = complex2 + 2;

shouldn't the const be converted to a Ccomplex object? I can make
the code work correctly if I add these lines:

template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
(COMPLEXTYPE dest, Ccomplex<COMPLEXTYPE> source)
{ return (Ccomplex<COMPLEXTYPE>) dest + source; }
template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest, COMPLEXTYPE source)
{ return dest + (Ccomplex<COMPLEXTYPE>) source; }

but then again I'm back with 3 overloads for every
operators.
 
D

Daniel T.

none said:
I'm sure there's a better way to do this, I would really like
to be able to declare only one operator overload for each
operators. By the way I think I'm may be missing some important
points about templates, I find the class and typename keywords
really confusion. Should I use typename for member types and
class only for objects? (there's no informations about
templates in any of my C++ books)

for example:
template <class COMPLEXTYPE, typename TYPENAME>
class Ccomplex

In that context, there is no difference between the keyword "class" and
the keyword "typename". I use typename because it is linguistically more
accurate.
 
R

red floyd

Daniel said:
In that context, there is no difference between the keyword "class" and
the keyword "typename". I use typename because it is linguistically more
accurate.

In this context, I like to use class vs. typename as a
self-documentation aid. Since in this context, there's no difference in
a template parameter list, I use "class" as a reminder that the template
is intended to be instantiated with a class type, and "typename" when
any type at all may be used.

Note: this is a personal preference as to coding style, and not to be
treated as gospel.
 
D

Daniel T.

As a style issue. I find it odd that you abbreviate imaginary to img and
yet use COMPLEXTYPE which is usually abbreviated to just T, Ty, or Type.
Also, using two Cs in the name of the class is confusing, just call it
"Complex" not "Ccomplex".

Lastly, at least look at the official interface for the standard complex
class:

http://www.dinkumware.com/manuals/default.aspx?manual=compleat&page=compl
ex.html#complex
template <class COMPLEXTYPE>
class Ccomplex
{
public:
COMPLEXTYPE real;
COMPLEXTYPE img;

// Constructor

Redundant comment, of course the member-function is a constructor.
Ccomplex (void)

Remove "void" above. It is unnecessary.
http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.4
{
real = 0;
img = 0;
}

Get in the habit of using initializer lists instead of assignment in the
body of the constructor.
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6
// Constructor (conversion operator)

Redundant comment...
Ccomplex (COMPLEXTYPE val)
{
real = val;
img = 0;
}

What about a two argument constructor? That would make sense...
// Destructor
~Ccomplex (void) { }

The compiler provides a destructor that does exactly what yours does. So
remove yours and let the compiler do its job.
inline Ccomplex<COMPLEXTYPE> operator = (Ccomplex<COMPLEXTYPE>
source);

The compiler provides an op= that does exactly what yours does. So
remove yours and let the compiler do its job.
friend inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest, Ccomplex<COMPLEXTYPE>
source);
friend inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest, const COMPLEXTYPE
source);
friend inline Ccomplex<COMPLEXTYPE> operator + \
(const COMPLEXTYPE dest, Ccomplex<COMPLEXTYPE>
source);

The backslash isn't necessary in the above (or anywhere else if this
program for that matter. Don't complicate your life by using unnecessary
constructs.

"friend" isn't necessary. There is nothing private/protected in the
class.

"inline" isn't necessary. The compiler will inline where it can.

The three declarations above aren't necessary.
protected:

Spurious access specifier.
};

typedef Ccomplex<double> COMPLEX;

Reserve all upper-case declarations for macros.
template <class COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> \
Ccomplex<COMPLEXTYPE>::eek:perator = (Ccomplex<COMPLEXTYPE>
source)
{
this->real = source.real;
this->img = source.img;
return *this;
}

template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest, Ccomplex<COMPLEXTYPE> source)

'dest' and 'source' are misleading names for the arguments.
{
Ccomplex<COMPLEXTYPE> newdest;
newdest.real = dest.real + source.real;
newdest.img = dest.img + source.img;
return newdest;

If you make a two argument constructor, the above can be made much
simpler...

return Complex said:
}

template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
(Ccomplex<COMPLEXTYPE> dest,const COMPLEXTYPE source)
{ return dest + (Ccomplex<COMPLEXTYPE>) source; }

Better to call the conversion constructor explicitly.
template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
(const COMPLEXTYPE dest, Ccomplex<COMPLEXTYPE> source)
{ return (Ccomplex<COMPLEXTYPE>) dest + source; }

const is unnecessary as used above. Generally, declaring arguments
"const type" is considered bad form. Pass the arguments either by value,
or by const reference.
int main(int argc, char* argv[])

If you don't use the arguments, don't put them in.
{
COMPLEX complex;
COMPLEX complex2;

complex.real = 5;
complex.img = 2;

// WORKS
complex2 = (COMPLEX) 1 + complex;
complex = complex2 + (COMPLEX) 2;

Prefer calling the conversion constructor explicitly instead of using a
cast.
// WORKS but must use double notation to avoid
// template ambiguities between in and double
complex2 = 1.0 + complex;
complex = complex2 + 2.0;

return 0;

"return 0;" from main is unnecessary.

So, if you accept all my changes, you end up with:

template <class T>
class Complex
{
public:
T real;
T img;

Complex(): real(0), img(0) { }
Complex(T val): real(val), img(0) { }
Complex(T real, T img): real(real), img(img) { }
};

template <typename T>
Complex<T> operator +(Complex<T> left, Complex<T> right)
{
return Complex<T>(left.real + right.real, left.img + right.img);
}

template <typename T>
Complex<T> operator +(Complex<T> left, T right)
{
return Complex<T>(left.real + right, left.img);
}

template <typename T>
Complex<T> operator +(const T left, Complex<T> right)
{
return Complex<T>(left + right.real, right.img);
}

typedef Complex<double> ComplexDouble;

int main(int argc, char* argv[])
{
ComplexDouble complex;
ComplexDouble complex2;

complex.real = 5;
complex.img = 2;

complex2 = ComplexDouble(1) + complex;
complex = complex2 + ComplexDouble(2);

complex2 = 1.0 + complex;
complex = complex2 + 2.0;
}
 
N

none

As a style issue. I find it odd that you abbreviate imaginary to img and
yet use COMPLEXTYPE which is usually abbreviated to just T, Ty, or Type.
Also, using two Cs in the name of the class is confusing, just call it
"Complex" not "Ccomplex".

Lastly, at least look at the official interface for the standard complex
class:

http://www.dinkumware.com/manuals/default.aspx?manual=compleat&page=c....
ex.html#complex
template <class COMPLEXTYPE>
class Ccomplex
{
 public:
   COMPLEXTYPE real;
   COMPLEXTYPE img;
   // Constructor

Redundant comment, of course the member-function is a constructor.
   Ccomplex (void)

Remove "void" above. It is unnecessary.http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.4
   {
    real = 0;
    img  = 0;
   }

Get in the habit of using initializer lists instead of assignment in the
body of the constructor.http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6
   // Constructor (conversion operator)

Redundant comment...
   Ccomplex (COMPLEXTYPE val)
   {
    real = val;
    img  = 0;
   }

What about a two argument constructor? That would make sense...


   // Destructor
   ~Ccomplex (void) { }

The compiler provides a destructor that does exactly what yours does. So
remove yours and let the compiler do its job.
   inline Ccomplex<COMPLEXTYPE> operator = (Ccomplex<COMPLEXTYPE>
source);

The compiler provides an op= that does exactly what yours does. So
remove yours and let the compiler do its job.
   friend inline Ccomplex<COMPLEXTYPE> operator + \
                (Ccomplex<COMPLEXTYPE> dest, Ccomplex<COMPLEXTYPE>
source);
   friend inline Ccomplex<COMPLEXTYPE> operator + \
                (Ccomplex<COMPLEXTYPE> dest, const COMPLEXTYPE
source);
   friend inline Ccomplex<COMPLEXTYPE> operator + \
                (const COMPLEXTYPE dest, Ccomplex<COMPLEXTYPE>
source);

The backslash isn't necessary in the above (or anywhere else if this
program for that matter. Don't complicate your life by using unnecessary
constructs.

"friend" isn't necessary. There is nothing private/protected in the
class.

"inline" isn't necessary. The compiler will inline where it can.

The three declarations above aren't necessary.
 protected:

Spurious access specifier.
typedef Ccomplex<double> COMPLEX;

Reserve all upper-case declarations for macros.
template <class COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> \
       Ccomplex<COMPLEXTYPE>::eek:perator = (Ccomplex<COMPLEXTYPE>
source)
{
  this->real = source.real;
  this->img  = source.img;
  return *this;
}
template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
      (Ccomplex<COMPLEXTYPE> dest, Ccomplex<COMPLEXTYPE> source)

'dest' and 'source' are misleading names for the arguments.
{
  Ccomplex<COMPLEXTYPE> newdest;
  newdest.real = dest.real + source.real;
  newdest.img  = dest.img  + source.img;
  return newdest;

If you make a two argument constructor, the above can be made much
simpler...

   return Complex said:
template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
      (Ccomplex<COMPLEXTYPE> dest,const COMPLEXTYPE source)
{ return dest + (Ccomplex<COMPLEXTYPE>) source; }

Better to call the conversion constructor explicitly.
template <typename COMPLEXTYPE>
inline Ccomplex<COMPLEXTYPE> operator + \
      (const COMPLEXTYPE dest, Ccomplex<COMPLEXTYPE> source)
{ return (Ccomplex<COMPLEXTYPE>) dest + source; }

const is unnecessary as used above. Generally, declaring arguments
"const type" is considered bad form. Pass the arguments either by value,
or by const reference.
int main(int argc, char* argv[])

If you don't use the arguments, don't put them in.
{
    COMPLEX complex;
    COMPLEX complex2;
    complex.real = 5;
    complex.img  = 2;
    // WORKS
    complex2 = (COMPLEX) 1 + complex;
    complex  = complex2 + (COMPLEX) 2;

Prefer calling the conversion constructor explicitly instead of using a
cast.
    // WORKS but must use double notation to avoid
    // template ambiguities between in and double
    complex2 = 1.0 + complex;
    complex  = complex2 + 2.0;
    return 0;

"return 0;" from main is unnecessary.

So, if you accept all my changes, you end up with:

   template <class T>
class Complex
{
public:
   T real;
   T img;

   Complex(): real(0), img(0) { }
   Complex(T val): real(val), img(0) { }
   Complex(T real, T img): real(real), img(img) { }

};

   template <typename T>
Complex<T> operator +(Complex<T> left, Complex<T> right)
{
   return Complex<T>(left.real + right.real, left.img + right.img);

}

   template <typename T>
Complex<T> operator +(Complex<T> left, T right)
{
   return Complex<T>(left.real + right, left.img);

}

   template <typename T>
Complex<T> operator +(const T left, Complex<T> right)
{
   return Complex<T>(left + right.real, right.img);

}

typedef Complex<double> ComplexDouble;

int main(int argc, char* argv[])
{
   ComplexDouble complex;
   ComplexDouble complex2;

   complex.real = 5;
   complex.img  = 2;

   complex2 = ComplexDouble(1) + complex;
   complex  = complex2 + ComplexDouble(2);

   complex2 = 1.0 + complex;
   complex  = complex2 + 2.0;



}- Hide quoted text -

- Show quoted text -

thanks a lot for your help!
 

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

No members online now.

Forum statistics

Threads
473,801
Messages
2,569,658
Members
45,419
Latest member
NereidaChe

Latest Threads

Top