/*
Vorgeschichte
Eine Klasse enthält eine Datenstruktur, über die in verschiedenen
Methoden auf ähnliche Weise in bestimmten Mustern iteriert werden muss.
Da diese Iteration relativ kompliziert ist und definitiv nicht per
Copy+Paste in die einzelnen Methoden gehört, wurde sie in eine
Template-Methode ausgelagert, die mit der Operation als Parameter
aufgerufen wird (In diesem Fall Hipster-Lambdas, Functoren gingen auch,
std::function hat Overhead, der hier wahrscheinlich stören würde).
Das Minimalbeispiel zeigt das Problem. In der echten Anwendung ist
natürlich alles komplizierter und das beschriebene Pattern war die
lesbarste und sauberste Lösung, die performant bleibt.
Eine const-Methode (1) kann natürlich keine nicht-const-Methode (3)
aufrufen und umgekehrt (2) (4), weshalb die Template-Methode in beiden
Varianten nötig scheint (const overloading)
Es wäre schöner, wenn -- naiv ausgedrückt -- irgendwie automagisch
anhand dessen, was der zweite Parameter tut, entschieden würde, ob die
Template-Methode const ist oder nicht.
Frage
Gibt es eine Möglichkeit, die beiden Kopien von for_every_nth, die sich
nur durch das const unterscheiden, irgendwie wie beschrieben
zusammenzufassen? Es sollte weder langsamer werden
noch viel Code erfordern (Selbst implementierte Spezial-Iteratoren sind
damit ausgeschlossen). Boost auf Expertenniveau möchte ich auch
vermeiden, dann behalte ich lieber die aktuelle Copy&Paste-Lösung.
*/
//
Mikro 7. schrieb:> Die non-const Methode ruft die const Methode auf, mit entsprechenden> const casts.
Ist bei ihm aber leicht anders, da er keinen Rückgabewert hat sondern
mit der Lambda Funktion Zeug erledigen will. So könnte man es machen,
obwohl ich das nicht wirklich schön finde:
Sebastian V. schrieb:> Ist bei ihm aber leicht anders...
Yo. Was ist denn die Signature der zweiten Lambda Funktion (set_rising)?
Bei der ersten ist es klar. Da paßt:
Mikro 7. schrieb:> ...hätte nicht gedacht dass [&i] die Signatur ändert.
Es ist nicht die capture expression, sondern die Parameter Liste. Die
eine Funktion nimmt (int& x) und die andere (const int& x). Und die
erste Funktion kann die nicht const qualifizierte Version von
for_every_nth () halt nicht aufrufen.
Wenn die Funktion so übersichtlich, wie im Beispiel ist, würde ich sie
zwei mal ausschreiben, ansonsten würde ich (wie von Dir vorgeschlagen)
mit const_cast auf die non-const Version verweisen:
Torsten R. schrieb:> Wenn die Funktion so übersichtlich, wie im Beispiel ist, würde ich sie> zwei mal ausschreiben, ansonsten würde ich (wie von Dir vorgeschlagen)> mit const_cast auf die non-const Version verweisen:
Wenn du das so rum machst kann man mit der const Version auch Variablen
verändern, je nachdem was die Lambda Funktion macht.
Moin
Sebastian V. schrieb:> So könnte man es machen
Nach dem Ausschlafen sieht das jetzt gut aus. :-)
Mein Compiler mag allerdings kein "auto" im Lambda-Kopf (C++14?). Also
bspw:
Sebastian V. schrieb:> Torsten R. schrieb:>> Wenn die Funktion so übersichtlich, wie im Beispiel ist, würde ich sie>> zwei mal ausschreiben, ansonsten würde ich (wie von Dir vorgeschlagen)>> mit const_cast auf die non-const Version verweisen:>> Wenn du das so rum machst kann man mit der const Version auch Variablen> verändern, je nachdem was die Lambda Funktion macht.
Habe mich auch gefragt, was alles schief gehen kann, wenn man es
umgekehrt macht. Habe den Scott Meyer nur in der 2nd ed. Da steht das
noch nicht drin.
Sebastian V. schrieb:> Torsten R. schrieb:>> Wenn die Funktion so übersichtlich, wie im Beispiel ist, würde ich sie>> zwei mal ausschreiben, ansonsten würde ich (wie von Dir vorgeschlagen)>> mit const_cast auf die non-const Version verweisen:>> Wenn du das so rum machst kann man mit der const Version auch Variablen> verändern, je nachdem was die Lambda Funktion macht.
Könnte man..., es ist aber eine private Funktion. Wenn die Klasse so
unübersichtlich ist, dass die Gefahr besteht, dass der Autor dort in ein
const qualifizierten Funktion ein Lambda verwendet, dass ein int& nimmt,
dann kann man natürlich das Lambda Argument zu compile-Zeit auch noch
mal prüfen.
so nicht! schrieb im Beitrag #4602528:
> Immer wieder lustig, wenn so ein Möchtegernprogrammieren eine Abhandlung> nach dem Schema
Und vielleicht auch einfach noch mal umdrehen, wenn man Sonntag-Morgen
schlechte Laune hat...
Danke für alle Beiträge und sorry für die späte Rückmeldung!
Sebastian V. schrieb:> statische Memberfunktion
Das wäre genau die einfache Lösung gewesen, die ich gesucht habe. Leider
muss auf einige Membervariablen/-methoden zugegriffen werden. Das kann
man zwar irgendwie mitübergeben, aber es wird dann noch hässlicher als
die doppelte Methode.
so nicht! schrieb im Beitrag #4602528:
> aufrufen und umgekehrt (2) (4), weshalb die Template-Methode in beiden>> Varianten nötig scheint (const overloading)>> Schwachsinn. Selbstverständlich kann eine non-const-Methode eine> const-Methode aufrufen.
Danke für die Korrektur. Der zweite Halbsatz war in dieser Form
natürlich Unfug und hätte heißen müssen: "...und umgekehrt kann eine
nicht-const-Methode nicht die const-Template-Methode mit einem
datenverändernden Lambda aufrufen, weshalb...". Das löst aber das
ursprüngliche Problem nicht.
Die Cast-Ansätze werde ich in Ruhe analysieren.
so nicht! schrieb im Beitrag #4602528:
> wie es jeder andere seit 100 Jahren macht.
Was wäre denn der bewährte Weg in diesem Fall? Der, den ich kenne,
verzichtet einfach ganz auf const-correctness.
Tom schrieb:> Die Cast-Ansätze werde ich in Ruhe analysieren.
BTW: Gibt es einen guten Grund, warum der Parameter doit per none
const reference übergeben wird?