Search code examples
c++inheritancec++14wxwidgets

Conversion in derived class inaccessible if base class is protected


Update:
This was a bug in wxWidgets. This has been fixed in wxWidgets 3.1.1, if you're using a C++11 compatible compiler.


I'm trying to dynamically bind an event handler to an event in wxWidgets. Unfortunately if the derived class is protected it doesn't seem to work.

Minimal example:

// Test.h
class Test : protected wxFrame
{
public:
    Test();

private:
    void sizing(wxSizeEvent& event);
};

// Test.cpp
Test::Test()
{
    Bind(wxEVT_SIZING, &Test::sizing, this);
}

void Test::sizing(wxSizeEvent& event)
{
}

That unfortunately doesn't seem to work and nets the following error on Visual Studio 2015 Update 3:

wxWidgets\include\wx/meta/convertible.h(31): error C2243: 'type cast': conversion from 'Test *' to 'wxEvtHandler *' exists, but is inaccessible
  wxWidgets\include\wx/event.h(335): note: see reference to class template instantiation 'wxConvertibleTo<Class,wxEvtHandler>' being compiled
          with
          [
              Class=Test
          ]
  wxWidgets\include\wx/event.h(3568): note: see reference to class template instantiation 'wxEventFunctorMethod<EventTag,Test,EventArg,EventHandler>' being compiled
          with
          [
              EventTag=wxEventTypeTag<wxSizeEvent>,
              EventArg=wxSizeEvent,
              EventHandler=Test
          ]
  Test.cpp(78): note: see reference to function template instantiation 'void wxEvtHandler::Bind<wxEventTypeTag<wxSizeEvent>,Test,wxSizeEvent,Test>(const EventTag &,void (__cdecl Test::* )(EventArg &),EventHandler *,int,int,wxObject *)' being compiled
          with
          [
              EventTag=wxEventTypeTag<wxSizeEvent>,
              EventArg=wxSizeEvent,
              EventHandler=Test
          ]

Changing the inheritance to public makes it work:

class Test : public wxFrame
  1. Why is the conversion inaccessible when the inheritance is protected?
  2. I do not wish to expose wxFrame to the world, but only the classes that derive the Test class. How can I do this while still being able to dynamically bind the event handler?

Solution

  • You could work around this using the following:

    Bind(wxEVT_SIZING, std::bind(&Test::sizing, this, std::placeholders::_1));
    

    Minimal sample that compiles:

    #include <wx/wx.h>
    #include <functional>
    using namespace std::placeholders;
    
    class Test : protected wxFrame
    {
    public:
        Test();
    
    private:
        void sizing(wxSizeEvent& event);
    };
    Test::Test()
    {
        Bind(wxEVT_SIZING, std::bind(&Test::sizing, this, _1));
    }
    
    void Test::sizing(wxSizeEvent& event)
    {
    }
    
    class MyApp: public wxApp
    {
    public:
        virtual bool OnInit();
    };
    class MyFrame: public wxFrame
    {
    public:
        MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
    private:
    };
    wxIMPLEMENT_APP(MyApp);
    bool MyApp::OnInit()
    {
        MyFrame *frame = new MyFrame( "", wxPoint(50, 50), wxSize(450, 340) );
        frame->Show( true );
        return true;
    }
    
    MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(NULL, wxID_ANY, title, pos, size)
    {
        Test* test = new Test();
    }