• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

g++ templates

kohlhz

Member
Verwende noch SuSE 11.2.
Ich habe eine (umfangreiche) Nicht-Template-Klasse togo, in der Objekte zweier Klassen, much und Town, verwendet werden,
much ist Template-Klasse, die je nach Instantiierung z.B. auf Town oder einfachen Datentypen aufbaut.
togo braucht Konstruktoren, deren Parameter Town und verschiedenen Instantiierungen von much sein können.

Also insgesamt eigentlich noch eine recht simple Konstruktion.

g++ habe ich dazu gebracht, ein Konstruktor-Template zu fressen - das ist das,was ich brauche.
Leider erzeugt dann der Compiler - bis zum Linken ohne Fehlermeldung oder Warnung - nicht alle benötigten Funktionen,
wenn ein Template-Parameter von much selbst wieder Klasse (Town) ist.
Holt man das 'von Hand' nach, wird u.a. Mehrfachdefinition angemosert, auch kein Linken möglich.

Als (grauslichen) Work-around habe ich mir das folgende einfallen lassen, bei dem g++ aber auch streikt,
Fehlermeldung:
go.cc: In constructor ‘togo::togo(const much<Town, Town>&, const Town&)’:
go.cc:532: error: no matching function for call to ‘mocktogo(const much<Town, Town>&, const Town&)’

Ob mit oder ohne '&', mit oder ohne 'const' erscheint völlig egal, aber eventuelle weitere Parameter zu mocktogo
gibt g++ bei der Fehlermeldung mit zusätzlichem '&' an, also statt erwartetem long .. long& (vermutlich unerheblich).

Egal, woran ich drehe - das Ergebnis bleibt in etwa gleich.
Fällt jemandem etwas auf, was ich übersehe?

Weiß jemand, wie Konstruktoren mit Parameter u.a. aus much (template-Klasse) erfolgreich - also so, dass g++ damit klarkommt - zu togo hinzugefügt werden können,
ohne togo zur Templateklasse zu machen?
Also so, dass g++ nicht nur (bei -Wall) ohne Fehler und Warnung übersetzt, sondern das Ganze auch linkbar ist?

typedef much<real_word,word> muchWord;
//typedef much<Town, Town> muchTown; // egal, ob dies ...
#define muchTown much<Town, Town> // .. oder dies verwendet - es geht nicht
//typedef much<real_word,word> muchWord; // aber mit einfachen Typen geht es dem Anschein nach ... nutzt nur nichts ...

class togo {
public:
togo (bool C_is=false);
togo (const char* R_text);
togo (togo const& toCopy);

togo (muchWord const& f, double x);
togo (much<long,long> const& f, long x);
togo (muchTown const& f, Town const& x);
..... // ggf. weitere Konstruktoren, alle wären aus einem Funktionstemplate ableitbar
};

template<class m_real_word, class m_word>
togo mocktogo(much<m_real_word,m_word> const& f, m_word const& x) {
m_word y = x;
unsigned i;
togo erg(reserves);
....
return erg;
};

togo::togo(muchWord const& f, double x) { // wird akzeptiert
*this = mocktogo<real_word,word>(f, x);
};

togo::togo(much<long,long> const& f, long x) { // habe ich nicht explizit aktiviert
*this = mocktogo<long,long>(f, x);
};

togo::togo (muchTown const& f, Town const& x) { /*much<Town,Town>*/
*this = mocktogo<muchTown,Town>(f, x); // or .. <much<Town, Town>, Town>
};
 
OP
K

kohlhz

Member
Habe jetzt eine Lösung gefunden, sie ist aber sehr unbefriedigend.
Bin deshalb nach wie vor an hilfreichen Antworten interessiert.

Anscheinend hat gnu C++ bei all meinen besseren Ansätzen bei der Aktivierung Referenzparameter in Wertparameter und umgekehrt verwandelt ...
Mal schauen, ob das in der SuSE 11.3 auch noch so ist (kann wegen der Zusatzbibliotheken ein Weilchen dauern).
Wenn ja, und wenn ich Zeit dafür finde, werde ich das weiter prüfen, ggf. eine Fehlermeldung erstellen.

Der einzige Vorteil ist, daß der neue Workaround*) Übersetzung, Linken und sogar Starten mit der früheren Leistung erlaubt.
Ich bin zuversichtlich, dass nach Erstellen von ein paar noch fehlenden Teilen das erweiterte Konstrukt funktioniert.

*) ansonsten sinnloses Hilfs-struct, das von einer Template-Funktion gefüllt wird, und ein (seltsam erscheinender Hilfs-)Konstruktor für diese.
Die Gegenprobe ergab: diese Teile lassen sich nicht in einen Konstruktor integrieren.
Hat schreckliche Folgen für den Programmcode.

Fazit: C++, vor 15 Jahren schlicht unbrauchbar, ist noch immer schlecht, aber verwendbar, bei allerdings hohem Programmier- und Debugaufwand.
Standard-Templates: unumgänglich, aber mit Vorsicht zu gebrauchen; wegen der horriblen Fehlerdiagnostik sollten Anfänger die Finger davon lassen.
Eigene Templates: einfache möglich, komplexere nur für Masochisten zu empfehlen.
Wer immer C++ vermeiden kann, sollte dies tun ... es gibt auch andere C-nahe Sprachen.
 
OP
K

kohlhz

Member
Gibt es irgendeine Möglichkeit, (z.B. alle) Mitglieder einer Template-Klasse zu 'friends' zu machen?
Gibt es gemeinsame (oder teilweise gemeinsame) static-Member von Template-Klassen?

Habe jetzt nochmal 2 Tage "Syntaxfehlersuche" im Zusammenhang mit C++-Templates hinter mir.
Na gut, es waren vereinzelt auch eigene Fehler dabei.
Der Umbau größerer ausgetesteter Programmteile in Templates mag noch so trivial aussehen -
selbst hundertfaches Kopieren und individuelles Anpassen der Typen kann - inklusive Maintenance! - weit weniger
Arbeit machen.

Typisch sind Situationen wie diese:
Einige Seiten Syntaxfehler wegen Konstruktionen wie dieser mit Vector coeff :
if (coeff != 0) {
if (abs(coeff)==1) stream << ((coeff >= 0)?a:b) << variable << trennSymbol << step;
else stream << ((coeff >= 0)?a:b) << abs(coeff) << variable << trennSymbol << step;
Funktionsfähigkeit nach Umsetzung in:
help = coeff;
if (help != 0) {
if ((abshelp = abs(help))==1) stream << ((help >= 0)?a:b) << variable << trennSymbol << step;
else stream << ((help >= 0)?a:b) << abshelp << variable << trennSymbol << step;
};

"Grund": in Templates kann bei g++ der Zugriff auf Vektorkomponenten - coeff und coeff.at(i) - zu Schwierigkeiten führen, obwohl sie
vom identischen Typ wie help sind ... (casting hilft deshalb nicht).
Ohne die 'offensichtlich unnötigen' Hilfsvariablen help und abshelp ging gar nichts.
Die I/O-Operatoren << und >> dürften inzwischen als Templates realisiert sein, jedenfalls kann ihre Verwendbarkeit in Templates
vergleichbare Probleme machen.

Manchmal hilft explizites Casting, manchmal 'unnötige' Angabe von Template-Parametern, manchmal typedef -
der C++-Programmierer darf nicht für Maintenierer lesbar schreiben, nein, er muß dem Compiler helfen.

Mein dringender Rat: Finger weit weg von eigenen nichttrivialen C++-Templates!!
Wenn möglich, eine Programmiersprache verwenden statt des entglittenen 'Makroassemblers' C++.

Werden Methoden der STL im Zusammenhang mit Templates verwendet, kann dies unterschiedlichen seltsamsten Folgen führen -
teils schwer zu finden, teils noch schwerer zu beheben.
 
OP
K

kohlhz

Member
D
Geier0815 schrieb:
http://www.c-plusplus.de/forum/ kennst Du? Ich glaube das Du dort eher die Cracks findest die dir bei deinen Problemen helfen könnten bzw dir evtl andere Wege aufzeigen könnten.

Danke! - Nein, kannte ich leider noch nicht.
(aber die Warnung, C++ - insbesondere C++-Templates! - keinesfalls nichttrivial zu nutzen, sollte beherzigt werden, insbesondere von denen, die ernsthaft OO programmieren wollen!)
 
Oben