Article View: de.comp.lang.c++
Article #503Re: instantiation of template - incomplete type
From: Karl-Heinz Krause
Date: Sun, 01 Oct 1995 18:40
Date: Sun, 01 Oct 1995 18:40
122 lines
4427 bytes
4427 bytes
Am 28. Sep 1995 schrieb Olaf Pfohl (pfohl@ips.cs.tu-bs.de) in
Beantwortung einer Anfrage von Thorsten Gau:
>Thorsten Gau (gau_t@gauhh.hanse.de) wrote:
>: ich habe Probleme mit folgendem Code. Der VisualAge C++ compiliert ihn ohne
>: Probleme, doch gcc 2.6.3 mag sowas gar nicht. Hilft mir da vielleicht ein
>: Upgrade auf 2.7.0 oder kann ich da irgendwie drumrum programmieren?
>: template<class T> class L {
>: T data;
>: public:
>: L() {}
>: };
>: class A {
>: public:
>: A() {}
>: L<A> children();
>: };
>Nun ja, ich finde dieses Klassendesign an sich nicht so toll: du gibst als
>template-Argument die Klasse an, in der das Klassen-Member selbst enthalten
>ist...das ist ja rekursiv und eine Fehlermeldung "uber unvollst"andige Klasse
>eigentlich genau die richtige Meldung.
>Besser w"are es, eine Basisklasse einzuf"uhren, von der abgelitten wird, und
>welche auch als template-Argument dienen kann:
>template <class T> class L {
> private:
> T data;
> public:
> L() {}
>};
>class B {
> // ...
>};
>class A: public B {
> public:
> A() {}
> L<B> children();
>};
Die Kritik am Klassendesign ist vollkommen unberechtigt. Natürlich ist
das ganze rekursiv, aber Rekursivität ist beim Programmieren etwas
ganz normales. Un die Fehlermeldung über unvollständige Klassen ist
nicht angemessen.
Indirekt ist A ja sowas ähnliches wie
struct A {
A child();
};
und sowas ist in C++ durchaus erlaubt!
Das Einfügen der Zwischenklasse B ist ein typischer "Workaround" um
Compilermängel zu umgehen. Wenn´s funktioniert: gut. Aber wenn ein
Compiler es nötig macht, solche Umwege zu gehen, statt die Sache
direkt so zu formulieren, wie man es haben will, dann ist das immer
als Compilerfehler anzusehen und hat nichts mit schlechtem
Programmierstil zu tun. Im Gegenteil, eigentlich sind solche
Workarounds schlechter (aber leider notwendiger) Programmierstil.
Der Vorschlag mit der Zwischenklasse B funktioniert außerdem nicht
immer. Da "child" ja jetzt den Typ L<B> hat, muß jede Operation, die
man auf "child" anwenden will, bereits in B definiert sein. Was ist
aber wenn in solch einer Operation ebenfalls auf "child" zugegriffen
werden soll? In B gibt es ja kein "child". (Soweit die Kritik an der
Kritik.)
Der Hauptgrund des Problems ist übrigens, daß es bisher keine wirklich
saubere Definition von Templates in C++ gibt, insbesondere was den Ort
der Instanziierung angeht. Bisher gibt es nur Aussagen von Stroustrup,
wie es ungefähr funktionieren soll, und deshalb verhalten sich die
verschiedenen Compiler da alle etwas anders. Borland C++ 4.5 hat
jedenfalls dasselbe Problem.
Ich habe in "The Design and Evolution of C++" folgende Aussage
gefunden (15.10.2): "The original definition says ... that the point
of instantiation is just before the global declatation in which a
template is first used."
In unserem speziellen Fall taucht L<A> erstmals in der Definition von
A auf. Also erfolgt die Instanziierung unmittelbar vor der Definition
von A. Den vom Compiler erzeugten Code muß man sich dann etwa so
vorstellen:
class A;
// Hier erfolgt Instanziierung von L<A>.
// class L<A> {
// A data;
// ...
// };
class A {
// Hier wird A erst definiert.
};
Die Instanziierung erfolgt also, bevor A vollständig definiert ist. In
der Instanziierung wird jedoch A benutzt um eine Variable zu
definieren, und das geht nicht. Die Definition eines Zeigers oder
einer Referenz des Typs A wäre dagegen erlaubt.
Der einzige Workaround, der mir einfällt und der zumindes in Borland
C++ 4.5 funktioniert, ist
template<class T> class L {
T *pData;
public:
L(): pData(new T) {}
~L() { delete pData; }
};
Viele Grüße von Karl-Heinz
Technical Details
Message-ID:
<44mna3$np4@news00.btx.dtag.de>Path:
arc1-ca.pugleaf.net!news00.btx.dtag.de!not-for-mailReferences:
<DFErsG.6EK@gauhh.hanse.de> <DFMC85.JKM@ips.cs.tu-bs.de>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!news00.btx.dtag.de!not-for-mail From: 0913148778-0001@btx.dtag.de (Karl-Heinz Krause) Newsgroups: de.comp.lang.c++ Subject: Re: instantiation of template - incomplete type Date: 1 Oct 1995 18:40:03 GMT Organization: Telekom Online Internet Gateway Message-ID: <44mna3$np4@news00.btx.dtag.de> References: <DFErsG.6EK@gauhh.hanse.de> <DFMC85.JKM@ips.cs.tu-bs.de> Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-Sender: 0913148778-0001@btx.dtag.de (Karl-Heinz Krause) X-Newsreader: Forte Free Agent 1.0.82