From 5551932c253b608a7e0b2e72ddba97fca9ce2fd6 Mon Sep 17 00:00:00 2001 From: VZ Date: Tue, 29 Nov 2016 19:32:40 +0100 Subject: [PATCH] Allow using Bind() with non-public inheritance in C++11 code Using Bind() with a method of the class deriving from wxEvtHandler non-publicly used to result in a compile-time error, but at least with C++11 we can detect this case and allow the code to compile. Closes #17623. --- docs/changes.txt | 2 ++ include/wx/event.h | 2 +- include/wx/meta/convertible.h | 22 ++++++++++++++++++++++ include/wx/weakref.h | 2 +- tests/events/evthandler.cpp | 18 ++++++++++++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index bc8d33f0fa..daeca82066 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -79,6 +79,8 @@ All: - Handle strings with embedded NULs in wxDataStream (Nitch). - Don't crash in wxTextFile::GetLastLine() if the file is empty (crohr). - Add wxString::cbegin() and cend() method (Lauri Nurmi). +- Allow using Bind() with event handlers non-publicly deriving from + wxEvtHandler and/or wxTrackable in C++11 code (Raul Tambre, mmarsan). All (GUI): diff --git a/include/wx/event.h b/include/wx/event.h index 89d4659e15..1d781ba618 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -332,7 +332,7 @@ class wxEventFunctorMethod < Class, EventArg, - wxConvertibleTo::value != 0 + wxIsPubliclyDerived::value != 0 > { private: diff --git a/include/wx/meta/convertible.h b/include/wx/meta/convertible.h index 4599937821..a58d5f2370 100644 --- a/include/wx/meta/convertible.h +++ b/include/wx/meta/convertible.h @@ -34,5 +34,27 @@ struct wxConvertibleTo }; }; +// This is similar to wxConvertibleTo, except that when using a C++11 compiler, +// the case of D deriving from B non-publicly will be detected and the correct +// value (false) will be deduced instead of getting a compile-time error as +// with wxConvertibleTo. For pre-C++11 compilers there is no difference between +// this helper and wxConvertibleTo. +template +struct wxIsPubliclyDerived +{ + enum + { +#if __cplusplus >= 201103 || (defined(_MSC_VER) && _MSC_VER >= 1600) + // If C++11 is available we use this, as on most compilers it's a + // built-in and will be evaluated at compile-time. + value = std::is_base_of::value && std::is_convertible::value +#else + // When not using C++11, we fall back to wxConvertibleTo, which fails + // at compile-time if D doesn't publicly derive from B. + value = wxConvertibleTo::value +#endif + }; +}; + #endif // _WX_META_CONVERTIBLE_H_ diff --git a/include/wx/weakref.h b/include/wx/weakref.h index 4794c85ef0..f674f0d996 100644 --- a/include/wx/weakref.h +++ b/include/wx/weakref.h @@ -19,7 +19,7 @@ template struct wxIsStaticTrackable { - enum { value = wxConvertibleTo::value }; + enum { value = wxIsPubliclyDerived::value }; }; diff --git a/tests/events/evthandler.cpp b/tests/events/evthandler.cpp index 4fb44ccfb9..ac8b59bd0c 100644 --- a/tests/events/evthandler.cpp +++ b/tests/events/evthandler.cpp @@ -509,3 +509,21 @@ void EvtHandlerTestCase::UnbindFromHandler() handler.ProcessEvent(e); } + +// This is a compilation-time-only test: just check that a class inheriting +// from wxEvtHandler non-publicly can use Bind() with its method, this used to +// result in compilation errors. +// Note that this test will work only on C++11 compilers, so we test this only +// for such compilers. +#if __cplusplus >= 201103 +class HandlerNonPublic : protected wxEvtHandler +{ +public: + HandlerNonPublic() + { + Bind(wxEVT_IDLE, &HandlerNonPublic::OnIdle, this); + } + + void OnIdle(wxIdleEvent&) { } +}; +#endif // C++11