Disabling wxString implicit conversion to std::string?

444 views
Skip to first unread message

kmcc...@gmail.com

unread,
Jan 9, 2017, 11:57:39 AM1/9/17
to wx-users
Hi list,

A question regarding wxString and std::string ...

With our build of wxWidgets 3.1.0, we find that the following code, which requests an implicit conversion from wxString to std::string, fails to compile on Linux (RHEL6 with GCC 4.8.4) --

  std::string s = wxString();

The compiler error looks something like:

error: conversion from ‘wxString’ to non-scalar type ‘std::string {aka std::basic_string<char>}’ requested

This is fine with us, it makes good sense that an explicit call to wxString::ToStdString() should be required in order to force the conversion.

However, on Windows (VS 2012 or VS 2015) we find that the above line of code *does* compile successfully.  This is a bit of a pain point since it means that code that mixes the two classes, even if successfully built and committed on Windows, has a fairly high likelihood of a build failure on our Linux automated build machines.

Could anyone suggest what we might need to do with our wxMSW build in order to prevent the implicit conversion from compiling there, too?  We tried looking at the wxString class code, but it is very complex ... perhaps this discrepancy between platforms is something to do with UTF-8 being the default on Linux but UTF-16 on Windows??

Thanks in advance,

--
Kevin B. McCarty
kmcc...@gmail.com

Stephan van den Akker

unread,
Jan 10, 2017, 4:47:19 AM1/10/17
to wx-users
Hi there,

Not an expert by any definition, but I have some experience with this.

The fact that the direct conversion is possible is probably due to the fact that the Windows versions of wxWidgets where compiled to use std:string as a parent object of wxString. There is a configure option "--enable-stl" that controls this.

Not sure how this works on Windows, but there probably is a similar mechanism to switch off the use of the stl. For the devs it might be worth to evaluate the possibility to do private or protected inheritance from std:string to wxString to prevent your problem.

Greetings,

Stephan van den Akker
the Netherlands

PB

unread,
Jan 10, 2017, 11:54:46 AM1/10/17
to wx-users
Hi,

regarding wxString and std::(w)string. As Stephan above indicated, at least on Windows, the behaviour is controlled by (at least) two compile-time options. In WXWIN\include\wx\msw\setup.h there is:

// Enable minimal interoperability with the standard C++ string class if 1.
// "Minimal" means that wxString can be constructed from std::string or
// std::wstring but can't be implicitly converted to them. You need to enable
// the option below for the latter.
//
// Default is 1 for most compilers.
//
// Recommended setting: 1 unless you want to ensure your program doesn't use
//                      the standard C++ library at all.
#define wxUSE_STD_STRING  wxUSE_STD_DEFAULT

// Make wxString as much interchangeable with std::[w]string as possible, in
// particular allow implicit conversion of wxString to either of these classes.
// This comes at a price (or a benefit, depending on your point of view) of not
// allowing implicit conversion to "const char *" and "const wchar_t *".
//
// Because a lot of existing code relies on these conversions, this option is
// disabled by default but can be enabled for your build if you don't care
// about compatibility.
//
// Default is 0 if wxUSE_STL has its default value or 1 if it is enabled.
//
// Recommended setting: 0 to remain compatible with the official builds of
// wxWidgets.
#define wxUSE_STD_STRING_CONV_IN_WXSTRING wxUSE_STL

I do not use Linux but it works similarly there, except the options are set with configure....

Regards, PB

Kevin B. McCarty

unread,
Jan 10, 2017, 1:02:37 PM1/10/17
to wx-u...@googlegroups.com
On Tue, Jan 10, 2017 at 8:54 AM, PB <pbfo...@gmail.com> wrote:
> Hi,
>
> regarding wxString and std::(w)string. As Stephan above indicated, at least
> on Windows, the behaviour is controlled by (at least) two compile-time
> options. In WXWIN\include\wx\msw\setup.h there is:

>> // Default is 0 if wxUSE_STL has its default value or 1 if it is enabled.
>> //
>> // Recommended setting: 0 to remain compatible with the official builds of
>> // wxWidgets.
>> #define wxUSE_STD_STRING_CONV_IN_WXSTRING wxUSE_STL

Thanks to you and Stephan, but that doesn't seem to be it: with some
suitable #ifdef and #error preprocessor directives I find that
wxUSE_STD_STRING_CONV_IN_WXSTRING does seem to be set to 0 (zero) in
our builds for both Linux and Windows.

Now, an interesting observation is that if on Windows, I build with
CXX=clang-cl (Clang's VS-compatibility-emulating wrapper, Clang
version 3.9.0) using essentially the same compiler flags, I get the
sorts of errors shown below that mention various wxString conversion
operators.

So I wonder if what is happening is that VS 2015 follows a two-step
path first from some wxString conversion operator to a pointer type,
and then from std::string's constructor from a char pointer? Not sure
why this would work in VS 2012 and 2015 but not in other compilers
(the usual lack of standards-compliance in VS perhaps??) but that's
the only thing I can come up with, in which case it might be difficult
to get this fixed ...

Clang errors follow:

.\testfile.cpp(215,17): error: no viable conversion from 'wxString'
to 'std::string' (aka 'basic_string<char, char_traits<char>,
allocator<char> >')
std::string x = wxString();
^ ~~~~~~~~~~
C:\Program Files (x86)\Microsoft Visual Studio
14.0\VC\INCLUDE\xstring(775,2): note: candidate constructor not
viable: no known conversion from 'wxString' to 'const _Myt &' (aka
'const basic_string<char, std::char_traits<char>, std::allocator<char>
> &') for 1st argument
basic_string(const _Myt& _Right)
^
C:\Program Files (x86)\Microsoft Visual Studio
14.0\VC\INCLUDE\xstring(834,2): note: candidate constructor not
viable: no known conversion from 'wxString' to 'const char *' for 1st
argument
basic_string(const _Elem *_Ptr)
^
C:\Program Files (x86)\Microsoft Visual Studio
14.0\VC\INCLUDE\xstring(909,2): note: candidate constructor not
viable: no known conversion from 'wxString' to '_Myt &&' (aka
'basic_string<char, std::char_traits<char>, std::allocator<char> >
&&') for 1st argument
basic_string(_Myt&& _Right) _NOEXCEPT
^
C:\Program Files (x86)\Microsoft Visual Studio
14.0\VC\INCLUDE\xstring(975,2): note: candidate constructor not
viable: no known conversion from 'wxString' to
'::std::initializer_list<char>' for 1st argument
basic_string(_XSTD initializer_list<_Elem> _Ilist,
^
d:\wxMSW-3.1.0\include\wx/string.h(1498,5): note: candidate function
operator wxCStrData() const { return c_str(); }
^
d:\wxMSW-3.1.0\include\wx/string.h(1507,5): note: candidate function
operator const char*() const { return c_str(); }
^
d:\wxMSW-3.1.0\include\wx/string.h(1508,5): note: candidate function
operator const wchar_t*() const { return c_str(); }
^
d:\wxMSW-3.1.0\include\wx/string.h(1513,5): note: candidate function
operator const void*() const { return c_str(); }
^
1 error generated.

kmcc...@gmail.com

unread,
Jan 10, 2017, 1:24:35 PM1/10/17
to wx-users
On Tuesday, January 10, 2017 at 10:02:37 AM UTC-8, Kevin B. McCarty wrote:

So I wonder if what is happening is that VS 2015 follows a two-step
path first from some wxString conversion operator to a pointer type,
and then from std::string's constructor from a char pointer?  Not sure
why this would work in VS 2012 and 2015 but not in other compilers
(the usual lack of standards-compliance in VS perhaps??)

Upon further research, this is a known bug in VS 2015 (and the test case provided at the bug filed in Connect also fails, i.e. successfully compiles, in VS 2012)

https://connect.microsoft.com/VisualStudio/feedback/details/2256407
http://stackoverflow.com/questions/32700574/multiple-user-defined-conversions-on-initialization

Sigh ...
Reply all
Reply to author
Forward
0 new messages