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.
Howard hinnant
source share