Fast gleicher Funktionskörper: wie zusammenfassend?
-
Hallo,
ich würde gern zwei Funktionen implementieren, die bis auf wenige Abweichungen gleich sind.
Mal ein Beispiel:
void myFunction(int myInt) { vector<int> values(3); // Variante a würde vector<int> values(2); reichen // gleiches Zeug ... // ... for (i = 0; i < maxI; i++) { for (j = 0; j < maxJ; j++) { values[0] = myInt + j; values[1] = -myInt + i; // nur für variante b: values[2] = 0; // und weiter maxValue = ... } } }Die Funktionen unterscheiden sich im Endeffekt nur durch ein weiteres Wert im values Vektor. Während ich bei der Initialisierung noch das mittels eines Parameters bzw einer if abfrage mir vorstellen kann, finde ich ein if im inneren der Schleife eher unelegant und wenig performant, oder?
Gibt es bessere Vorschläge, sollte ich die Funktionen lieber duplizieren?
Danke im Voraus.
Mat.
-
Mit templates gibt es verschiedenste Möglichkeiten.
Eine wäre den Code der unterschiedlich sein kann in eine Klasse auszulagern und diese dann zu verwenden:
struct WithTwoValues { WithTwoValues() : values(2) {} void DoIt(int myInt, int i, int j) { values[0] = myInt + j; values[1] = -myInt + i; } std::vector<int> values; }; struct WithThreeValues { WithThreeValues() : values(3) {} void DoIt(int myInt, int i, int j) { values[0] = myInt + j; values[1] = -myInt + i; values[2] = 0; } std::vector<int> values; }; template <class Blubb> void myFunction(int myInt) { Blubb blubb; // gleiches Zeug ... // ... for (i = 0; i < maxI; i++) { for (j = 0; j < maxJ; j++) { blubb.DoIt(myInt, i, j); // und weiter maxValue = ... } } } void foo() { myFunction<WithTwoValues>(123); myFunction<WithThreeValues>(123); }Allerdings kann ich jetzt nicht abschätzen ob das in genau der Form für dein Problem eine gute/wartbare/elegante Lösung wäre, da du ja nicht verrätst worum es geht.
-
entweder so, wie hustbaer schreibt oder so:
void myFunction(int myInt, size_t length) { vector<int> values (length); /* ... */ for (i = 0; i < maxI; i++) { for (j = 0; j < maxJ; j++) { values[0] = myInt + j; values[1] = -myInt + i; if (length == ...) values[2] = 0; // und weiter maxValue = ... } } }oder du machst es doch mit templates aber vll eher so:
template <size_t length> void myFunction(int myInt) { vector<int> values (length); /* ... */ for (i = 0; i < maxI; i++) { for (j = 0; j < maxJ; j++) { values[0] = myInt + j; values[1] = -myInt + i; values[2] = 0; maxValue = ... } } } template < > void myFunction <2> (int myInt) { vector<int> values (2); /* ... */ for (i = 0; i < maxI; i++) { for (j = 0; j < maxJ; j++) { values[0] = myInt + j; values[1] = -myInt + i; maxValue = ... } } }gibt halt viele möglichkeiten...
vll beschreibst du einfach mal, wieso du es genau brauchst und was du machen willst etc... ?
dann kann man das vll besser sagen, was am besten wäre und was nicht so gut wäre oder wie man es vll doch ganz anders machen sollte ^^bb
-
Ich habe halt eine Funktion, die sich an wenigen Stellen unterscheidet.
Natürlich könnte man jedesmal entsprechend eine if Abfrage machen, aber wie schon gesagt, im inneren einer Schleife (mehrfach verschachtelt), kommt mir dies nicht effizient vor. Nur so ein Gefühl.Somit wollte ich Möglichkeiten, wie man es anders bzw besser machen kann oder ob das mit dem if legitim und ein guter Stil ist.
Das mit dem Templates sieht in der Tat gut aus, werde ich mir mal anschauen...
-
Matrim schrieb:
Natürlich könnte man jedesmal entsprechend eine if Abfrage machen, aber wie schon gesagt, im inneren einer Schleife (mehrfach verschachtelt), kommt mir dies nicht effizient vor. Nur so ein Gefühl.
Arbeitest du derart zeitkritisch, dass es darauf ankommt? Eine If-Abfrage braucht vielleicht einige Nanosekunden...
-
Wird wie in diesem Beispiel der 3. Wert immer auf einen Wert gesetzt, der sich in der Schleife nicht ändert ?
Dafür gibt es natürlich eine noch einfachere Lösung:
void myFunction(int myInt) { vector<int> values(3); // Variante a würde vector<int> values(2); reichen if(variante b) { values[2] = 0.0; } // gleiches Zeug ... // ... for (i = 0; i < maxI; i++) { for (j = 0; j < maxJ; j++) { values[0] = myInt + j; values[1] = -myInt + i; // und weiter maxValue = ... } } }Wird der Wert allerdings in der Schleife geändert, so ist eine der obrigen Lösungen notwendig.
-
@Matrim: da das "if" in der Schleife immer gleich ausgeht (für alle Durchläufe false oder alle true) wird das von der branch-prediction perfekt abgefangen und kostet dadurch sehr wenig. regelmässige patterns (1 0 1 0 1 0 ...) sind auch meist kein problem wenn sie kurz genug sind. "ifs" die unvorhersehbar wechseln sind dagegen deutlich teurer.
alles in allem gilt aber hier auch: premature optimization is the root of all evil in programming.