std::wstring_convertとstd::wstring_bufferって、std::localeと組み合わて使うのが難しいです。そんなわけで、その名前とは裏腹にstd::wstring (wchar_t)との組み合わせには使いづらいなあと思っています。
が、しかし、Visual C++はその辺、規格をいい感じにやっちゃって(無視して)いて、使えるようになっていることに気付いてしまいました。
このコード、コンパイルできてしまいました。もちろん、実行すればちゃんと動きます。
#include <codecvt> #include <locale> #include <string> #include <iostream> int main() { using codecvt_wchar = std::codecvt<wchar_t, char, std::mbstate_t>; std::locale loc(""); std::wstring_convert<codecvt_wchar> cv( &std::use_facet<codecvt_wchar>(loc)); std::string message = "あいうえお"; std::wstring wcs = cv.from_bytes(message); std::string mbs = cv.to_bytes(wcs); std::cout << mbs << std::endl; } |
wbuffer_convertも同様にコンパイルできました。
#include <codecvt> #include <locale> #include <string> #include <iostream> #include <sstream> int main() { using codecvt_wchar = std::codecvt<wchar_t, char, std::mbstate_t>; std::locale loc(""); std::wstring_convert<codecvt_wchar> cv( &std::use_facet<codecvt_wchar>(loc)); std::wbuffer_convert<codecvt_wchar> buf( std::cout.rdbuf(), &std::use_facet<codecvt_wchar>(loc)); std::wostream my_wcout(&buf); std::wstring wcs = cv.from_bytes("かきくけこ"); my_wcout << wcs << std::endl; } |
「こういう風に書くとダメなんですよー」という例を出すつもりで書き始めたら、逆にコンパイルエラーが出なくて、驚きました。
- wstring_convertおよびwstring_bufferのコンストラクタがコンパイルできている。標準規格では、仮引数の型が非constなポインタ型となっているのに、VC++ではconstなポインタ型となっている。use_facetの戻り値の型はconstな参照なのだが、そのせいでコンパイルが通る。
- wstring_convertおよびwstring_bufferのデストラクタがコンパイルできている。デストラクタでは、コンストラクタで渡したcodecvtへのポインタをdeleteすることになっているのだが、std::codecvtのデストラクタはprotected。VC++のwstring_convertとwbuffer_convertは、内部でstd::localeオブジェクトにcodecvtを持たせることで、この問題を回避している。
GCC (libstdc++)やClang (libc++)だといずれもコンパイルエラーです。
この実装、私がこういう風に使えたら良かったと考えていた感じです。その点では素晴らしいのですが、現実VC++だけが標準規格に沿っていないという現状では、あまり有用に使えないのですよね。
2017年1月15日追記: 後者について、開発元に質問が出ているのを見かけています: [Visual C++] Is it accepted std::wstring_convert/std::wbuffer_convert delete std::codecvt pointer ? – Developer Community
スポンサード リンク |