Advertisement

GCC 4.2.4 very broken? (Ubuntu 8.04 LTS)

Started by December 09, 2008 02:34 AM
2 comments, last by Bregma 15 years, 11 months ago
I'm running Ubuntu Server 8.04 LTS on an x64 system. Trying to compile this simple code, I get the following compile errors from GCC:
GuiKitWidget2.cpp: In member function âvoid HostedSubscriber<Host, Delivery, Cancellation>::OnDelivery()â:
GuiKitWidget2.cpp:53: error: âhost_â was not declared in this scope
GuiKitWidget2.cpp: In member function âvoid HostedSubscriber<Host, Delivery, Cancellation>::OnCancellation()â:
GuiKitWidget2.cpp:57: error: âsubscribable_â was not declared in this scope
GuiKitWidget2.cpp:58: error: âhost_â was not declared in this scope
GuiKitWidget2.cpp: In member function âvoid HostedSubscriberDeliveryOnly<Host, Delivery>::OnDelivery()â:
GuiKitWidget2.cpp:70: error: âhost_â was not declared in this scope
GuiKitWidget2.cpp: In member function âvoid HostedSubscriberDeliveryOnly<Host, Delivery>::OnCancellation()â:
GuiKitWidget2.cpp:74: error: âsubscribable_â was not declared in this scope
GuiKitWidget2.cpp:75: error: âhost_â was not declared in this scope
GuiKitWidget2.cpp: In member function âvoid HostedSubscriberCancellationOnly<Host, Cancellation>::OnCancellation()â:
GuiKitWidget2.cpp:88: error: âsubscribable_â was not declared in this scope
GuiKitWidget2.cpp:89: error: âhost_â was not declared in this scope

The file:

class Subscriber
{
  public:
    virtual void OnDelivery() = 0;
    virtual void OnCancellation() = 0;
};

class Subscribable
{
  public:
    virtual void AddSubscriber(Subscriber *sub) = 0;
    virtual void RemoveSubscriber(Subscriber *sub) = 0;
};

template<typename Host>
class HostedSubscriberBase : Subscriber
{
  public:
    HostedSubscriberBase() : host_(0), subscribable_(0) {}
    void Start(Subscribable *sub, Host *host)
      {
        Stop();
        if (sub != 0)
        {
          host_ = host;
          subscribable_ = sub;
          sub->AddSubscriber(this);
        }
      }
    void Stop()
      {
        if (subscribable_)
          subscribable_->RemoveSubscriber(this);
        subscribable_ = 0;
        host_ = 0;
      }
    bool Active() const
      {
        return subscribable_ != 0;
      }
  protected:
    Host *host_;
    Subscribable * subscribable_;
};

template<typename Host, void (Host::*Delivery)(), void (Host::*Cancellation)()>
class HostedSubscriber : public HostedSubscriberBase<Host>
{
  public:
    void OnDelivery()
      {
        host_->Delivery();
      }
    void OnCancellation()
      {
        subscribable_ = 0;
        Host *h = host_;
        host_ = 0;
        (h->*Cancellation)();
      }
};

template<typename Host, void (Host::*Delivery)()>
class HostedSubscriberDeliveryOnly : public HostedSubscriberBase<Host>
{
  public:
    void OnDelivery()
      {
        host_->OnDelivery();
      }
    void OnCancellation()
      {
        subscribable_ = 0;
        host_ = 0;
      }
};

template<typename Host, void (Host::*Cancellation)()>
class HostedSubscriberCancellationOnly : public HostedSubscriberBase<Host>
{
  public:
    void OnDelivery()
      {
      }
    void OnCancellation()
      {
        subscribable_ = 0;
        Host *h = host_;
        host_ = 0;
        (h->*Cancellation)();
      }
};

class Foo
{
  public:
    void Func() {}
    HostedSubscriberCancellationOnly<Foo, &Foo::Func> foo_;
};

Am I mad, or is GCC just horrily broken? MSVC (2008 sp1) compiles this particular code just fine.
enum Bool { True, False, FileNotFound };
Same problem on gcc 4.1.2 (RedHat) and 4.3.2 (Debian). Adding "this->" makes it work on both. Weird. Maybe some C++ wizard could tell if this is a feature or a bug.
Advertisement
I have no c++ compiler handy here at work. But what if you try out ...

protected:    typename Host *host_;    typename Subscribable * subscribable_;


?
It's Microsoft's compiler that's broken, not gcc. I never really understood why the standard absolutely has to require it like this, to be honest. Either way, it's correct, since it's the standard.

If you have a copy of Vandervoorde/Josuttis (which you probably do), there are a few words on page 47, and a lengthy explanation on pages 136-139.
The bottom line is, you have to use this-> or Subscriber:: to fully qualify your members, else :: will be assumed, where of course nothing will be found.
Quote: Original post by samoth
It's Microsoft's compiler that's broken, not gcc. I never really understood why the standard absolutely has to require it like this, to be honest. Either way, it's correct, since it's the standard.


There are names available when a template is defined. Then, there are names available whgen a template is instantiated. At template definition time there is no way to tell what names will be available at template instatiation time. By explicitly qualifying the name with the '->' operator, you're explicitly telling the compiler that a name will be available from the base class regardless of what is available at instatiation time, so it can emit code that binds it appropriately. Remember, thge compiler cannot devine what you want, only what you tell it.

Tell me, what rules does the Microsoft compiler follow to resolve this ambiguity when it arises, considering it doesn' do what the over-ten-years-old standard specifies quite clearly?

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement