VC den falschen Bediener die Wahl << Überlastung nur beim ersten Aufruf. Fehler?
-
21-09-2019 - |
Frage
Ich verbrachte einige Zeit, um alle uninfluent Code zu entfernen, und hier ist mein Problem.
--- --- 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;
}
Und das ist die Ausgabedatei nach dem Aufbau mit cl
und Optionen /D "WIN32" /D "_UNICODE" /D "UNICODE"
und läuft
--- --- test.txt
00414114test
Im Grunde, was passiert ist, dass der erste operator<<
Anruf in main
an die Element-Methode gebunden ist
basic_ostream<char>& basic_ostream<char>::operator<<(
const void *)
während die zweite ist (richtig) gebunden
basic_ostream<char>& __cdecl operator<<(
basic_ostream<char>&,
const char *)
also einen anderen Ausgang zu geben.
Dies geschieht nicht, wenn ich eine der folgenden Bedingungen tun:
- Inline
File::CreateOutput
- Ändern
DataOutput
mit einem nicht-Vorlage eines mitElement=char
- Add
*output;
vor dem erstenoperator<<
Anruf
Am i korrigieren diese einen unerwünschten Compiler Verhalten bei der Prüfung?
Gibt es eine Erklärung dafür?
Oh, und ich bin mit VC 7 zur Zeit diesen vereinfachten Code zu testen, aber ich habe den ursprünglichen Code in VC9 und VC8 versucht, und das gleiche passiert.
Jede Hilfe oder sogar ein Hinweis ist willkommen
Lösung
Sieht aus wie ein Compiler-Fehler. Sie könnten mit den neuesten VC-Compiler versuchen wollen (die im Moment ist VC10 Beta2), und wenn es nicht fixiert ist, folgen mit dem VC-Team (Sie erhalten eine komplette in sich geschlossene Repo müssen). Wenn es festgelegt ist, sollten Sie nur die Arbeit nutzen um dich gefunden und mit Ihrem Leben weitergehen.
Andere Tipps
Es ist ein Compiler Fehler (nicht sieht genauso aus wie ein), da es unterschiedliche Anruf Bindungen für die beiden identischen Aussagen erzeugt
*output << "test"; // Calls wrong overload
*output << "test"; // Calls right overload!!!
Doch die Compiler innerhalb seiner Rechte ist , dies zu tun, da Sie
void main()
Das bedeutet, dass dies kein gültiges C ++ Programm (void main
ist nicht erlaubt in C entweder, und es hat nie gültig gewesen in C oder C ++). So wurden Sie laufen das Ergebnis der Code ungültig Quelle kompilieren. Das Ergebnis, dass kann alles sein.
Die Tatsache, dass die Visual C ++ Compiler nicht diagnose void main
ist nur ein anderer Compiler Bug .
Veränderung
* Dataoutput Ausgang (file.CreateOutput (false false));
* Dataoutput output = file.CreateOutput (false, false); und es könnte funktionieren. Aber machen dies zu einem vernünftigen lib Funktion Sie müssen nicht aufräumen, nachdem Sie sollten keinen Zeiger, sondern ein tatsächliches Objekt zurück.