help-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Using a C++ polymorphic hierarchy with Bison


From: Hans Aberg
Subject: Re: Using a C++ polymorphic hierarchy with Bison
Date: Sun, 24 Oct 2004 18:30:48 +0200
User-agent: Microsoft-Outlook-Express-Macintosh-Edition/5.0.6

Some typos and changes:

- The return value of the binary operator+() and operator*() should be the
same as that of the arguments:

template<class A>
inline bool operator+(const ref<A>& x, const ref<A>& y) {
  return ((*x) + (*y));
}

template<class A>
inline bool operator*(const ref<A>& x, const ref<A>& y) {
  return ((*x) * (*y));
}

- Change ref<A>::data_ to be mutable. And change the duplicated detach() and
unary operator+() const/non-const functions to single mixed const/return
non-const functions. The reason is that a reference counted class may behave
as mutable, even though declared const.

template<class A>
class ref {
protected:
  mutable A* data_;
  ...
public:
  ...
  // Create an independent copy of the referenced object.
  ref<A> detach() const {
    if (data_ != 0 && data_->count() > 1) { data_->shed(); data_ =
data_->clone(); }
    return copy();
  }

  // If 0, mutate to new A(). Return a reference to an independent copy of
the
  // referenced object.
  A& operator+() const {
    if (data_ == 0)  data_ = new A();
    else if (data_->count() > 1) { data_->shed(); data_ = data_->clone(); }
    return *data_;
  }
};

- The class object should have a copy constructor to ensure that cloned
objects gets the reference count 1:

class object {
  ...
public:
  ...  
  object(const object&) : count_(1) {}
  ...
};

- A problem with the ref<A>::null_ object, used to reference 0, is that the
class A cannot be abstract. Another is that the null_ object may have a
different behavior than suitable defaults for classes deriving from A. In
order to fix these problems, one can instead use:

template<class A>
class ref {
protected:
  ...
  static A::null_type null_;
  ...
};

Every class A must then have a typedef telling which calls to use for the
null_object:

class A : public ... {
public:
  typedef B null_type;
  ...
};

The class has been rewritten so that this will work if class B is derived
from A. One can then write:

class A_null;

class A : public ... {
public:
  typedef A_null null_type;
  ...
};

class A_null : public A { ...};

In source:

ref_null(A); // Implement A::null_type null_ object.

Class A_null can then implement arbitrary null_ behavior of the functions in
class A, whereas class A can be abstract if so wanted, and other classes
derive from class A, not an intermediate. The reference to null_ object has
then this way been hidden away.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]