Lib ++ vs V ++: Is it possible to make conversions without UTF using wstring_convert?

C ++ 11 std::wstring_convert works fine * for standard conversions UTF-8 ↔ UTF-16 / UCS2 / UCS4. However, when I tried to instantiate wstring_convert or wbuffer_convert with a face not of <codecvt> , it did not work properly:

 // works as expected std::wstring_convert<std::codecvt_utf8<wchar_t>> ucs4conv; // Now, by analogy, I want to try this: std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>> gbconv( new std::codecvt_byname<wchar_t, char, std::mbstate_t>("zh_CN.gb18030")); 

Clang ++ error saying "calling protected codecvt <> in ~ wstring_convert"

Visual Studio allows this (although it lacks this locale, but this is another story), because its wstring_convert puts the facet pointer life cycle management in the locale object that it holds as a member, and the locales know how to delete pointers to all faces.

Is Visual Studio and libC ++ correct?

* implemented in clang ++ - 2.9 / lib ++ - svn and Visual Studio 2010 EE SP1, the following example works on both, but not in GCC, unfortunately: https://ideone.com/hywz6

+8
c ++ c ++ 11 non-unicode
source share
1 answer

I'm admittedly biased in this answer. But I will try to support my claims with links to the N3290 (which, unfortunately, is no longer public). And I also offer a solution.

Analysis:

The wstring_convert summary in [conversionions.string] / p2 includes:

 private: byte_string byte_err_string; // exposition only wide_string wide_err_string; // exposition only Codecvt *cvtptr; // exposition only state_type cvtstate; // exposition only size_t cvtcount; // exposition only 

"Summary only" means that wstring_convert should not have these members in that order with this spelling. But "only from exposure" members are used to describe the effects of different members, and these specifications are mandatory.

So the question is:

What is the specification of ~wstring_convert() ?

This is in p17 of the same section ([conversionions.string]):

~wstring_convert();

Effects: The destructor should remove cvtptr .

This means that ~Codecvt() should be available, so libC ++ follows the C ++ 11 specification.

I also agree that this is a royal pain in the butt.

Decision:

Having all aspects of C ++ 98/03 protected destructors turned out to be very inconvenient. Here is an adapter that can take any face and give it a public destructor:

 template <class Facet> class usable_facet : public Facet { public: template <class ...Args> usable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {} ~usable_facet() {} }; 

Now you can use this generic adapter in your code:

 typedef usable_facet<std::codecvt<wchar_t, char, std::mbstate_t>> C; std::wstring_convert<C> gbconv(new C("zh_CN.gb18030")); 

Hope this helps.

+10
source share

All Articles