Solved

How to use overloaded operators in template class

Posted on 2002-05-22
12
253 Views
Last Modified: 2013-12-14
Hi

I am in the process of converting a simple C++ library into a template-based form, but have hit a snag on operators.  Rather than present the whole library (!), the problem can be shown easily in a simple snippet below, which fails to compile.  I'm also having similar difficulty using friend operators within the template class.  All the template-based functions work fine.

The following fails to compile with errors on the two operators (+ and =) when using the g++ compiler.  The simple print() and put() work fine if the operator-related parts of the code are deleted.

Thank you.
----------------------------------------------

// Very very simple template class
#include <iostream>
#include <cstdlib>
using namespace std;

template <class MyType> class simple {
   MyType a;
public:
   put(MyType inval);
   print();
   MyType operator+(simple op);
   MyType operator=(simple op);
};

// Put value
template <class MyType> simple<MyType>::put(MyType inval)
{
   a = inval;
}

// Print value
template <class MyType> simple<MyType>::print()
{
   cout << "\nThe value of a is " << a << "\n";
}

// Add together two objects (does not work)
template <class MyType> MyType simple<MyType>::operator+(simple op)
{
   simple temp;

   temp.a = op.a + a;
   return a;
}

// Overload = sign (does not work)
template <class MyType> MyType simple<MyType>::operator=(simple op)
{
   a = op.a;

   return *this;
}

// Off we go...
int main()
{
   simple<int> intobject1;
   simple<int> intobject2;
   simple<int> intobject3;

   intobject1.put(5);
   intobject2.put(6);

   intobject1.print();
   intobject2.print();

   intobject3 = intobject1 + intobject2;

   intobject3.print();

   return 0;
}
0
Comment
Question by:doyston
  • 7
  • 3
  • 2
12 Comments
 
LVL 3

Expert Comment

by:MDarling
ID: 7027245
#include <iostream>
#include <cstdlib>

using namespace std;

template <class MyType> class simple {
    MyType a;
public:

    simple()
        {
        }

    simple(const simple<MyType>& x)
        {
            a=x.a;
        }

    void put(MyType inval);
    void print();
    simple<MyType> operator+(const simple& op);
    simple<MyType>& operator=(const simple& op);


};

// Put value
template <class MyType>
void simple<MyType>::put(MyType inval)
{
    a = inval;
}

// Print value
template <class MyType>
void simple<MyType>::print()
{
    cout << "\nThe value of a is " << a << "\n";
}

// Add together two objects (does not work)
template <class MyType>
simple<MyType> simple<MyType>::operator+(const simple& op)
{
    simple<MyType> temp;
    temp.a=this->a + op.a;
    return temp;
}

// Overload = sign (does not work)
template <class MyType>
simple<MyType>& simple<MyType>::operator=(const simple& op)
{
    a = op.a;
    return *this;
}

// Off we go...
int main()
{
    simple<int> intobject1;
    simple<int> intobject2;
    simple<int> intobject3;
    intobject1.put(5);
    intobject2.put(6);
    intobject1.print();
    intobject2.print();
    intobject3 = intobject1 + intobject2;
    intobject3.print();
    return 0;
}

0
 
LVL 3

Expert Comment

by:MDarling
ID: 7027254
code modified above to compile.

You were mistakenly returning MyType in some cases instead of the template class object you really wanted to return.

Notice the use of const references as well in some cases on params.

Also notice I created a default constructor and a copy constructor to enable the assignment to work.

Regards,
Mike
0
 
LVL 3

Expert Comment

by:MDarling
ID: 7027255
code modified above to compile.

You were mistakenly returning MyType in some cases instead of the template class object you really wanted to return.

Notice the use of const references as well in some cases on params.

Also notice I created a default constructor and a copy constructor to enable the assignment to work.

Regards,
Mike
0
Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

 
LVL 22

Expert Comment

by:ambience
ID: 7028797
#include <iostream>
#include <cstdlib>
using namespace std;

template <class MyType> class simple
{
  MyType a;

public:
  simple<MyType>(){}
  simple<MyType>(MyType b) { a = b; }
  simple<MyType>(simple<MyType> b) { a = b.a; }
 
  void put(MyType inval);
  void print();

  // Maybe you wanted to return MyType here
  // if yes then the second constructor is required
  // otherwise you can return simple<MyType> as given in
  // another solution above

  MyType operator+(const simple<MyType>& op);
  simple<MyType> operator=(const simple<MyType>& op);
};

// Put value
template <class MyType>
void simple<MyType>::put(MyType inval)
{
  a = inval;
}

// Print value
template <class MyType>
void simple<MyType>::print()
{
  cout << "\nThe value of a is " << a << "\n";
}

// Add together two objects (does not work)
template <class MyType>
MyType simple<MyType>::operator+(const simple<MyType>& op)
{
  simple<MyType> temp;
  temp.a = op.a + a;
  return temp.a;
}

// Overload = sign (does not work)
template <class MyType>
simple<MyType> simple<MyType>::operator=(const simple<MyType>& op)
{
  a = op.a;
  return *this;
}

// Off we go...
int main()
{
  simple<int> intobject1;
  simple<int> intobject2;
  simple<int> intobject3;

  intobject1.put(5);
  intobject2.put(6);

  intobject1.print();
  intobject2.print();

  intobject3 = intobject1 + intobject2;
  intobject3.print();
  return 0;
}


hope this helps
0
 
LVL 22

Expert Comment

by:ambience
ID: 7028801
sorry for one thing

simple<MyType>(simple<MyType> b) { a = b.a; }

should've been

simple<MyType>(const simple<MyType>& b) { a = b.a; }
 


0
 

Author Comment

by:doyston
ID: 7029198
Thank you both for your help; program now compiles properly.  I should have spotted my mistake when I tried to return MyType instead of the template class itself.  I notice that you've slightly altered the layout of the code, which makes it much more readable, and the logic is now clearer.

I'm still hitting a snag when I try and include a friend function, however.  For example, if I want to overload the + operator so that it can do an object + integer addition, I've tried putting:

friend simple<MyType> operator+(const simple &op1, const int &op2);

within the public definition of the simple class, and then further down the code put:

// Overload + as friend
template <class MyType>
simple<MyType> operator+(const simple &op1, const int &op2)
{
   simple<MyType> temp;

   temp.a = op1.a + op2;

   return temp;
}

This generates all sorts of compilation errors on g++, including warnings about the friend declaration declaring a non-template declaration, and the need to add <> after the function name, which I don't really understand, and it then gets confused by the number of arguments expected for the friend function.  The compiler states that it must be one or two (I thought it was two according to the code).

I'm obviously making some silly mistake here, but haven't got the hang of these templates yet.

Thanks again for your help.
Roy
0
 
LVL 3

Expert Comment

by:MDarling
ID: 7029237
look at your parameters to the function....

Regards,
Mike.
0
 
LVL 3

Expert Comment

by:MDarling
ID: 7029249
template <class MyType>
simple<MyType> operator+(const simple<MyType> &op1, const int &op2)
{
  simple<MyType> temp;
  temp.a = op1.a + op2;
  return temp;
}

Regards,
Mike.
0
 

Author Comment

by:doyston
ID: 7029342
Thanks, but I'm still hitting similar compilation problems.  Lots of warnings about the friend declaration being a non-template type, then followed by the line:

/tmp/ccDf55h1.o: In function'main':
/tmp/ccDf55h1.o (.text+0x72): undefined reference to 'operator+(simple<int> const &, int const &)'

which I guess is some sort of linker error when it hits the line

intobject3 = intobject2 + 10;

in main.  This is being run on RHL 6.0.
Roy
0
 
LVL 3

Expert Comment

by:MDarling
ID: 7029369
The reason is you are creating a specialisation for simple<int>

your need to define the friend function for each specialisation you use.

see below...

0
 
LVL 3

Accepted Solution

by:
MDarling earned 300 total points
ID: 7029372
#include <iostream>
#include <cstdlib>

using namespace std;

template <class MyType> class simple {
    MyType a;
public:

    simple()
        {
        }

    simple(const simple<MyType>& x)
        {
            a=x.a;
        }

    void put(MyType inval);
    void print();
    simple<MyType> operator+(const simple& op);
    simple<MyType>& operator=(const simple& op);

    friend simple<MyType> operator+(const simple<MyType>& op1,int op2);
};

// Put value
template <class MyType>
void simple<MyType>::put(MyType inval)
{
    a = inval;
}

// Print value
template <class MyType>
void simple<MyType>::print()
{
    cout << "\nThe value of a is " << a << "\n";
}

// Add together two objects
template <class MyType>
simple<MyType> simple<MyType>::operator+(const simple& op)
{
    simple<MyType> temp;
    temp.a=this->a + op.a;
    return temp;
}

// Overload = sign
template <class MyType>
simple<MyType>& simple<MyType>::operator=(const simple& op)
{
    a = op.a;
    return *this;
}


// specialisation for simple<int>
simple<int> operator+(const simple<int>& op1, int op2)
{
    simple<int> temp;
    temp.a = op1.a + op2;
    return temp;
}

// Off we go...
int main()
{
    simple<int> intobject1;
    simple<int> intobject2;
    simple<int> intobject3;
    intobject1.put(5);
    intobject2.put(6);
    intobject1.print();
    intobject2.print();
    intobject3 = intobject1 + intobject2;
    intobject3.print();
    intobject3 = intobject2 + 10;
    return 0;
}



0
 

Author Comment

by:doyston
ID: 7029821
Excellent!  I think I now understand what's going on, as I hadn't through the implications of the friend function being outside the MyType template.

Thank you very much for your help.
Roy
0

Featured Post

Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
THe viewer will learn how to use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question