This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RTTI bug


hi there,

I'm running into a bug with gcc 3.2 (compiled by hand as well
as the RH 8.0 version). I attach a small test which reproduces
the bug; I compiled it with 'g++ -o bug bug.cc'.

I played a bit with slight modifications to the code, as there
is a mix of template instance resolution, runtime type resolution,
etc., but I couldn't come up with a clear discrimination of
buggy/non-buggy cases.

The situation in short is this: we use the 'Recurrent Template
Pattern' to implement an event multicasting framework, i.e. to
type-safely bind observers to senders. The real observer calls
a templated method of the 'Observer' interface, which itself
makes a dynamic_cast to the concrete type, provided as a template
parameter.

The bug is that dynamic_cast fails.

Typeinfo().name() produces the same names for the origin and the target type.
Moreover (and that seems the real kick), the bug is triggered only if
the concrete Observer is derived from the Observer interface privately.

Oh, and if I remove the argument of the concrete Observer's constructor
(thus making it a 'default constructor'), the problem goes away, too.

Hope this provides enough context...


Thanks a lot !

Stefan
#include <iostream>
#include <typeinfo>

class Observer
{
public:
   virtual ~Observer() {}
   Observer() {}
//    template <typename _Event, typename _Observer>
//    void Attach(void (_Observer::*method)(const _Event &), 
//                const typename _Event::Origin *subject);
   template <typename _Event, typename _Observer>
   void AttachAll(void (_Observer::*method)(const _Event &));
private:
   template <typename _Event, typename _Observer> class AdapterT;
};

// template <typename _Event, typename _Observer>
// inline void Observer::Attach(void (_Observer::*method)(const _Event &),
//                              const typename _Event::Origin *subject)
// {

//    if (!dynamic_cast<_Observer *>(this))
//    {
//       std::cout << "TROUBLE !" << std::endl;
//       std::cout << typeid(*this).name() << std::endl;
//       std::cout << typeid(_Observer).name() << std::endl;
//    }
// }

template <typename _Event, typename _Observer>
inline void Observer::AttachAll(void (_Observer::*method)(const _Event &))
{

   if (!dynamic_cast<_Observer *>(this))
   {
      std::cout << "TROUBLE !" << std::endl;
      std::cout << typeid(*this).name() << std::endl;
      std::cout << typeid(_Observer).name() << std::endl;
   }
}

struct Sender
{
   struct Event
   {
      typedef Sender Origin;
   };
};

class Binding : Observer
{
public:
   Binding(const Sender &)
   {
//       Attach<Sender::Event>(&Binding::Notify, &sender);
      AttachAll<Sender::Event>(&Binding::Notify);
   }
private:
   void Notify(const Sender::Event &)
   {
      std::cout << "Binding::Notify" << std::endl;
   }
};

int main(int, char **)
{

   Sender sender;
   Binding binding(sender);
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]