die einen vector mit N Elementen erstellt. Ob der vector nun mit
derived_a oder derived_b Objekten gefüllt werden soll, steht vor dem
Compilieren fest. Nur möchte ich nicht für jede abgeleitete Klasse eine
eigene Funktion schreiben (momentan wären es nur 4, später jedoch mehr),
die im Grunde alle genau das Gleiche tun.
Den Weg über Templates soll mir recht sein, nur weiss ich nicht, wie ich
die verschiedene Anzahl Argumente der Create Funktionen handhaben soll.
Irgendwie muss ich diese ja auch der Funktion Generate übergeben.
Zusätzlich sind nicht immer alle Argumente vom gleichen Typ. Falls nötig
ist es möglich, move Konstruktoren und move operator= Funktionen zu
definieren. Die habe ich weggelassen, da bisher nicht benötigt.
Kennt jemand eine praktikable Lösung dafür, oder ist das, was ich da
machen will, absoluter Schwachsinn?
vec.emplace_back(std::make_unique<T>(args...));// Auch wegen Effizienz
10
returnvec;
11
}
Wenn du nur effizient kopierbare Datentypen wie "int" übergibst, macht
es Sinn das "Args&" duch "Args" zu ersetzen. Universelle Referenzen kann
man hier leider nicht wirklich einsetzen. Die Werte werden
logischerweise in jedem Fall kopiert, wenn du zB einen std::vector als
Argument übergibst, wird es N Kopien geben, eine rvalue/move
construction Optimierung geht hier nicht.
be s. schrieb:> Den Weg über Templates soll mir recht sein, nur weiss ich nicht, wie ich> die verschiedene Anzahl Argumente der Create Funktionen handhaben soll.
Da du ja eh schon C++11 einsetzt, lässt sich das relativ leicht mittels
Variadic Templates lösen:
1
template <typename TYPE, typename... ARGS>
2
std::vector<base::ptr> Generate(std::size_t N, ARGS... args)
3
{
4
std::vector<base::ptr> vec;
5
6
while (N-- > 0)
7
vec.push_back(TYPE::Create(args...));
8
9
return v;
10
}
Alternativ kann man auch mit Initializer Lists arbeiten, dann musst du
aber noch deine Create() entsprechend überladen.
be s. schrieb:> oder ist das, was ich da machen will, absoluter Schwachsinn?
Ob dieser Ansatz insgesamt sinnvoll ist oder ob es vielleicht nicht doch
eine elegantere Lösung gibt, hängt halt vom konkreten Anwendungsfall ab.
Kann man aber durchaus so machen.
Vielen Dank für die Antworten.
Dr. Sommer schrieb:> Du brauchst variadische Templates:
Die hab ich noch nie verwendet, da muss ich mich erst ein wenig
einlesen.
Dr. Sommer schrieb:> Wenn du nur effizient kopierbare Datentypen wie "int" übergibst, macht> es Sinn das "Args&" duch "Args" zu ersetzen.
Bisher werden nur Integer und doubles übergeben, für grössere Typen sehe
ich momentan keinen Bedarf.
Variadic Templates schrieb:> Alternativ kann man auch mit Initializer Lists arbeiten, dann musst du> aber noch deine Create() entsprechend überladen.
Habe ich mir auch schon überlegt, dies funktioniert aber nur, solange
alle Argumente vom gleichen Typ sind.
Variadic Templates schrieb:> Ob dieser Ansatz insgesamt sinnvoll ist oder ob es vielleicht nicht doch> eine elegantere Lösung gibt, hängt halt vom konkreten Anwendungsfall ab.> Kann man aber durchaus so machen.
Hintergrund: Gegeben ist ein zweidimensionales Feld, in das Objekte
"gezeichnet" werden sollen (Linie, Kreis etc.), natürlich alles
parametrisierbar (Grösse usw.). Zusätzlich müssen die Eigenschaften der
Objekte definiert werden (Argumente für Create-Funktionen). Die Objekte
sind zunächst alle identisch, entwickeln später jedoch je nach Standort
und Nachbarn ein "Eigenleben" und sind damit einzigartig, deswegen will
ich diese nicht kopieren können.
Meine Generate-Funktion wird so nirgends in meinen Code verwendet
werden, ist aber das einfachste Minimalbeispiel, das mir in den Sinn
gekommen ist, ohne viel drumherum erklären zu müssen. Wenns vom Prinzip
her mit meiner Generate-Funktion funktioniert, schaffe ich das auch, das
Prinzip auch meine Funktionen zu übertragen.
Ich werde mich mal einlesen und es mit den validarischen Templates
versuchen, aber jetzt gibts erstmal Abendessen.
Eine andere Möglichkeit wäre es, der Generate etwas
factory-method-ähnliches mitzugeben. Ich bin aber nicht davon überzeugt,
dass man damit außer Codelänge und Komplexität irgendetwas gewinnt.
Tom schrieb:> Eine andere Möglichkeit wäre es, der Generate etwas> factory-method-ähnliches mitzugeben.
Und diese Generate Version macht praktisch das Gleiche wie
std::generate... ;-)
Dr. Sommer schrieb:> Und diese Generate Version macht praktisch das Gleiche wie> std::generate... ;-)
Dass die Generate() ziemlich überflüssig ist, ist mir auch aufgefallen,
aber als Minimalbeispiel des OP für "Funktion will Objekte erzeugen,
weiß aber selbst nicht, welche oder wie das im Einzelnen geht." ist sie
sehr passend.
Daniel A. schrieb:> validarischen = überprüfend, du meinst variadic (variadisch) = variable> argumentnummer.
Danke für die Korrektur. Ich hab mir ehrlich gesagt das Wort nie richtig
angeschaut...