 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Martin Komischke Guest
|
Posted: Wed Mar 28, 2007 1:00 pm Post subject: Funktionstemplate mit abstrakter Basisklasse |
|
|
Hallo,
habe das Problem, dass ich in einem Funktionstemplate ein Argument vom
Typ einer abstrakten Basisklasse A angeben will.
Im Funktionsrumpf soll danach ein Objekt vom Typ A_konkret (von A
abgeleitet) instanziiert werden.
Wird ein Argument vom Typ B (B ist abstrakt) angegeben, soll im Rumpf
ein Objekt vom Typ B_konkret instanziert werden.
Kann mir jemand sagen wie ich das lösen kann? Was bietet sich für die
Lösung dieses Problems eher an? Was sind Stolperfallen hier?
Natürlich ist meine Funktion länger, deshalb ist es hier schon
erwägenswert "Code zu sparen".
template<typename T>
void DoSomeThing(T a)
{
T_konkret obj; // T_konkret ist von T abgeleitet
obj.DoIt();
}
Gruß
Martin |
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Sat Mar 31, 2007 2:18 am Post subject: Re: Funktionstemplate mit abstrakter Basisklasse |
|
|
Martin Komischke <makom.news (AT) arcor (DOT) de> writes:
| Quote: | habe das Problem, dass ich in einem Funktionstemplate ein Argument vom
Typ einer abstrakten Basisklasse A angeben will.
Im Funktionsrumpf soll danach ein Objekt vom Typ A_konkret (von A
abgeleitet) instanziiert werden.
Wird ein Argument vom Typ B (B ist abstrakt) angegeben, soll im Rumpf
ein Objekt vom Typ B_konkret instanziert werden.
Kann mir jemand sagen wie ich das lösen kann? Was bietet sich für die
Lösung dieses Problems eher an?
|
Eher als was?
| Quote: | Was sind Stolperfallen hier?
|
Du erzeugst eine Abhängigkeit von einer abstrakten Klasse auf eine
konkrete, selbst von ihr abhängige. Die beiden Klassen sind dann sehr
eng aneinander gekoppelt. Ob das eine "Stolperfalle" ist, kann ich
Dir nicht sagen.
| Quote: | Natürlich ist meine Funktion länger, deshalb ist es hier schon
erwägenswert "Code zu sparen".
template<typename T
void DoSomeThing(T a)
|
Ich dachte, T sei abstrakt?
| Quote: | {
T_konkret obj; // T_konkret ist von T abgeleitet
obj.DoIt();
}
|
Aber solange Du a gar nicht brauchst, übergibst Du es am besten gar
nicht.
Traits bieten eine Lösung:
template <typename T>
struct traits;
template <>
struct traits<A>
{
typedef A_konkret konkreter_typ;
};
template <>
struct traits<B>
{
typedef B_konkret konkreter_typ;
};
template <typename T>
void DoSomeThing()
{
typename traits<T>::konketer_typ obj;
obj.DoIt();
}
Wenn's "intrusive" sein darf, kann jede abstrakte Klasse "ihre"
konkrete Klasse auch selbst deklarieren. Dann wird DoSomeThing()
einfach zu
template <typename T>
void DoSomeThing()
{
typename T::konketer_typ obj;
obj.DoIt();
}
und Du brauchst keine Traits. |
|
| Back to top |
|
 |
Florian Schröder Guest
|
Posted: Sat Mar 31, 2007 3:13 am Post subject: Re: Funktionstemplate mit abstrakter Basisklasse |
|
|
In article <460a20ff$0$23138$9b4e6d93 (AT) newsspool1 (DOT) arcor-online.net>,
Martin Komischke <makom.news (AT) arcor (DOT) de> wrote:
| Quote: | habe das Problem, dass ich in einem Funktionstemplate ein Argument vom
Typ einer abstrakten Basisklasse A angeben will.
Im Funktionsrumpf soll danach ein Objekt vom Typ A_konkret (von A
abgeleitet) instanziiert werden.
Wird ein Argument vom Typ B (B ist abstrakt) angegeben, soll im Rumpf
ein Objekt vom Typ B_konkret instanziert werden.
Kann mir jemand sagen wie ich das lösen kann? Was bietet sich für die
Lösung dieses Problems eher an? Was sind Stolperfallen hier?
Natürlich ist meine Funktion länger, deshalb ist es hier schon
erwägenswert "Code zu sparen".
Hallo Martin, |
ich bin mir nicht ganz sicher, wo dein Problem ist, aber sieh dir mal
das Factory Method Pattern an, vielleicht hilft dir das Entwurfsmuster.
http://en.wikipedia.org/wiki/Factory_method_pattern.
In Kombination mit spezialisierten Templates. Diese machen aber nur Sinn
wenn die Spezialisierung nur für eine geringe Zahl nötig ist.
Tendenziell würde ich an dieser Stelle aber ehr versuchen die Templates
ganz abzusetzen und durch eine geschickt gewählte Abstrakte Oberklasse
zu ersetzen. A und B werden ja wohl schon was gemeinsam haben.
Entsprechend brauchst du dann auch zwischen A_konkret und B_konkret
nicht zu unterscheiden. Du Definierst in der Oberklasse deine
Schnittstelle, die in A_konkret und B_konkret dann Implementiert ist und
die Factory erzeugt dir dann das gewünschte Objekt.
Gruß,
Florian
--
--
Our software does not coddle the weak. Bugs are good for building character in the user. |
|
| Back to top |
|
 |
Torsten Robitzki Guest
|
Posted: Sat Mar 31, 2007 11:46 am Post subject: Re: Funktionstemplate mit abstrakter Basisklasse |
|
|
Hallo Martin,
Martin Komischke wrote:
| Quote: | Wird ein Argument vom Typ B (B ist abstrakt) angegeben, soll im Rumpf
ein Objekt vom Typ B_konkret instanziert werden.
template<typename T
void DoSomeThing(T a)
{
T_konkret obj; // T_konkret ist von T abgeleitet
obj.DoIt();
}
|
Irgend wie musst Du definieren, wie die Funktion von T auf T_konkret
kommen soll. Ein Möglichkeit wäre, so eine Art map zu verwenden:
template <class T>
struct map;
template <>
struct map<A>{
typedef A_konkret konkret;
};
template <>
struct map<B>{
typedef B_konkret konkret;
};
template<typename T>
void DoSomeThing(T a)
{
typename map<T>::konkret obj;
obj.DoIt();
}
Sieht mir aber nicht wirklich nützlich aus. Was möchtest Du den erreichen?
mfg Torsten |
|
| Back to top |
|
 |
Stefan Reuther Guest
|
Posted: Sat Mar 31, 2007 3:47 pm Post subject: Re: Funktionstemplate mit abstrakter Basisklasse |
|
|
Martin Komischke wrote:
| Quote: | Kann mir jemand sagen wie ich das lösen kann? Was bietet sich für die
Lösung dieses Problems eher an? Was sind Stolperfallen hier?
Natürlich ist meine Funktion länger, deshalb ist es hier schon
erwägenswert "Code zu sparen".
template<typename T
void DoSomeThing(T a)
{
T_konkret obj; // T_konkret ist von T abgeleitet
obj.DoIt();
}
|
Du brauchst eine Zuordnung von 'T' zu 'T_konkret'. Die einfachste
Möglichkeit wäre, in jedes 'T' ein passendes Member-Typedef zu setzen:
class FredKonkret;
class Fred {
public:
typedef FredKonkret konkret_t;
// ...
}
template<typename T>
void DoSomeThing(T a)
{
typename T::konkret_t obj;
obj.DoIt();
}
Wenn du diese Zuordnung nicht in den Basisklassen haben willst, bietet
sich eine traits-Klasse an.
template<typename T> class foo_traits;
template<>
struct foo_traits<Fred> {
typedef FredKonkret konkret_t;
}
template<typename T>
void DoSomeThing(T a)
{
typename foo_traits<T>::konkret_t obj;
obj.DoIt();
}
Stefan |
|
| Back to top |
|
 |
Martin Komischke Guest
|
Posted: Thu Apr 19, 2007 2:13 am Post subject: Re: Funktionstemplate mit abstrakter Basisklasse |
|
|
Torsten Robitzki schrieb:
| Quote: | Sieht mir aber nicht wirklich nützlich aus. Was möchtest Du den erreichen?
|
Danke für Deine Antwort. Als Argument-Typ kann ich nur die Abstrakte
Basisklasse (T) angeben (vorgegeben). Im Funktionsrumpf soll aber die
von T erbende Klasse (T_konkret) instanziiert werden.
Das mit der Map hört sich interessant an. Wenn ich das richtig
verstanden habe, würde ich die Assoziation zwischen abstrakter und
konkreter Klasse dort reinpacken und könnte dies innerhalb der Funktion
aufrufen.
Gruß
Martin |
|
| Back to top |
|
 |
Martin Komischke Guest
|
Posted: Thu Apr 19, 2007 2:13 am Post subject: Re: Funktionstemplate mit abstrakter Basisklasse |
|
|
Hallo Stefan,
Beide Möglichkeiten kommen für mich in Betracht, wobei ich die Umsetzung
mit der Traits-Klasse besonders interessant finde.
Vielen Danke
Martin |
|
| Back to top |
|
 |
Martin Komischke Guest
|
Posted: Thu Apr 19, 2007 2:13 am Post subject: Re: Funktionstemplate mit abstrakter Basisklasse |
|
|
Thomas Maeder schrieb:
| Quote: | Martin Komischke <makom.news (AT) arcor (DOT) de> writes:
[...]
Kann mir jemand sagen wie ich das lösen kann? Was bietet sich für die
Lösung dieses Problems eher an?
Eher als was?
|
Momentan habe ich das Funktionstemplate folgendermaßen aufgebaut, in dem
ich selber sicherstelle das die Abhängigkeit von T zu T_konkret
gewährleistet ist. Is nicht schön aber funktioniert erstmal.
template <typename T1, T2>
void DoSomething(const T1& arg)
{
T2 obj;
obj.DoIt();
}
Aufruf erfolgt mit:
DoSomething<T_abstrakt, T_konkret>(argument);
| Quote: | Was sind Stolperfallen hier?
Du erzeugst eine Abhängigkeit von einer abstrakten Klasse auf eine
konkrete, selbst von ihr abhängige. Die beiden Klassen sind dann sehr
eng aneinander gekoppelt. Ob das eine "Stolperfalle" ist, kann ich
Dir nicht sagen.
|
OK, das soll so sein ;-)
| Quote: | Natürlich ist meine Funktion länger, deshalb ist es hier schon
erwägenswert "Code zu sparen".
template<typename T
void DoSomeThing(T a)
Ich dachte, T sei abstrakt?
Ja, isses doch auch.
{
T_konkret obj; // T_konkret ist von T abgeleitet
obj.DoIt();
}
Aber solange Du a gar nicht brauchst, übergibst Du es am besten gar
nicht.
|
OK, das Beispiel hätte ich vielleicht auch so schreiben können:
template<typename T>
T_konkret DoSomeThing(T a)
{
T_konkret obj; // T_konkret ist von T abgeleitet
obj.Copy("Foo");
obj.Append(a);
return obj;
}
| Quote: |
Traits bieten eine Lösung:
template <typename T
struct traits;
template
struct traits<A
{
typedef A_konkret konkreter_typ;
};
template
struct traits<B
{
typedef B_konkret konkreter_typ;
};
template <typename T
void DoSomeThing()
{
typename traits<T>::konketer_typ obj;
obj.DoIt();
}
Wenn's "intrusive" sein darf, kann jede abstrakte Klasse "ihre"
konkrete Klasse auch selbst deklarieren. Dann wird DoSomeThing()
einfach zu
template <typename T
void DoSomeThing()
{
typename T::konketer_typ obj;
obj.DoIt();
}
und Du brauchst keine Traits.
|
Super! Danke.
Gruß
Martin |
|
| Back to top |
|
 |
Martin Komischke Guest
|
Posted: Thu Apr 19, 2007 2:13 am Post subject: Re: Funktionstemplate mit abstrakter Basisklasse |
|
|
Florian Schröder schrieb:
[...]
Ist mir bestens bekannt.
| Quote: | In Kombination mit spezialisierten Templates. Diese machen aber nur Sinn
wenn die Spezialisierung nur für eine geringe Zahl nötig ist.
|
In der Verbindung noch nicht gesehen, hast Du ein kurzes Beispiel?
| Quote: | Tendenziell würde ich an dieser Stelle aber ehr versuchen die Templates
ganz abzusetzen und durch eine geschickt gewählte Abstrakte Oberklasse
zu ersetzen. A und B werden ja wohl schon was gemeinsam haben.
Entsprechend brauchst du dann auch zwischen A_konkret und B_konkret
nicht zu unterscheiden. Du Definierst in der Oberklasse deine
Schnittstelle, die in A_konkret und B_konkret dann Implementiert ist und
die Factory erzeugt dir dann das gewünschte Objekt.
|
Hmm. Geht leider nicht ganz so einfach, als Parameter bin ich auf die
abstrakte Basisklasse angewiesen. A und B haben insofern was gemeinsam
(jetzt wirds nicht mehr ISO-C++ ), als dass beides Descriptoren sind
(einer wide der andere narrow char).
Ich kann mir momentan aber nicht so richtig vorstellen wie mir das
Factory-Method-Pattern da eine konkrete Klasse draus instanziieren soll.
Muss ich mal drüber schlafen
Gruß
Martin |
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Fri Apr 20, 2007 2:56 am Post subject: Re: Funktionstemplate mit abstrakter Basisklasse |
|
|
Martin Komischke <makom.news (AT) arcor (DOT) de> writes:
| Quote: | template<typename T
void DoSomeThing(T a)
Ich dachte, T sei abstrakt?
Ja, isses doch auch.
|
Von einer abstrakten Klasse kannst Du keine Objekte by value übergeben. |
|
| Back to top |
|
 |
Martin Komischke Guest
|
Posted: Mon Apr 23, 2007 5:33 pm Post subject: Re: Funktionstemplate mit abstrakter Basisklasse |
|
|
Thomas Maeder schrieb:
| Quote: | Martin Komischke <makom.news (AT) arcor (DOT) de> writes:
template<typename T
void DoSomeThing(T a)
Ich dachte, T sei abstrakt?
Ja, isses doch auch.
Von einer abstrakten Klasse kannst Du keine Objekte by value übergeben.
|
Hast recht, das würde nicht funktionieren. Ist eben das Problem, bei
nicht kompilierten Beispielen vergißt man schnell mal ein "&". |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|