s のコピー不可能な性質について助けが必要[io](f)stream
です。
fstream
Windows でファイル名に Unicode 文字を含むファイルを処理するには、s の周りにハック的なラッパーを提供する必要があります。このために、ラッパー関数を考案しました。
bool open_ifstream( istream &stream, const string &filename )
{
#ifdef __GLIBCXX__
FILE* result = _wfopen( convert_to_utf16(filename).c_str(), L"r" );
if( result == 0 )
return false;
__gnu_cxx::stdio_filebuf<char>* buffer = new __gnu_cxx::stdio_filebuf<char>( result, std::ios_base::in, 1 );
istream stream2(buffer);
std::swap(stream, stream2);
#elif defined(_MSC_VER)
stream.open( convert_to_utf16(filename) );
#endif
return !!stream;
}
もちろん、std::swap
ラインが犯人です。関数からストリームを返すことも試みましたが、同じ問題が発生します。a のコピー コンストラクタstd::istream
はdelete
d です。私も試してみましたstd::move
が、それは役に立ちませんでした。この問題を回避するにはどうすればよいですか?
編集:Keep It Simple (TM)
@tiburのアイデアのおかげで、私はついに良い方法を見つけましたが、機能的です。使用されている Windows 標準 C++ ライブラリに依存するという意味ではまだハックですが、実際に使用されているのは 2 つだけなので、私にとってはそれほど問題ではありません。
#include <fstream>
#include <memory>
#if _WIN32
# if __GLIBCXX__
# include<ext/stdio_filebuf.h>
unique_ptr<istream> open_ifstream( const string &filename )
{
FILE* c_file = _wfopen( convert_to_utf16(filename).c_str(), L"r" );
__gnu_cxx::stdio_filebuf<char>* buffer = new __gnu_cxx::stdio_filebuf<char>( c_file, std::ios_base::in, 1 );
return std::unique_ptr<istream>( new istream(buffer) );
}
# elif _MSC_VER
unique_ptr<ifstream> open_ifstream( const string &filename )
{
return unique_ptr<ifstream>(new ifstream( convert_to_utf16(filename)) );
}
# else
# error unknown fstream implementation
# endif
#else
unique_ptr<ifstream> open_ifstream( const string &filename )
{
return unique_ptr<ifstream>(new ifstream(filename) );
}
#endif
そしてユーザーコードでは:
auto stream_ptr( open_ifstream(filename) );
auto &stream = *stream_ptr;
if( !stream )
return emit_error( "Unable to open nectar file: " + filename );
これは C++0x<memory>
とauto
キーワードに依存します。もちろんclose
、結果のstream
変数だけを取得することはできませんが、GNU Libstdc++std::istream
デストラクタがファイルを閉じる処理を行うため、余分なメモリ管理はどこにも必要ありません。