Opened 2 months ago

Closed 2 months ago

#19266 closed defect (fixed)

Fix for ticket 17623 (Bind doesn't work for private and protected inheritance) fails with GCC11 and std=gnu++17 mode

Reported by: mgimenez Owned by: Vadim Zeitlin <vadim@…>
Priority: normal Milestone: 3.1.6
Component: GUI-all Version: dev-latest
Keywords: gcc11 bind C++17 Cc: webmaster@…
Blocked By: Blocking:
Patch: no

Description (last modified by vadz)

The fix for ticket #17623 works OK with GCC11 and std=gnu++11 or std=gnu++14, but fails (with the same original error) when using std=gnu++17 (default value for GCC11):

/usr/include/wx-3.1/wx/event.h:157:12: error: 'wxEvtHandler' is an inaccessible base of 'CCManager'

where wxEvtHandler is a private base of CCManager. You can see this thread in the Code::Blocks forum

Using current head in C::B and wxWidgets. Reported on Arch Linux.

Change History (10)

comment:1 Changed 2 months ago by vadz

  • Description modified (diff)
  • Keywords C++17 added
  • Milestone set to 3.1.6

Can the problem be reproduced just with the test code added to tests/events/evthandler.cpp as part of #17623 fix or is something more needed?

comment:2 Changed 2 months ago by mmarsan

Can you tell what's the output of this code?

#include <iostream>

int main()
{
    std::cout << "__cplusplus= " << __cplusplus << std::endl;
    return (int)__cplusplus;
}

When executed with https://wandbox.org/ (I tried different compiler/flag version) it gives

__cplusplus= 201703

and the 'int' return is '231'

As I side note, https://gcc.godbolt.org/ shows that __cplusplus is well defined for all GCC/ICC/Clang compilers, but not for MSVC. That's why wx code tests __cplusplus and MSVC version.

comment:3 Changed 2 months ago by mmarsan

  • Cc mmarsan@… added

To add a bit of info here, I have searched the origin of the issue.
At http://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/ccmanager.cpp:290:22
we find iside CCmanager ctor:

 m_pHtml->Connect(wxEVT_COMMAND_HTML_LINK_CLICKED,
                     wxHtmlLinkEventHandler(CCManager::OnHtmlLink), nullptr, this);

m_pHtml is a wxHtmlWindow*

comment:4 Changed 2 months ago by mgimenez

  • Cc webmaster@… added

I cannot contact the OP from the C::B forum, i sent him a private message and an email, but there is no response.

His problem was fixed specifying -std=gnu++14 to override the default ghu++17

comment:5 Changed 2 months ago by mmarsan

  • Cc mmarsan@… removed

I don't think this ticket is related to #17623, despite of both have in common deriving non-publicly from wxEventHander.

The issue origins at wxHtmlLinkEventHandler(CCManager::OnHtmlLink), which uses the wxEVENT_HANDLER_CAST( functype, func ) defined at include/wx/event.h::193

A static_cast<functype>(&func) call is used in all C++version-depending branches.

To me, the difference is that for ver < C++17 it uses (wxEvtHandler::*wxXXXEventFunction)(wxXXXEvent) as functype while for ver = C++17 it tries to cast to (wxEventHander::*)(wxXXXEvent)

comment:6 Changed 2 months ago by vadz

Sorry, I'm still not sure about the answer to the question in the comment:1: do we have a simple way of reproducing the problem? I.e. a simple patch to tests/events/evthandler.cpp?

This needs to be fixed, of course, the workaround of not using C++17 is unacceptable, and I'll try to debug it myself, but if you already have a way of reproducing it, please post/attach it here. TIA!

comment:7 Changed 2 months ago by mmarsan

Mmmm, add these two lines in HandlerNonPublic() at tests/events/evthandler.cpp

UnBind(wxEVT_IDLE, &HandlerNonPublic::OnIdle, this);
Connect(wxEVT_IDLE, wxIdleEventHandler(HandlerNonPublic::OnIdle),nullptr, this);

comment:8 Changed 2 months ago by vadz

Thanks, I can indeed reproduce the problem with g++ -std=c++17 with Connect().

But thinking more about this, we've never guaranteed that using Connect() with classes not publicly-deriving from wxEvtHandler was supposed to work and it takes a wxObjectEventFunction which is a pointer to wxEvtHandler method. So I don't think this is a bug at all, after all: you just need to use either public inheritance with Connect(), or Bind().

Am I missing something here or could this be simply closed, maybe after mentioning this issue in Connect() documentation?

comment:9 Changed 2 months ago by mmarsan

IMHO Connect is designed for publicly deriving from wxEventHandler, ans it should be mentioined in the docs.

I still have a doubt for Bind. For non-publicly it continues as if the passed &C::*f was a function/functor. I mean, if it loses the 'handler' info how can the per-instance binding is achieved?

comment:10 Changed 2 months ago by Vadim Zeitlin <vadim@…>

  • Owner set to Vadim Zeitlin <vadim@…>
  • Resolution set to fixed
  • Status changed from new to closed

In 9b5a72bd1/git-wxWidgets:

Document Connect() limitations compared to Bind()

Instead of just saying that Bind() is better, provide some points
illustrating why is it better.

Notable mention that Connect() can only be used with methods of the
classes publicly inheriting from wxEvtHandler, unlike Bind().

Closes #19266.

Note: See TracTickets for help on using tickets.