以前より、Visual C++のファイルストリーム(basic_fstream, basic_ifstream, basic_ofstream)には、独自拡張が存在しました。ファイルパスをワイド文字列で指定できる実引数のコンストラクタとopenメンバー関数の多重定義です。理由は、WindowsのAPIがUTF-16 (wchar_t)でファイルパスを扱うためです。

さて、C++17でこれが標準に取り込まれることに気付きました。こうなったのは、std::filesystem::pathの影響です。代表として、C++17のbasic_fstreamのコンストラクタを見てみます。

basic_fstream(const char*, ios_base::openmode);
basic_fstream(const string&, ios_base::openmode);
// C++17で追加。ただし、value_typeがchar以外の場合のみ。
basic_fstream(const filesystem::path::value_type*, ios_base::openmode);
// C++17で追加。
basic_fstream(const filesystem::path&, ios_base::openmode);

多重定義が2つ追加されています。同様のものが、openメンバー関数にも、basic_ifstreamやbasic_ofstreamにも、basic_filebuf::openにも追加されています。

前回(filesystem::pathの文字の型)書いたように、filesystem::path::value_typeというのはpathクラス内で用いている文字型です。すなわち、Windows環境ではwchar_tになると考えています。

するとどうでしょう。今まで独自拡張として定義されてきた多重定義が、そのままconst filesystem::path::value_type*版に当てはまっています。

というわけで、このままいけば「ワイド文字列(const wchar_t*)でファイルパスをファイルストリームの実引数に渡す」ということがVC++の独自拡張ではなくなると考えています。

#include <fstream>
#include <iostream>
#include <string>
 
int main()
{
  // あるいはL"C:\\Windows\\win.ini"でも可
  std::ifstream is(LR"(C:\Windows\win.ini)");
  std::string s;
  std::getline(is, s);
  std::cout << s << std::endl;
}

こういうわけなので、この手のコードがUnix系でも使えるようになるという話ではありません。逆に言えば、MinGW (g++, clang++)やC++ Builderなど、Windowsターゲットなら期待できるのではないでしょうかという具合です。

C++17 filesystemが実装された暁には、std::filesystem::pathクラスオブジェクトでファイルパスを扱うことをおすすめします。が、今回はpathクラスを直接使わない場合の話でした。

スポンサード リンク

この記事のカテゴリ

  • ⇒ ワイド文字列でファイル名を指定する機能がC++標準に入るようだ
  • ⇒ ワイド文字列でファイル名を指定する機能がC++標準に入るようだ