Design issue... Question on best way to do it in C++.

P

Paulo Matos

Hi all,

Guess I wish to do some parsing for a calculator which might include
rational numbers.
So I can have integers (sequence of digits possibly started by -) and
rationals (two integers separated by '/').
I did a NumberWrapper which makes the use of a number, be it an integer
or rational transparent to the user.
Number(1, 2); represents 1/2
Number(2); represents 1

First issue, I have something like this in number (or would like to):
class Number {
....

private:
enum numberType {INTEGER, RATIONAL};
numberType type;
union {
int integer;
Rational rational; // Class defined by me...
};
};

Problem is Rational has non-trivial constructors so it just can't be
there. One way it to remove the union and just have an int and a
rational, never both are used at the same time (that wastes space but
saves me a lot of trouble).
Another way is to have a void* and then based on type I just cast it to
int or to rational as I need, obviously with caution, deleting and
freeing what I need. Well, this seems a lot of trouble!
Another is to just represent an integer as a rational with denominator
1 and forget the int or wrapper at all and use rationals all the way.

Another issue has to do with how to structure things around the
parsing. Bison uses unions for communication with flex so I have a
Number * in the union and whenever flex finds a rational or number,
allocates a new number and bison get's it so I can use it in parsing.
struct parsingState {
union {

Number *num;

};
ParsingStructureType type;
};
Problem is when I need to do some computations...
Guess I have Number *num; in the union and I want to update it to
become -num. I have defined operator-() in Number so I do:
parsingState ps;

....

ps->num = - ps->num;

It seems to be that this will leak right? (-ps->num) will allocate
another Number because operator-() is
Number Number::eek:perator-() const;

and I'll lose my previous allocated number.
Any ideas on how I can do this or organize my structures?

Regards,

Paulo Matos
 
D

dasjotre

Paulo said:
Hi all,

Guess I wish to do some parsing for a calculator which might include
rational numbers.
So I can have integers (sequence of digits possibly started by -) and
rationals (two integers separated by '/').
I did a NumberWrapper which makes the use of a number, be it an integer
or rational transparent to the user.
Number(1, 2); represents 1/2
Number(2); represents 1

First issue, I have something like this in number (or would like to):
class Number {
...

private:
enum numberType {INTEGER, RATIONAL};
numberType type;
union {
int integer;
Rational rational; // Class defined by me...
};
};

Problem is Rational has non-trivial constructors so it just can't be
there. One way it to remove the union and just have an int and a
rational, never both are used at the same time (that wastes space but
saves me a lot of trouble).
Another way is to have a void* and then based on type I just cast it to
int or to rational as I need, obviously with caution, deleting and
freeing what I need. Well, this seems a lot of trouble!
Another is to just represent an integer as a rational with denominator
1 and forget the int or wrapper at all and use rationals all the way.

The safest way I found for this kind of a
problem is to use boost::variant

to start you up

typedef ::boost::variant<int, Rational> Number;

class plus_visitor : public boost::static_visitor<Number>
{
public:

Number operator()(int i, int j) const
{
return Number(i+j);
}

Number operator()(Rational const & i, Rational const & j) const
{
//suppose you have + op for Rational
return Number(i+j);
}

Number operator()(Rational const & i, int j) const
{
// suppose your rational has a constructor
// like Rational(int nominator, int denominator
return Number(Rational(i.nominator+j*i.denominator, i.denominator));
}

Number operator()(int i, Rational const & j) const
{
return Number(Rational(j.nominator+i*j.denominator, j.denominator));
}
};

Number n = 1;
Number r = Rational(3, 4);
Number t = ::boost::apply_visitor(plus_visitor(), n, r);
t is now 7/4

boost has a very nice documentation so look it up.
Another issue has to do with how to structure things around the
parsing. Bison uses unions for communication with flex so I have a
Number * in the union and whenever flex finds a rational or number,
allocates a new number and bison get's it so I can use it in parsing.
struct parsingState {
union {

Number *num;

};
ParsingStructureType type;
};
Problem is when I need to do some computations...
Guess I have Number *num; in the union and I want to update it to
become -num. I have defined operator-() in Number so I do:
parsingState ps;

...

ps->num = - ps->num;

It seems to be that this will leak right? (-ps->num) will allocate
another Number because operator-() is
Number Number::eek:perator-() const;

and I'll lose my previous allocated number.
Any ideas on how I can do this or organize my structures?
Sorry I don't use nether Bison nor flex, can't help you there
 
O

Ondra Holub

I would simply store all numbers as rationals. Every integer N is also
special case of rational N/1.
 

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
474,212
Messages
2,571,101
Members
47,695
Latest member
KayleneBee

Latest Threads

Top