PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : std::map<int, fstream&> und GCC 2.95



7.e.Q
17-11-2006, 10:47
Hi Leute,

ich glaub, ich bin mal wieder zu blöd... ist sowas da nicht möglich?




static std::map<int, fstream&> vJobMap;

.
.
.
int JobNo = 1234;

fstream tFile("/abc.bin", ios::out | ios::binary);
vJobMap[JobNo] = tFile;

if( vJobMap.find(JobNo) != vJobMap.end() ) ...
if( vJobMap[JobNo].is_open() ) vJobMap[JobNo].close();



Ich bekomme da so lustige Fehlermeldungen wie "forming reference to reference type `fstream &'" und solche Sachen...

Kann mir das mal jemand erklären? Achtung, GCC ist Version 2.95. Vielleicht liegt's daran?

Danke!

Grüße,
Hendrik


EDIT:

Arbeite ich hier ohne & (also std::map<int, fstream> vJobMap;), so bekomme ich in allen Fällen, wo ich Zugriff auf das Feld in der Map nehme




std::map<int, fstream> vJobMap;

int JobNo = 1234;

vJobMap[JobNo].open("/abc.bin", ios::out | ios::binary);


die Fehlermeldung `ios::ios(const ios &)' is private within this context, welche auf die "...open(...)" Zeile zeigt.

Was ist das?

locus vivendi
17-11-2006, 11:15
ich glaub, ich bin mal wieder zu blöd... ist sowas da nicht möglich?


Code:

static std::map<int, fstream&> vJobMap;

.
.
.
int JobNo = 1234;

fstream tFile("/abc.bin", ios::out | ios::binary);
vJobMap[JobNo] = tFile;

if( vJobMap.find(JobNo) != vJobMap.end() ) ...
if( vJobMap[JobNo].is_open() ) vJobMap[JobNo].close();
Ich bekomme da so lustige Fehlermeldungen wie "forming reference to reference type `fstream &'" und solche Sachen...

Kann mir das mal jemand erklären? Achtung, GCC ist Version 2.95. Vielleicht liegt's daran?
Da sind mehrere Dinge falsch. Erstens darfst du keine Referenzen in Standard-Container legen (Elemente von Standard-Containern müssen CopyConstructible sein). Zweitens kannst du auch keine Fstreams zuweisen. Drittens, die Fehlermeldung "forming reference to reference" ist damals als der Gcc 2.95 aktuell war korrekt gewesen. Heute wäre sie glaube ich nicht mehr korrekt, denn soweit ich weiss, reduziert sich seit 2003 "Referenz auf Referenz" auf "Refererenz". Zumindest aber im aktuellen Workingpaper zu C++ ist diese Regelung drin.

Ich würde aber auch ohne dieses spezielle Problem davon abraten so einen alten Compiler zu verwenden.


Arbeite ich hier ohne & (also std::map<int, fstream> vJobMap;), so bekomme ich in allen Fällen, wo ich Zugriff auf das Feld in der Map nehme


Code:

std::map<int, fstream> vJobMap; [...]
Ähnliches Problem wie oben: Fstream ist nicht kopierbar.

anda_skoa
17-11-2006, 14:52
Am ehesten erreichst du ein ähnliches Verhalten mit einem shared_ptr<fstream> als Werttyp in der Map

Ciao,
_

7.e.Q
18-11-2006, 09:58
Achso, okay, ja, das sind noch so ein paar Bildungskrater von mir, die ihr damit gestopft habt... danke.

Mit dem shared_ptr<fstream> kann ich also eine Map mit Streams anlegen? Wäre wichtig, da ich momentan noch FILE* in der Map hab, die sich aber nicht so schön über good() und so validieren lassen...

anda_skoa
18-11-2006, 14:46
Du kannst auch frstream* als Inhalte nehmen, das geht auch

Ciao,
_

7.e.Q
20-11-2006, 08:18
shared_ptr stammt (google's Meinung nach) aus der Boost Lib? Da kann ich leider nix mit anfangen, weil ich Boost nicht in die alte Compiler Umgebung integriert bekomme.

Den alten Compiler benutzen wir nur deshalb, weil wir noch keine Zeit hatten, die Sourcen an die neue Compiler Umgebung anzupassen. Das ist ein riesen Haufen Kot, der da angepasst werden muss. Die Krux an der Sache ist, daß wir eine Cygwin-Crosscompiler-Umgebung nutzen, um Linux(ELF) Binaries unter Windows zu erstellen. Und diese ist inzwischen so alt und abgespeckt, daß da auch nix anderes mehr mit läuft.

Wenn ich fstream* nutze, muss ich den Zeiger vor Operationen darauf aber wieder validieren, also sicherstellen, daß dieser gültig ist und nicht ins Nirwana zeigt, richtig?

Genau das wollte ich ja vermeiden. :-/

anda_skoa
20-11-2006, 16:23
Du kannst dir natürlich auch selber einen Shared Pointer implementieren.
Bei Single Threaded und nur für eine bestimmte Klasse ist das relativ einfach.

Praktisch einfaches Reference Counting

Ciao,
_

7.e.Q
22-11-2006, 06:49
Hast du auf die Schnelle Informationen dazu, wie man sowas genau macht? Hab mich damit noch nicht so recht auseinandergesetzt.

anda_skoa
22-11-2006, 21:54
Im Grunde recht einfaches Prinzip.

Du hast zwei Klassen. Eine mit einen Zähler, der in den Konstruktoren der anderen Klasse rauf gezählt wird und in den Destruktoren runter.
Wenn die letzte "Kopie" gelöscht wird, löscht sie den gemeinsamen Pointer.

In etwa so (nicht getestet)



class Shared
{
public:
Shared() : count(0), data(0) {}
~Shared() { delete data; }

int count;
fstream* data;
};

class SharedStream
{
public:
SharedStream() : m_shared(0) {}

SharedStream(fstream* stream)
{
m_shared = new Shared();
m_shared->count++;
m_shared->data = stream;
}

SharedStream(const SharedStream& other)
{
m_shared = other.m_shared;
if (m_shared != 0) m_shared->count++;
}

~SharedStream()
{
if (m_shared != 0)
{
m_shared->count--;
if (m_shared->count == 0) delete m_shared;
}
}

SharedStream& operator=(const SharedStream& other)
{
if (this == &other) return *this; // self assignment

if (m_shared != 0)
{
m_shared->count--;
if (m_shared->count == 0) delete m_shared;
}

m_shared = other.m_shared;
if (m_shared != 0) m_shared->count++;
}

private:
Shared* m_shared;
};


Ciao,
_