Я, по общему признанию, склонен в этом ответе. Но я попытаюсь подкрепить свои утверждения ссылками на N3290 (который, к сожалению, более не доступен для общественности). И я также предложу решение.
Анализ:
Сводка wstring_convert
в [conversions.string] / p2 включает:
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
«Только экспозиция» означает, что wstring_convert
не должен содержать этих членов в этом порядке по этому написанию. Но элементы «только для экспозиции» используются для описания эффектов различных членов, и эти спецификации являются обязательными.
И поэтому возникает вопрос:
Что такое спецификация ~wstring_convert()
?
Это находится в p17 того же раздела ([conversions.string]):
~wstring_convert();
Эффекты: Деструктор должен удалить cvtptr
.
Это подразумевает, что ~Codecvt()
должен быть доступен, и, следовательно, libc ++ соответствует спецификации C ++ 11.
Я бы также согласился, что это королевская боль в заднице.
Решение:
Наличие всех фасетов C ++ 98/03 с защитой деструкторов оказалось очень неудобным. Вот адаптер, который может принять любой аспект и сделать его публичным деструктором:
template <class Facet>
class usable_facet
: public Facet
{
public:
template <class ...Args>
usable_facet(Args&& ...args)
: Facet(std::forward<Args>(args)...) {}
~usable_facet() {}
};
Теперь вы можете использовать этот универсальный адаптер в вашем коде:
typedef usable_facet<std::codecvt<wchar_t, char, std::mbstate_t>> C;
std::wstring_convert<C> gbconv(new C("zh_CN.gb18030"));
Надеюсь, это поможет.