Question

I have the following construct in a static library (part of a dispatcher mechanism, unrelated details removed for brevity):

class Base {
protected:
    Base(Connection* conn = nullptr) : myConn(conn) {;} // = nullptr fixes the problem

    Connection* myConn;
};

class Handler : virtual public Base {
public:
    virtual void handleMessage(InputStream&) = 0;

protected:
    Handler(int id) : myId(id) {;} <<<<< Error <<<<<<<

    const int myId;
};

template<class EventType>
class TypedHandler : public Handler
{
protected:
    TypedHandler() : Handler(EventType::ID) {;}

    virtual void onEvent(const EventType&) = 0;

private:
    virtual void handleMessage(InputStream& message)
    {
        EventType event(message);
        onEvent( event );
    }
};

I'm fully aware that the most derived class should initialize the base class, which would look like:

class A : public TypedHandler<SuperEvent>
        , public TypedHandler<DuperEvent>
{
public:
    A(Connection* conn) : Base(conn) {}

    void onEvent(const SuperEvent&)
    { ... }

    void onEvent(const DuperEvent&)
    { ... }
};

But I get "error C2512: no appropriate default constructor available virtual base class" at marked position (VS 2012, MSVC++ 11), even though Handler is never meant to be most derived...

Ideas ?

Edit: By allowing a default constructor to be generated (via Connection* conn = nullptr in constructor), it works. According to Igor's link the default constructor won't be called in Handler constructor, since Handler is virtual.

Edit2: By setting the virtual base class default constructor private, and setting the immediate two sub classes as friends + non-default constructor as protected, not only does it compile, but compilation fails if the most derived class does not intialize the virtual base class correctly. All checkboxes ticked! :)

Was it helpful?

Solution

This issue is fixed in clang 3.4, but not earlier. Given that it is a compiler bug or at least a contentious compiler trait, and that Base(Connection& conn) is protected, you might be able to go with an in-your-face conditional compilation workaround, e.g.

class Base {
protected:
#if HAVE_BUG_GCC19249
    Base(Connection& conn = _workaround_bug_gcc19249_) : myConn(conn) {;}
#else
    Base(Connection& conn) : myConn(conn) {;}
#endif

    Connection& myConn;

#if HAVE_BUG_GCC19249
    static Connection _workaround_bug_gcc19249_;
    // ... conditional definition in implementation file.
#endif
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top