locked
Visual Studio 2015 Update 1 implicit string narrow wide conversion and _CONVERSION_DONT_USE_THREAD_LOCALE RRS feed

  • Question

  •  

    Hello,
    I want to use the feature of the CStringW to implicitly convert a narrow string to a wide string in the constructor with the CP_ACP conversion rule. In order to use this you have to define the _CONVERSION_DONT_USE_THREAD_LOCALE, this works with the A2W macros as expected - in atlconv.h the function AtlA2WHelper is called with acp == 0 == CP_ACP, but not for the CStringW constructor that calls operator= in cstringt.h. This operator calls StringTraits::ConvertToBaseType that calls MultiByteToWideChar with the first parameter returned by the function _AtlGetConversionACP that is always 3 == CP_THREAD_ACP and never CP_ACP.

    // Compile with _CONVERSION_DONT_USE_THREAD_LOCALE defined in C/C++ Preprocessor definitions
             
    // OS set to "Greek"
    char* s = "äöü";
    CStringW sw(s);       // sic! always CP_THREAD_ACP is passed to MultiByteToWideChar even if _CONVERSION_DONT_USE_THREAD_LOCALE is defined
    
    USES_CONVERSION; 
    CStringW sww(A2W(s)); // works as expected, AtlA2WHelper is called with CP_ACP that is passed to MultiByteToWideChar

    Thanks for the help,


    Andreas

    Tuesday, March 22, 2016 8:50 AM

All replies

  • In my copy of VC++2015 Community Update 1 the _AtlGetConversionACP function is at line 104 of atlconv.h and appears as

    inline UINT WINAPI _AtlGetConversionACP() throw()
    {
    #ifdef _CONVERSION_DONT_USE_THREAD_LOCALE
    	return CP_ACP;
    #else
    	return CP_THREAD_ACP;
    #endif
    }
    

    I don't understand how it could return CP_THREAD_ACP if _CONVERSION_DONT_USE_THREAD_LOCALE has been defined.

    Tuesday, March 22, 2016 11:51 AM
  • char* s = "äöü";
    CStringW sw(s);       // sic! always CP_THREAD_ACP is passed to MultiByteToWideChar even if _CONVERSION_DONT_USE_THREAD_LOCALE is defined
    
    USES_CONVERSION; 
    

    Hi,

    I am sorry. Could you please provide me more information, I am confused. If you use the new ATL 7.0 Conversion classes, you never require USES_CONVERSION to be defined.

    If you have free time, please see the ATL and MFC String Conversion Macros.

    https://msdn.microsoft.com/en-us/library/87zae4a3(v=vs.90).aspx

    Best Regards,

    Hart


    Wednesday, March 23, 2016 6:30 AM
  • Seems that you have to recompile the MFC library, since it was built with different value of _CONVERSION_DONT_USE_THREAD_LOCALE.

    Another workaround: use CW2A or CW2AEX with CP_ACP argument.

    Wednesday, March 23, 2016 6:54 AM
  • You are right, I don't need the USES_CONVERSION any more, copied the lines from a very old project - but that is not the matter - the question was about CStringW's implicit narrow to wide conversion.


    Andreas

    Wednesday, March 23, 2016 8:21 AM
  • the question was about CStringW's implicit narrow to wide conversion.


    Andreas

    Hi,

    Based on my research. CStringW is the wide character string only version. I don’t understand this sentence.

    You can see the MSDN document to understand the CStringW.

    https://msdn.microsoft.com/en-us/library/ms235631.aspx

    Best Regards,

    Hart


    Wednesday, March 23, 2016 9:07 AM
  • the question was about CStringW's implicit narrow to wide conversion.


    Andreas

    Hi,

    Based on my research. CStringW is the wide character string only version. I don’t understand this sentence.

    You can see the MSDN document to understand the CStringW.

    https://msdn.microsoft.com/en-us/library/ms235631.aspx

    Best Regards,

    Hart


    If you try some sample code in VC++ 2015 Update 1 you will find that there is a CStringW constructor that accepts ASCII strings.   Stepping through the constructor will reveal where and how the _AtlGetConversionACP function is called.
    Wednesday, March 23, 2016 9:59 AM
  • Hi,

    Yes, thanks for explanation, I also reproduce the issue. As end-user I don’t know why the Microsoft designed.

    Best Regards,

    Hart


    • Edited by Hart Wang Thursday, March 24, 2016 6:41 AM
    Thursday, March 24, 2016 6:38 AM
  • I submitted this issue to Microsoft connect, see https://connect.microsoft.com/VisualStudio/feedback/details/2508989

    Please vote that you can reproduce it.

    Thanks,


    Andreas

    • Proposed as answer by Hart Wang Friday, March 25, 2016 6:59 AM
    Thursday, March 24, 2016 10:25 AM
  • Hi,

    Yes, thanks for explanation, I also reproduce the issue. As end-user I don’t know why the Microsoft designed.


    This is unclear.  Were you able to reproduce the issue described by the original poster regarding incorrect use of CP_THREAD_ACP or are you saying that you now understand that the CStringW class includes a constructor that accepts narrow character strings?
    Thursday, March 24, 2016 11:20 AM
  • Hi,

    Yes, thanks for explanation, I also reproduce the issue. As end-user I don’t know why the Microsoft designed.


    This is unclear.  Were you able to reproduce the issue described by the original poster regarding incorrect use of CP_THREAD_ACP or are you saying that you now understand that the CStringW class includes a constructor that accepts narrow character strings?

    Hi,

    I say that i now understand that the CStringW class includes a constructor that accepts narrow character strings.

    Best Regards,

    Hart

    Friday, March 25, 2016 6:59 AM
  • I say that i now understand that the CStringW class includes a constructor that accepts narrow character strings.

    Best Regards,

    Hart

    Thank you for the clarification.  I suggest you visit the issue opened by the original poster at https://connect.microsoft.com/VisualStudio/feedback/details/2508989 since it asserts that you were able to reproduce the original poster's CP_THREAD_ACP issue.

    Friday, March 25, 2016 10:35 AM
  • I submitted this issue to Microsoft connect, see https://connect.microsoft.com/VisualStudio/feedback/details/2508989

    Frankly I do not know why you are bothering with this automatic conversion feature in CString. I regard this feature as extremely dangerous, and I think your post is an illustration of that fact.

    I have banished use of the local code page from my code, but sometimes I use both UTF-8 and UTF-16 in an application. My most feared failure case is

    CString str(someUtf8String);
    

    Actually, if CString could be configured to use UTF-8 as the 8-bit character set, I might consider using the automatic conversion, but AFAIK it can't.


    David Wilkinson | Visual C++ MVP

    Friday, March 25, 2016 1:42 PM
  • >> I submitted this issue to Microsoft connect, see https://connect.microsoft.com/VisualStudio/feedback/details/2508989
    I think the bug report is worthwhile if it only serves to get MS to
    mark the conversion constructor as deprecated - with a note to not use
    ii because of this issue.

    Dave

    Friday, March 25, 2016 6:50 PM
  • So far the issue has not been reproduced by any of the folks who have responded to the post.
    Friday, March 25, 2016 6:57 PM
  •  Alexander [MSFT]  could reproduce this issue, see https://connect.microsoft.com/VisualStudio/feedback/details/2508989/implicit-string-narrow-wide-conversion-and-conversion-dont-use-thread-locale-does-not-work-as-expected

    he recommends statically linking against MFC - no option for me.

    he suggest making the conversion explicitly and use use the ATL 7.0 string conversion macros - I want to get rid of all this "ugly" macro stuff.

    It would be very nice if the developer team of MFC would solve this issue and I could use the ctor that does all the stuff and I could get rid of this "ugly" macro stuff from my code.

    And also resolve the CArchive problem when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined:

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/f3f53a82-55de-4283-98d0-f9e84a2d7ebe/visual-studio-2015-update-1-cstringdisablenarrowwideconversion-and-carchiveoperator-error?forum=vcgeneral#6b122e07-0ecb-4ebc-8fe8-cb0484ffde7e

    Thanks,


    Andreas

    Thursday, May 19, 2016 9:45 AM
  • It appears that the MFC Dlls are the culprit in this case.  That explains why any attempt to replicate the issue using ATL without dynamically linked MFC  was unsuccessful. 

    It seems that there will always be a risk that distributed Dlls have been created using choices that later conflict with those made by the developer.

    Perhaps these things should be documented by MS so that it doesn't require a bug hunt to resolve unexpected behavior?

    Thursday, May 19, 2016 10:12 AM
  • >Perhaps these things should be documented by MS so that it doesn't require a bug hunt to resolve unexpected behavior?

    Perhaps they should issue compiler warnings (deprecated functions
    maybe) as well as being documented - so there's more likelihood that
    folks will be aware of the issue?

    Dave

    Thursday, May 19, 2016 10:34 AM
  • he suggest making the conversion explicitly and use use the ATL 7.0 string conversion macros - I want to get rid of all this "ugly" macro stuff.

    The ATL 7.0 converions, such as CA2W, are not macros, they are classes. They do not require USES_CONVERSION.

    Personally, I much prefer explicit use of these conversion classes to using a hidden (mis-)feature of CString.


    David Wilkinson | Visual C++ MVP

    Friday, May 20, 2016 10:25 AM
  • The reason for this is that the MFC variant of CString use an instance of _AtlGetConversionACP() that is already compiled into the MFC dll.

    _CONVERSION_DONT_USE_THREAD_LOCALE only works for CAtlString.

    If you don't use MFC, CString is typedef'ed CAtlString (aka the ATL variant of CString), and this then of course works for both type names.

    If you use the type CAtlString it works even when using MFC.


    Thursday, October 20, 2016 8:25 PM