From f4f70102eaf7193eb8e87a3106e405c50efea246 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 9 Apr 2020 19:48:26 +0200 Subject: [PATCH 1/2] Define wxNOEXCEPT similarly to the existing wxOVERRIDE Also define wxHAS_NOEXCEPT allowing to check if noexcept is supported. This is not used in the library yet, but probably should be. --- docs/doxygen/mainpages/const_cpp.h | 1 + include/wx/defs.h | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/docs/doxygen/mainpages/const_cpp.h b/docs/doxygen/mainpages/const_cpp.h index 2a23d7381e..a355c74ac7 100644 --- a/docs/doxygen/mainpages/const_cpp.h +++ b/docs/doxygen/mainpages/const_cpp.h @@ -188,6 +188,7 @@ Currently the following symbols exist: @itemdef{wxHAS_NATIVE_ANIMATIONCTRL, Defined if native wxAnimationCtrl class is being used (this symbol only exists in wxWidgets 3.1.4 and later).} @itemdef{wxHAS_NATIVE_DATAVIEWCTRL, Defined if native wxDataViewCtrl class is being used (this symbol only exists in wxWidgets 3.1.4 and later).} @itemdef{wxHAS_NATIVE_WINDOW, Defined if wxNativeWindow class is available.} +@itemdef{wxHAS_NOEXCEPT, Defined if the currently used compiler supports C++11 @c noexcept. @c wxNOEXCEPT is defined as this keyword in this case, and as nothing otherwise.} @itemdef{wxHAS_NULLPTR_T, Defined if the currently used compiler supports C++11 @c nullptr.} @itemdef{wxHAS_IMAGES_IN_RESOURCES, Defined if Windows resource files or OS/2 resource files are available on the current platform.} diff --git a/include/wx/defs.h b/include/wx/defs.h index a7472b60b3..a08dfb557d 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -285,6 +285,14 @@ typedef short int WXTYPE; #define wxOVERRIDE #endif /* HAVE_OVERRIDE */ +/* same for noexcept keyword */ +#if __cplusplus >= 201703L || wxCHECK_VISUALC_VERSION(14) + #define wxHAS_NOEXCEPT + #define wxNOEXCEPT noexcept +#else + #define wxNOEXCEPT +#endif + /* Support for nullptr is available since MSVS 2010, even though it doesn't define __cplusplus as a C++11 compiler. From c3810da54937110df8a5cfc3aee66fde2960b593 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 9 Apr 2020 19:48:59 +0200 Subject: [PATCH 2/2] Allow using noexcept methods with event tables macros Explicitly remove noexcept before static-casting the member function pointer to the base class pointer type to avoid compilation error with C++17. Add a test checking that this does work now. Closes #18721. --- include/wx/event.h | 36 +++++++++++++++++++++++++++++++++++- tests/events/evthandler.cpp | 7 +++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/wx/event.h b/include/wx/event.h index 39ca40725d..1c9b794fd9 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -144,9 +144,43 @@ inline wxEventFunction wxEventFunctionCast(void (wxEvtHandler::*func)(T&)) wxGCC_WARNING_RESTORE_CAST_FUNCTION_TYPE() } +// Special hack to remove "noexcept" from the function type when using C++17 or +// later: static_cast<> below would fail to cast a member function pointer to a +// member of a derived class to the base class if noexcept is specified for the +// former, so remove it first if necessary. +#if __cplusplus >= 201703L + +namespace wxPrivate +{ + +// Generic template version, doing nothing. +template +struct RemoveNoexceptEventHandler +{ + using type = T; +}; + +// Specialization removing noexcept when it's specified. +// +// Note that this doesn't pretend to be generally suitable, this is just enough +// to work in our particular case. +template +struct RemoveNoexceptEventHandler +{ + using type = R (C::*)(E&); +}; + +} // namespace wxPrivate + +#define wxREMOVE_NOEXCEPT_EVENT_HANDLER(pmf) \ + static_cast::type>(pmf) +#else +#define wxREMOVE_NOEXCEPT_EVENT_HANDLER(pmf) pmf +#endif + // Try to cast the given event handler to the correct handler type: #define wxEVENT_HANDLER_CAST( functype, func ) \ - wxEventFunctionCast(static_cast(&func)) + wxEventFunctionCast(static_cast(wxREMOVE_NOEXCEPT_EVENT_HANDLER(&func))) // The tag is a type associated to the event type (which is an integer itself, diff --git a/tests/events/evthandler.cpp b/tests/events/evthandler.cpp index 6be6c2d1ec..dce3f762a5 100644 --- a/tests/events/evthandler.cpp +++ b/tests/events/evthandler.cpp @@ -122,6 +122,9 @@ public: void OnEvent(wxEvent&) { g_called.method = true; } void OnAnotherEvent(AnotherEvent&); void OnIdle(wxIdleEvent&) { g_called.method = true; } +#ifdef wxHAS_NOEXCEPT + void OnIdleNoExcept(wxIdleEvent&) noexcept { } +#endif private: wxDECLARE_EVENT_TABLE(); @@ -138,6 +141,10 @@ wxBEGIN_EVENT_TABLE(MyClassWithEventTable, wxEvtHandler) EVT_MYEVENT(MyClassWithEventTable::OnMyEvent) EVT_MYEVENT(MyClassWithEventTable::OnEvent) +#ifdef wxHAS_NOEXCEPT + EVT_IDLE(MyClassWithEventTable::OnIdleNoExcept) +#endif + // this shouldn't compile: //EVT_MYEVENT(MyClassWithEventTable::OnIdle) //EVT_IDLE(MyClassWithEventTable::OnAnotherEvent)