8

C++11は、標準の UTF-8 <-> UTF-16/UCS2/UCS4 変換にstd::wstring_convert最適です。*ただし、からではないファセットを使用して wstring_convert または wbuffer_convert をインスタンス化しようとすると、<codecvt>期待どおりに機能しませんでした。

// 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 ++は、「〜wstring_convertでcodecvt <>の保護されたデストラクタを呼び出しています」というエラーを出します

Visual Studio ではそれが可能です (ただし、そのロケールはありませんが、それは別の話です)。これは、その wstring_convert がメンバーとして保持するロケール オブジェクトへのファセット ポインターの有効期間管理をポーンし、ロケールがすべてのファセットへのポインターを削除する方法を知っているためです。

Visual Studio は正しく、libc++ は間違っていますか?

*clang++-2.9/libc++-svn および Visual Studio 2010 EE SP1 で実装されているように、次の例は両方で機能しますが、悲しいことに GCC では機能しません: https://ideone.com/hywz6

4

1 に答える 1

10

私は確かにこの答えに偏っています。しかし、私は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()

これは、同じセクション([conversions.string])のp17にあります。

~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"));

お役に立てれば。

于 2011-09-29T15:50:24.337 に答える