読者です 読者をやめる 読者になる 読者になる

meryngii.neta

今日も新たな"ネタ"を求めて。

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へのコメントに関して

日本発ということもあってやはり文字コード絡みの提案が多いです。

25.例外クラスのUnicode対応

戻り値によるオーバーロードはできないので少々厄介ですが、C言語のしがらみが無いのでむしろファイル名の問題より楽かもしれません。

27.システムに関わる文字列でstd::string/char*はUTF-8であるという規約が欲しい

実現できれば素晴らしい案だと思います。ファイル名の問題も全てconst char*に転送してしまえばいいわけです。ただ互換性を考えると少し難しいかなと思います。

*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にもありそうですが見つけられず。