M
Master of C++
Hello Folks,
I have a programming dilemma with templates and "genericity". I can
think of a few solutions, but I am not sure which one is the best in
terms of genetic C++ style. Any suggestions will be greatly
appreciated.
I am writing a template class Polynomial that encapsulates the
functionalities of a Polynomial. Here is a rough sketch for the class:
.. template class<T>
.. class Polynomial
.. {
.. std::vector<T> coeffts; // coefficients
..
.. public:
.. // constructors and destructor.
.. // accessor routines.
.. // arithemtic operators.
.. // utility functions for printing, reduction, etc.,
.. };
This class can be used to represent polynomials like ax^2 + bx + c,
where the coefficients a, b, c can be either built-in types such as
int, double, float etc., or classes which have operators such as +, - ,
*, etc., defined. One of the main reasons for writing the above class
is to handle polynomials over Galois Fields (an abstract algebra
concept, but that is not relevant to the question). I have a class that
encapsulates a Galois Field element, whose sketch is given below:
.. class GFElement
.. {
.. uint32 gfValue;
.. GaloisField *gf;
..
.. public:
.. // constructors and destructor.
.. // accessors.
.. // arithmetic operators.
.. };
All the properties of the field are encapsulated within the class
GaloisField. It has stuff such as addition, subtraction,
multiplication, division, exponentiation and logarithm tables (because
a GaloisField has a finite number of elements, it is possible to
represent all arithmetic operations using tables at the expense of a
little memory). These tables will be used to look-up results of
arithmetic operations in GFElement (basically, the 'gf' pointer defines
the field that 'gfValue' belongs to).
As you can see, in order for a GFElement to be valid, we need to
initialize it with two parameters ('gfValue' and the pointer 'gf' to a
GaloisField object). This becomes a problem if I have code such as:
if (coeffts > (T)0)
....
(or)
T temp = (T) 0;
....
temp += coeffts;
in the Polynomial<T> class (with T = GFElement). This is because, I can
only specify one value in the type-conversion constructor for GFElement
(where I initialize 'gfValue' to the argument of the constructor and
set 'gf' equal to NULL). In the above 'if' statement, the 'operator>'
function is comparing two GFElement objects, one with a 'gf' pointer
that points to a valid object and another with a 'gf' pointer that is
set to NULL. Normally, this situation should raise an exception simply
because one of the operands has an invalid 'gf' pointer.
In order to solve this dilemma, I set up an rule that: if 'gfValue' is
zero and the 'gf' pointer is NULL, the GFElement object is valid as
long as the routine that operates on that object does to use the 'gf'
pointer. If the above condition is met I will not raise an exception
and consider that situation as NORMAL.
So, my question would be: Is there a better way this situation could be
resolved ? or am I missing some big picture here ? What would Brian
Boitano do ?
Any suggestions or comments will be greatly appreciated, and thanks for
reading this long post.
Thanks,
Vijay.
I have a programming dilemma with templates and "genericity". I can
think of a few solutions, but I am not sure which one is the best in
terms of genetic C++ style. Any suggestions will be greatly
appreciated.
I am writing a template class Polynomial that encapsulates the
functionalities of a Polynomial. Here is a rough sketch for the class:
.. template class<T>
.. class Polynomial
.. {
.. std::vector<T> coeffts; // coefficients
..
.. public:
.. // constructors and destructor.
.. // accessor routines.
.. // arithemtic operators.
.. // utility functions for printing, reduction, etc.,
.. };
This class can be used to represent polynomials like ax^2 + bx + c,
where the coefficients a, b, c can be either built-in types such as
int, double, float etc., or classes which have operators such as +, - ,
*, etc., defined. One of the main reasons for writing the above class
is to handle polynomials over Galois Fields (an abstract algebra
concept, but that is not relevant to the question). I have a class that
encapsulates a Galois Field element, whose sketch is given below:
.. class GFElement
.. {
.. uint32 gfValue;
.. GaloisField *gf;
..
.. public:
.. // constructors and destructor.
.. // accessors.
.. // arithmetic operators.
.. };
All the properties of the field are encapsulated within the class
GaloisField. It has stuff such as addition, subtraction,
multiplication, division, exponentiation and logarithm tables (because
a GaloisField has a finite number of elements, it is possible to
represent all arithmetic operations using tables at the expense of a
little memory). These tables will be used to look-up results of
arithmetic operations in GFElement (basically, the 'gf' pointer defines
the field that 'gfValue' belongs to).
As you can see, in order for a GFElement to be valid, we need to
initialize it with two parameters ('gfValue' and the pointer 'gf' to a
GaloisField object). This becomes a problem if I have code such as:
if (coeffts > (T)0)
....
(or)
T temp = (T) 0;
....
temp += coeffts;
in the Polynomial<T> class (with T = GFElement). This is because, I can
only specify one value in the type-conversion constructor for GFElement
(where I initialize 'gfValue' to the argument of the constructor and
set 'gf' equal to NULL). In the above 'if' statement, the 'operator>'
function is comparing two GFElement objects, one with a 'gf' pointer
that points to a valid object and another with a 'gf' pointer that is
set to NULL. Normally, this situation should raise an exception simply
because one of the operands has an invalid 'gf' pointer.
In order to solve this dilemma, I set up an rule that: if 'gfValue' is
zero and the 'gf' pointer is NULL, the GFElement object is valid as
long as the routine that operates on that object does to use the 'gf'
pointer. If the above condition is met I will not raise an exception
and consider that situation as NORMAL.
So, my question would be: Is there a better way this situation could be
resolved ? or am I missing some big picture here ? What would Brian
Boitano do ?
Any suggestions or comments will be greatly appreciated, and thanks for
reading this long post.
Thanks,
Vijay.