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.
This commit is contained in:
parent
f4f70102ea
commit
c3810da549
@ -144,9 +144,43 @@ inline wxEventFunction wxEventFunctionCast(void (wxEvtHandler::*func)(T&))
|
|||||||
wxGCC_WARNING_RESTORE_CAST_FUNCTION_TYPE()
|
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 <typename T>
|
||||||
|
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 <typename R, typename C, typename E>
|
||||||
|
struct RemoveNoexceptEventHandler<R (C::*)(E&) noexcept>
|
||||||
|
{
|
||||||
|
using type = R (C::*)(E&);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace wxPrivate
|
||||||
|
|
||||||
|
#define wxREMOVE_NOEXCEPT_EVENT_HANDLER(pmf) \
|
||||||
|
static_cast<wxPrivate::RemoveNoexceptEventHandler<decltype(pmf)>::type>(pmf)
|
||||||
|
#else
|
||||||
|
#define wxREMOVE_NOEXCEPT_EVENT_HANDLER(pmf) pmf
|
||||||
|
#endif
|
||||||
|
|
||||||
// Try to cast the given event handler to the correct handler type:
|
// Try to cast the given event handler to the correct handler type:
|
||||||
#define wxEVENT_HANDLER_CAST( functype, func ) \
|
#define wxEVENT_HANDLER_CAST( functype, func ) \
|
||||||
wxEventFunctionCast(static_cast<functype>(&func))
|
wxEventFunctionCast(static_cast<functype>(wxREMOVE_NOEXCEPT_EVENT_HANDLER(&func)))
|
||||||
|
|
||||||
|
|
||||||
// The tag is a type associated to the event type (which is an integer itself,
|
// The tag is a type associated to the event type (which is an integer itself,
|
||||||
|
@ -122,6 +122,9 @@ public:
|
|||||||
void OnEvent(wxEvent&) { g_called.method = true; }
|
void OnEvent(wxEvent&) { g_called.method = true; }
|
||||||
void OnAnotherEvent(AnotherEvent&);
|
void OnAnotherEvent(AnotherEvent&);
|
||||||
void OnIdle(wxIdleEvent&) { g_called.method = true; }
|
void OnIdle(wxIdleEvent&) { g_called.method = true; }
|
||||||
|
#ifdef wxHAS_NOEXCEPT
|
||||||
|
void OnIdleNoExcept(wxIdleEvent&) noexcept { }
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
@ -138,6 +141,10 @@ wxBEGIN_EVENT_TABLE(MyClassWithEventTable, wxEvtHandler)
|
|||||||
EVT_MYEVENT(MyClassWithEventTable::OnMyEvent)
|
EVT_MYEVENT(MyClassWithEventTable::OnMyEvent)
|
||||||
EVT_MYEVENT(MyClassWithEventTable::OnEvent)
|
EVT_MYEVENT(MyClassWithEventTable::OnEvent)
|
||||||
|
|
||||||
|
#ifdef wxHAS_NOEXCEPT
|
||||||
|
EVT_IDLE(MyClassWithEventTable::OnIdleNoExcept)
|
||||||
|
#endif
|
||||||
|
|
||||||
// this shouldn't compile:
|
// this shouldn't compile:
|
||||||
//EVT_MYEVENT(MyClassWithEventTable::OnIdle)
|
//EVT_MYEVENT(MyClassWithEventTable::OnIdle)
|
||||||
//EVT_IDLE(MyClassWithEventTable::OnAnotherEvent)
|
//EVT_IDLE(MyClassWithEventTable::OnAnotherEvent)
|
||||||
|
Loading…
Reference in New Issue
Block a user