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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Paulo Matos

    #1

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

    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;

    };
    ParsingStructur eType 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::operato r-() const;

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

    Regards,

    Paulo Matos

  • dasjotre

    #2
    Re: Design issue... Question on best way to do it in C++.


    Paulo Matos wrote:
    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::varian t<int, RationalNumber;

    class plus_visitor : public boost::static_v isitor<Number>
    {
    public:

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

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

    Number operator()(Rati onal 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_vi sitor(), 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;
    >
    };
    ParsingStructur eType 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::operato r-() 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

    Comment

    • Ondra Holub

      #3
      Re: Design issue... Question on best way to do it in C++.

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

      Comment

      Working...