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)