Ich arbeite derzeit an einem Projekt und habe das folgende Problem.
Ich habe eine C ++ - Methode, mit der ich auf zwei verschiedene Arten arbeiten möchte:
void MyFunction()
{
foo();
bar();
foobar();
}
void MyFunctionWithABonus()
{
foo();
bar();
doBonusStuff();
foobar();
}
Und ich möchte meinen Code nicht duplizieren, da die eigentliche Funktion viel länger ist. Das Problem ist, dass ich unter keinen Umständen dem Programm Ausführungszeit hinzufügen darf, wenn MyFunction anstelle von MyFunctionWithABonus aufgerufen wird. Deshalb kann ich nicht einfach einen booleschen Parameter haben, den ich mit einem C ++ - Vergleich überprüfe.
Meine Idee wäre gewesen, C ++ - Vorlagen zu verwenden, um meinen Code virtuell zu duplizieren, aber ich kann mir keine Möglichkeit vorstellen, bei der ich keine zusätzliche Ausführungszeit habe und den Code nicht duplizieren muss.
Ich bin kein Experte für Vorlagen, daher fehlt mir möglicherweise etwas.
Hat jemand von euch eine Idee? Oder ist das in C ++ 11 einfach unmöglich?
Antworten:
Mit Vorlage und Lambda können Sie Folgendes tun:
oder Sie können einfach erstellen
prefix
undsuffix
funktionieren.quelle
So etwas wird gut funktionieren:
Nennen Sie es über:
Die "hässliche" Vorlage kann vermieden werden, indem den Funktionen einige nette Wrapper hinzugefügt werden:
Sie können einige nette Informationen auf dieser Technik finden dort . Das ist ein "altes" Papier, aber die Technik an sich bleibt völlig richtig.
Vorausgesetzt, Sie haben Zugriff auf einen netten C ++ 17-Compiler, können Sie die Technik sogar weiter vorantreiben, indem Sie den constexpr verwenden, wenn :
quelle
if constexpr (bonus) { doBonusStuff(); }
.doBonusStuff()
aus irgendeinem Grund im Nicht-Bonus-Fall nicht einmal kompiliert werden kann, wird dies einen großen Unterschied machen.In Anbetracht einiger Kommentare, die das OP zum Debuggen abgegeben hat, ist hier eine Version, die
doBonusStuff()
Debug-Builds fordert , aber keine Builds veröffentlicht (die definierenNDEBUG
):Sie können das
assert
Makro auch verwenden, wenn Sie eine Bedingung überprüfen möchten, und fehlschlagen, wenn sie falsch ist (jedoch nur für Debug-Builds; Release-Builds führen die Prüfung nicht durch).Seien Sie vorsichtig, wenn
doBonusStuff()
Nebenwirkungen auftreten, da diese Nebenwirkungen in Release-Builds nicht vorhanden sind und möglicherweise die im Code getroffenen Annahmen ungültig machen.quelle
#if defined(NDEBUG)
es wahrscheinlich einfacher ist , nur direkt zu verwenden.Hier ist eine geringfügige Abweichung von Jarod42s Antwort unter Verwendung verschiedener Vorlagen, sodass der Anrufer null oder eine Bonusfunktion bereitstellen kann:
Aufrufcode:
quelle
Eine andere Version, die nur Vorlagen und keine Umleitungsfunktionen verwendet, da Sie sagten, Sie wollten keinen Laufzeit-Overhead. Für mich erhöht dies nur die Kompilierungszeit:
Es gibt jetzt nur eine Version von
MyFunc()
mit dembool
Parameter als Vorlagenargument.quelle
bonus<false>()
Ruft die Standardversion derbonus
Vorlage auf (Zeilen 9 und 10 des Beispiels), sodass kein Funktionsaufruf erfolgt. Anders ausgedrückt:MyFunc()
Kompiliert in einen Codeblock (ohne Bedingungen) undMyFunc<true>()
in einen anderen Codeblock (ohne Bedingungen).Sie können Tag-Dispatching und einfache Funktionsüberladung verwenden:
Dies ist leicht zu lesen / zu verstehen, kann ohne Schweiß (und ohne Heizplatte) erweitert werden
if
Klauseln - durch Hinzufügen weiterer Tags) erweitert werden und hinterlässt natürlich keinen Laufzeit-Footprint.Die aufrufende Syntax ist zwar recht freundlich, kann aber natürlich in Vanille-Aufrufe eingepackt werden:
Das Versenden von Tags ist eine weit verbreitete generische Programmiertechnik. Hier ist ein schöner Beitrag über die Grundlagen.
quelle