Initializer list constructors cause ambiguous overloads in application code (Issue #24093)

115 views
Skip to first unread message

Gregor Riepl

unread,
Nov 26, 2023, 7:50:24 AM11/26/23
to wx-...@googlegroups.com, Subscribed

Description

Bug description:

In wxWidgets 3.2.4, support for C++ initializer lists in certain type constructors was introduced. (PR: #23309 )
This causes problems in 3rd party code, where transitive constructors are overloaded with other types that take initializer lists.

Specifically, PrusaSlicer fails to build with 3.2.4.

Expected vs observed behaviour:

Code like this should compile:

#include <string>
#include <vector>
#include <wx/arrstr.h>
struct Test {
	wxArrayString arr;
	Test(const std::vector<std::string> &values) {
		if (values.empty()) return;
		for (const auto &el : values) arr.Add(wxString(el));
	};
	Test(const wxArrayString &values) {
		if (values.empty()) return;
		for (const auto &el : values) arr.Add(wxString(el));
	};
};
int main() {
	Test({ std::string("Hello, world") });
}

This compiled fine with wxWidgets 3.2.3, but with 3.2.4, g++ reports the following error (gcc 13.2.0):

test.cpp: In function ‘int main()’:
test.cpp:16:45: error: call of overloaded ‘Test(<brace-enclosed initializer list>)’ is ambiguous
   16 |         Test({ std::string("Hello, world") });
      |                                             ^
test.cpp:10:9: note: candidate: ‘Test::Test(const wxArrayString&)’
   10 |         Test(const wxArrayString &values) {
      |         ^~~~
test.cpp:6:9: note: candidate: ‘Test::Test(const std::vector<std::__cxx11::basic_string<char> >&)’
    6 |         Test(const std::vector<std::string> &values) {
      |         ^~~~

Potential fixes:

Curiously, I expected that making the initializer list constructors explicit would help, but the transitive overload is still considered ambiguous by gcc:

class WXDLLIMPEXP_BASE wxArrayString : public wxArrayStringBase {
...
	template<typename U>
	explicit wxArrayString(std::initializer_list<U> list) : wxArrayStringBase(list) { }
...
};

Platform and version information

  • wxWidgets version you use: 3.2.4
  • wxWidgets port you use: wxGTK
  • OS and its version: Debian sid
    • GTK version: 3.24.38
    • Which GDK backend is used: X11
    • Desktop environment : N/A
    • Current theme: N/A


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/24093@github.com>

VZ

unread,
Nov 26, 2023, 12:09:36 PM11/26/23
to wx-...@googlegroups.com, Subscribed

Yes, I'm afraid this change shouldn't have been backported as it broke a lot of code and it could have been foreseen.

Unfortunately now that it is, we're not going to remove it as it would make the matters even worse, so the only fix is to work around it in the application code by using the explicit conversion from the initializer list to whichever class you want to use. E.g. in your case you'd use

Test(wxArrayString({ std::string("Hello, world") }));

or

Test(std::vector<std::string>({ std::string("Hello, world") }));

depending on what the intention is (the latter would restore the previous behaviour).

We could also allow predefining some wxDISABLE_ARRAYSTRING_INITLIST to exclude this ctor during the build, would this help?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/24093/1826837753@github.com>

Gregor Riepl

unread,
Nov 27, 2023, 6:58:44 AM11/27/23
to wx-...@googlegroups.com, Subscribed

Thanks for the explanation!

I worked around the issue with an explicit std::vector(), I think this is good enough for now.
As wxArrayString seems to be deprecated, it's probably better to refactor its usage anyway.
Do you have a timeframe when it will be removed completely?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/24093/1827694348@github.com>

VZ

unread,
Nov 27, 2023, 12:55:41 PM11/27/23
to wx-...@googlegroups.com, Subscribed

Do you have a timeframe when it will be removed completely?

It's not going to be removed in the observable future, there is just too much code using it and it still must be used in some places in wx API. The plan/hope is to get rid of these remaining places and it's, of course, recommended not to use it in any new code, but removing it would break way too many code bases, so it's not going to happen any time soon.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/24093/1828341313@github.com>

Reply all
Reply to author
Forward
0 new messages