help-bison
[Top][All Lists]
Advanced

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

Re: C++ / multiple instances / iostreams


From: Hans Aberg
Subject: Re: C++ / multiple instances / iostreams
Date: Thu, 22 Jul 2004 19:34:36 +0200

At 00:22 +0200 2004/07/22, Detlef Vollmann wrote:
>>  class semantic_type {
>>  public:
>>    long number_;
>>    std::string text_;
>>    my::object object_;
>>
>>    semantic_type() : number_(0) {}
>>  };
>>  #define YYSTYPE semantic_type
>> will suffice as semantic type. One converts data using either
>> dynamic_cast<T*>, in which case null pointer must be checked, or
>> dynamic_cast<T&>, in which case null pointers case an exception to be
>> thrown.
>I don't really see how you use this, but for dynamic_cast to work the
>classes must be related:

Yes, one builds a hierarchy of classes, all derived from one root class --
which I called class object_root. If you want to put a class of any kind
into this polymorphic hierarchy, then make a virtual derivation from the
root class, like:
  class my_class : public virtual object_root {
    ...
  };
Then the class object that maintains a reference-counted pointer to
  object_root* data_;
also has functions
  object_root* data() { return data_; }
  const object_root* data() const { return data_; }
Thus, a typical Bison .y action might look like:
  my_class& mc = dynamic_cast<my_class&>(*$5.object_.data());
or
  my_class* mcp = dynamic_cast<my_class*>($5.object_.data());
  if (mcp == 0)  error();

I can also build an object class maintianing a pointer to my_class:
  class my_object_class {
    my_class data_;
    ...
    object_root* data() { return data_; }
    const object_root* data() const { return data_; }
    ...
  };
Then these classes need not be derived in any particular manner. And by
adding the data() functions, then Bison action code will look exactly the
same when invoking the dynamic_cast.

If I make some type errors when programming, that will end up as captured
parser runtime errors. I have found that is enough to not really need the
Bison type-checking feature that is invoked by %union. Otherwise, I
experimented a while with a feature %typed which is the same as %union,
except that the semantic type is not implemented as a union.

>Some compilers allow (and check) dynamic_casts between pointers to
>unrelated classes, some even allow dynamic_cast<T *>(void *), but thats
>completely implementation defined.

The C++ standard says that if the dynamic_cast fails one gets a null
pointer (T*) or an exception (T&):

[expr.dynamic.cast] 5.2.7:9 The value of a failed cast to pointer type is
the null pointer value of the required result type. A failed cast to
reference type throws bad_cast (18.5.2).

So dynamic_cast can always be applied.

>And (as you can also read in the Performance Report) dynamic_casts
>are notorically slow in most implementations.

And so are dynamic allocations. If speed is crucial, then avoid all such
dynamic features. Or build your own GC, and make the dynamic allocations C
style: A shortcoming of current C++ is that it is notoriously difficult to
combine with a GC, other than a reference count.

  Hans Aberg






reply via email to

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