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! :)
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
};