Domanda

ho trascorso qualche tempo la rimozione di tutto il codice uninfluent e qui è il mio problema.

--- --- 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;
}

E questo è il file di output dopo la costruzione con cl e opzioni /D "WIN32" /D "_UNICODE" /D "UNICODE" e funzionante

--- --- test.txt

00414114test

Fondamentalmente ciò che accade è che la prima chiamata operator<< in main è legato al metodo membro

basic_ostream<char>& basic_ostream<char>::operator<<(
    const void *)

mentre la seconda è (correttamente) associato a

basic_ostream<char>& __cdecl operator<<(
    basic_ostream<char>&,
    const char *)

dando così un output diverso.

Questo non succede se faccio una delle seguenti:

        
  • Inline File::CreateOutput
  •     
  • Cambia DataOutput con un non-modello di uno con Element=char
  •     
  • Aggiungi *output; prima della prima chiamata operator<<

Ho ragione nel considerare questo un comportamento indesiderato compilatore?

C'è una spiegazione per questo?

Oh, e sto usando VC7 al momento di testare questo codice semplificato ma ho provato il codice originale in VC9 e VC8 e la stessa cosa stava accadendo.

Qualsiasi aiuto o anche un indizio è apprezzato

È stato utile?

Soluzione

Sembra un bug del compilatore. Si potrebbe desiderare di provare con l'ultimo compilatore VC (che al momento è VC10 Beta2), e se non è fisso, follow-up con il team di VC (avrete bisogno di un auto completa pronti contro termine contenute). Se è fisso, si dovrebbe utilizzare il lavoro intorno hai trovato e andare avanti con la tua vita.

Altri suggerimenti

Si tratta di un bug del compilatore (non solo si presenta come uno) in quanto produce diversi attacchi di chiamata per le due affermazioni identiche

    *output << "test"; // Calls wrong overload
    *output << "test"; // Calls right overload!!!

Tuttavia, il compilatore è nel suo pieno diritto per fare questo, dal momento che hai

    void main()

che significa che questo non è un programma valido C ++ (void main non è consentito in C sia, e non è mai stato valido in C o C ++). Quindi, siete stati in esecuzione il risultato della compilazione del codice sorgente non valido. Il risultato di questo può essere qualsiasi cosa.

Il fatto che il compilatore di Visual C ++ non diagnostica void main è solo un altro compilatore bug .

cambia

DataOutput * uscita (file.CreateOutput (false, false));

a

DataOutput * = uscita file.CreateOutput (false, false); e potrebbe funzionare. Ma per rendere questa funzione lib una ragionevole non è necessario pulire dopo, non si dovrebbe restituire un puntatore, ma un oggetto reale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top