fstreamのファイル名
std::fstreamがファイル名をマルチバイト文字列(const char*とconst std::string&)でしか受け取れない件についてです。
template <class charT, class traits=char_traits<charT> > class basic_fstream : public basic_iostream<charT,traits> { public: // ... explicit basic_fstream(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out); explicit basic_fstream(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out); // ... void open(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out); void open(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out); // ... };
C++98からの問題で、ファイル名をワイド文字列(const wchar_t*やconst wstring&)で渡すことができません。*1
http://hw001.gate01.com/eggplant/tcf/cpp/wchar_t_trap.html
でもBoost.Filesystemのfstreamは受け取ることができます。*2
標準ライブラリでだけ用意されていないとはどういうことなんでしょうか。
調べていくと、どうやらC言語でもfopenに対応したワイド文字版の関数が無いようです。*3C++のfstreamはこれに従ったように見えます。
標準ライブラリがワイド文字列のファイル名を扱えない特別な理由は思い当たりません。まあ、C言語が絡んでくると伝統の一言で片づけられそうですが…。
char16/32_tが導入されるとwchar_tは排除されるのかもしれませんが、いずれにしてもファイル名にもUnicodeが使えるようにして下さいということです。
basic_stringについて
basic_string向けの関数も同時に定義する必要があります。しかし、現状のstd::stringの対応はs.c_str()でconst char*に転送されているだけです。std::wstringも同じようにconst wchar_t*に転送すればいいだけです。
// C++0xではコンストラクタの委譲が可能 template<class charT2, class traits2, class Alloc2> explicit basic_fstream(const basic_string<charT2, traits2, Alloc2>& s, ios_base::openmode mode = ios_base::in|ios_base::out) : basic_fstream(s.c_str(), mode) { }
openメンバ関数についても同様です。
CDへのコメントに関して
日本発ということもあってやはり文字コード絡みの提案が多いです。
*1:Visual C++では2005から独自拡張でconst wchar_t*を受け取ることができます。 http://www.sutosoft.com/room/archives/2008_02.html
*2:Boost.FilesystemはTR2に入るようで、std::fstreamは置き換えられるのかもしれません。
*3:やはりVisual C++には独自拡張で_wfopenという関数があります。http://msdn.microsoft.com/ja-jp/library/yeby3zcb(VS.80).aspx POSIXにもありそうですが見つけられず。