Calling a template object's member function

Dear all,

Recently, I wrote some code for computations with polynomials (stuff like x^2+xy+5 - just as studied in high school) over the rational numbers.

I want to make my code so that the coefficient ring (a ring means some set in which you have a concept of addition and multiplication) can be changed. At best, I will be happy to have the elements of the coefficient ring enter as a template class. What would you advise me to do? Any advice is welcome!

The following "pseudo-c++-code" is what I would like to have realized - one way or another. Of course, the below "code" doesn't compile.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <class ElementOfCommutativeRingWithIdentity>
class PolynomialOverCommutativeRingWithIdentity
{
	ElementOfCommutativeRingWithIdentity Coeff;
	void AddConstant(ElementOfCommutativeRingWithIdentity* c);
/*...*/
/*other elements and functions here, I have plenty :)*/
};


/*the ElementOfCommutativeRingWithIdentity object MUST have a function "Add", which it does for all the classes I want to use. */
template <class ElementOfCommutativeRingWithIdentity>
void PolynomialOverCommutativeRingWithIdentity::AddConstant( ElementOfCommutativeRingWithIdentity* c)
{
	Coeff.Add(*c);
}


Thanks a lot for your advice!
Last edited on
If there is a function that is required for the class, my first thought is to make an abstract base class with a pure virtual function Add. Then concrete objects that inherit from the base class could be passed to your Polynomial as base class pointers.

I don't see what was gained by making the Polynomial class a template. Also, you may want to look up the prototype pattern for adding coefficients.
I tried for a while to realize it with virtual functions, when I realized that I don't exactly understand your reply. Let me give the actual code I am trying to modify:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*edited the code to make it more readable*/

class Rational
{
void Assign(Rational& r);
void MultiplyBy(Rational& r);
/*and some other members*/
};
class Monomial
{
public:
	int NumVariables;
	int* degrees;
	Rational Coefficient;
	void MultyplyBy(Monomial& m);
	bool HasSameExponent(Monomial& m);
	void CopyFrom(Monomial& m);
/*...and some more members...*/
};


class Polynomial
{
/*uses arrays of monomials. Here is the big lump of code.*/
};

void Monomial::MultyplyBy(Monomial& m)
{
	assert(m.NumVariables == this->NumVariables);
	for(int i=0; i< m.NumVariables;i++)
	{
		this->degrees[i]+=m.degrees[i]; 
	}
	this->Coefficient.MultiplyBy(m.Coefficient); 
}

void Monomial::CopyFrom(Monomial& m)
{
	this->init(m.NumVariables); 
	for (int i=0;i<NumVariables;i++)
	{
		this->degrees[i]=m.degrees[i]; 
	}
	this->Coefficient.Assign (m.Coefficient);
}



If I substitute the class "Rational" in the above code with a virtual class, say "ElementOfCommutativeRingWithIdentity", I wouldnt be able to declare class Monomial since the compiler wouldn't know how much memory to reserve for element in question.

As far as I understood your suggestion, you would advise me to create my ElementOfCommutativeRingWithIdentity elsewhere, and pass a pointer to it to my Polynomial class. That, however, would mean that

1) I must rewrite a solid portion of my code (which is actually ok by me)
2) The Polynomial class will be something like a nice object to "attach" to my ElementOfCommutativeRingWithIdentity object. In particular, my Polynomial class will not be able to allocate memory for its coefficients. This would lead to major structural changes in my code, which would, in my opinion, be more inconvenient than having me actually copy and paste my code and substitute the string "Rational" with the string "QuasiPolynomial" and the string "Polynomial" with the string "Polynomial2" (I would like to have "QuasiPolynomials" as coefficients of my polynomials, whatever that means).
Last edited on
This is getting too complicated for my liking. Start from the bottom up, and be very specific about your intention and the problems that you face and we can work our way up to the whole deal. Maybe that approach will help.

Two immediate suggestions: use the STL container(s) to handle memory allocation for you and look up the prototype pattern.

Have you white-boarded your hierarchy or anything? It kind of looks like there has been little planning and lots of coding. Let's take more of an engineering approach.
sorry for the too much blah-blah from my side. In reality, I wanted to write the below code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
template <class ElementOfCommutativeRingWithIdentity>
class Monomial
{
public:
	int NumVariables;
	int* degrees;
	ElementOfCommutativeRingWithIdentity Coefficient;
	void MultyplyBy(Monomial& m);
	bool HasSameExponent(Monomial& m);
	void CopyFrom(Monomial& m);
/*some other functions*/
};

void Monomial::MultyplyBy(Monomial& m)
{
	assert(m.NumVariables == this->NumVariables);
	for(int i=0; i< m.NumVariables;i++)
	{
		this->degrees[i]+=m.degrees[i]; 
	}
	this->Coefficient.MultiplyBy(m.Coefficient); 
};

void Monomial::CopyFrom(Monomial& m)
{
	this->init(m.NumVariables); 
	for (int i=0;i<NumVariables;i++)
	{
		this->degrees[i]=m.degrees[i]; 
	}
	this->Coefficient.Assign (m.Coefficient);
}

Monomial<Rational> m1;
Monomial<QuasiPoly> m2;


I actually had some miniature hope that the above would work, provided that my two classes "Rational" and "QuasiPoly" have the member functions "Assign" and "MultiplyBy" (which they both do!). As you can guess, however, this code didn't compile...

Hope this makes my desire more clear; however I am beginning to fear I ask for something that cannot be actually done in c++, at least not so simply...

@seymore15074
Honestly, I do not know what STL means. Also, no, I haven't done any serious planning ahead (I didn't know for mathematical reasons that I will have to change the coefficient ring when I started writing the program). I was thinking to actually copy and paste the code and replace the string "Rational" with whichever other class I need, however, I decided to check whether you guys have any smart idea (since obviously mine is stupid but guaranteed to work).
Last edited on
You could post the compiler errors for us to see what is actually wrong?
I fail to see your problem? You want to call a member's method within a template function?

myClass.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

class Build {
public:
  void doIt() { cout << "Building..." << endl; }
};

template<class T>
class Bob {
public:
  Bob() { pBuild = new T(); }
  ~Bob() { delete pBuild; }
  void print() { cout << "bob is printing" << endl;
    pBuild->doIt();
  }

  T *pBuild;
};


Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>

#include "myClass.h"

using namespace std;

int main()
{
  Bob<Build> myBob = Bob<Build>();

  myBob.print();

  return 0;
}


Output:
bob is printing
Building...
Last edited on
!
Thanks a lot! As simple as that - will rework it quick! My problem was I was stupid enough not to get the

Bob() { pBuild = new T(); }
~Bob() { delete pBuild; }

part. However I was smart enough to ask you guys, and actually get the answer, and that is a minor relief :)
You don't haveto have it as a pointer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

class Build {
public:
  void doIt() { cout << "Building..." << endl; }
};

template<class T>
class Bob {
public:
  Bob() { TBuild = T(); }
  ~Bob() {  }
  void print() { cout << "bob is printing" << endl;
    TBuild.doIt();
  }

  T TBuild;
};


Works equally well.
Finally got it!

I can actually call functions of template (i.e."parameter") classes! It was for some syntax errors of mine that I couldn't originally do it, and not because it can't be done.

Now that I compiled and linked, let me share my personal favourite from the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
template <class ElementOfCommutativeRingWithIdentity>
class Monomial
{
public:
	int NumVariables;
	int* degrees;
	ElementOfCommutativeRingWithIdentity Coefficient;
/*plus more functions*/
};

/*ListObjectPointers is a template class of mine which I guess is a remake of the vector template class. My personal favourite class follows :))*/
template <class ElementOfCommutativeRingWithIdentity>
class MonomialPointers: public ListObjectPointers< Monomial<ElementOfCommutativeRingWithIdentity>> 
{
public:
};

template <class ElementOfCommutativeRingWithIdentity>
class Polynomial
{
public:
	MonomialPointers <ElementOfCommutativeRingWithIdentity> TheMonomials;
/*and more members*/
};

template <class ElementOfCommutativeRingWithIdentity>
class PolynomialPointers: public ListObjectPointers<Polynomial<ElementOfCommutativeRingWithIdentity>>
{
public:
/* some list of functions*/
};


For me, c++ is a love and hate relationship - yesterday I hated it, today I love it!

Thanks to all again :)
Haha, yeah I know what you mean by the love and hate. Although I'm starting to get a lot better at it.
One word of Advice. "ElementOfCommutativeRingWithIdentity" Is very long. As a template type it's common practice to just use the letter "T". :)
Topic archived. No new replies allowed.