diff --git a/docs/doxygen/mainpages/const_cpp.h b/docs/doxygen/mainpages/const_cpp.h index 75ffbad426..5453ca49a4 100644 --- a/docs/doxygen/mainpages/const_cpp.h +++ b/docs/doxygen/mainpages/const_cpp.h @@ -191,6 +191,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 98d06650ba..347d622ee7 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -285,12 +285,19 @@ typedef short int WXTYPE; #define wxOVERRIDE #endif /* HAVE_OVERRIDE */ -/* same for defaulted member function keyword */ +/* same for more C++11 keywords which don't have such historic baggage as + override and so can be detected by just testing for C++11 support (which + still requires handling MSVS specially, unfortunately) */ #if __cplusplus >= 201103L || wxCHECK_VISUALC_VERSION(14) #define wxHAS_MEMBER_DEFAULT #define wxMEMBER_DEFAULT = default + + #define wxHAS_NOEXCEPT + #define wxNOEXCEPT noexcept #else #define wxMEMBER_DEFAULT + + #define wxNOEXCEPT #endif /* 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)