影響のないコードをすべて削除するのに少し時間を費やしましたが、これが私の問題です。
--- File.h ---
#include <fstream>
#include <string>
template <typename Element>
class DataOutput : public std::basic_ofstream<Element>
{
public:
DataOutput(const std::string &strPath, bool bAppend, bool bBinary)
: std::basic_ofstream<Element>(
strPath.c_str(),
(bAppend ? ios_base::app : (ios_base::out | ios_base::trunc)) |
(bBinary ? ios_base::binary : 0))
{
if (is_open())
clear();
}
~DataOutput()
{
if (is_open())
close();
}
};
class File
{
public:
File(const std::string &strPath);
DataOutput<char> *CreateOutput(bool bAppend, bool bBinary);
private:
std::string m_strPath;
};
--- File.cpp ---
#include <File.h>
File::File(const std::string &strPath)
: m_strPath(strPath)
{
}
DataOutput<char> *File::CreateOutput(bool bAppend, bool bBinary)
{
return new DataOutput<char>(m_strPath, bAppend, bBinary);
}
--- main.cpp ---
#include <File.h>
void main()
{
File file("test.txt");
DataOutput<char> *output(file.CreateOutput(false, false));
*output << "test"; // Calls wrong overload
*output << "test"; // Calls right overload!!!
output->flush();
delete output;
}
そしてこれは、cl
オプション/D "WIN32" /D "_UNICODE" /D "UNICODE"
を使用してビルドして実行した後の出力ファイルです
--- test.txt ---
00414114test
基本的に何が起こるかというと、最初のoperator<<
呼び出しmain
はメンバーメソッドにバインドされます
basic_ostream<char>& basic_ostream<char>::operator<<(
const void *)
一方、2番目のものは(正しく)バインドされています
basic_ostream<char>& __cdecl operator<<(
basic_ostream<char>&,
const char *)
したがって、異なる出力が得られます。
次のいずれかを実行した場合、これは発生しません。
- 列をなして
File::CreateOutput
DataOutput
非テンプレートのものに変更しますElement=char
- 最初の呼び出し
*output;
の前に追加operator<<
これを望ましくないコンパイラの動作と見なすのは正しいですか?
これについて何か説明はありますか?
ああ、私は現在この簡略化されたコードをテストするためにVC7を使用していますが、VC9とVC8で元のコードを試しましたが、同じことが起こっていました。
どんな助けや手がかりさえもありがたいです