Ich versuche C ++ 11-Funktionen zu verwenden, um benutzerdefinierte Stream-Manipulatoren einfacher zu erstellen. Ich kann Lambda-Funktionen als Manipulatoren verwenden, aber nicht std::function<ostream&(ostream&)>
.
Hier ist der gekürzte Code:
%Vor% Die zweite cout
-Anweisung schlägt mit folgendem fehl:
Warum scheitert das? Ich benutze cygwin gcc 4.5.3.
Während ich frage, bin ich nicht verrückt nach der Verwendung von std::function
wegen der Effizienzprobleme. Aber ich möchte Funktionen schreiben, die Lambda-Funktionen zurückgeben und keine Ahnung haben, wie das geht, ohne std::function
. Zum Beispiel wäre so etwas wie das Folgende toll.
... funktioniert aber offensichtlich nicht. Gibt es eine alternative Syntax, die funktioniert? Ich kann mir nicht vorstellen, was es sein könnte, also könnte ich bei std::function
feststecken.
Wenn ich eine Lösung für die zweite Frage hätte, wäre die erste Frage fragwürdig.
Danke.
Definieren von operator<<(ostream&, std::function<ostream&(ostream&)>
half. Ich hatte eine Webseite falsch gelesen und hatte den Eindruck, dass ostream
schlau genug war, ein beliebiges Objekt mit einem operator()
als Manipulator zu behandeln. Ich habe mich geirrt. Außerdem wurde das einfache lambda
, das ich gebaut habe, wahrscheinlich nur zu einer einfachen alten Funktion kompiliert, genau wie mir gesagt wurde. In der Tat, wenn ich die Variable Capture verwenden, um sicherzustellen, dass lambda
keine einfache Funktion ist, schlägt der Compiler fehl. Außerdem werden Objekte mit operator()
(standardmäßig) nicht als Manipulatoren behandelt:
Weitere Aktualisierung: Es stellt sich heraus, dass eine etwas robustere Lösung als die folgenden mit:
erreicht werden kann %Vor% Dieser Code hat ein zusätzliches const
. Ich entdeckte dies, als ich versuchte, die Lösung in meinem Projekt zu implementieren.
Wenn du operator<<
für ostream
betrachtest, gibt es keine Überladung für die Verwendung von std::function
- und das ist im Grunde das, was du hier mit cout << functionManip
machen willst. Um dies zu beheben, definieren Sie entweder die Überlast selbst:
Oder übergeben Sie stream
als Argument an die Funktion:
Warum lambda
funktioniert, da der Rückgabetyp von lambda
nicht definiert ist und eine Überladung für die Verwendung eines Funktionszeigers besteht:
Das Lambda umschließt wahrscheinlich alles, indem es eine Struktur verwendet und operator()
definiert, was in diesem Fall genau wie ein Funktionszeiger funktioniert. Das ist für mich die wahrscheinlichste Erklärung, hoffentlich kann mich jemand korrigieren, wenn ich falsch liege.
Dies ist nicht die Ursache des Fehlers, aber da Sie sowohl lambdaManip
als auch functionManip
mit dem Rückgabetyp ostream&
definiert haben, glaube ich, dass Sie vergessen haben, return stream;
zu beiden hinzuzufügen.
Der Aufruf cout << functionManip
schlägt fehl, weil kein operator<<(ostream&, std::function<ostream&(ostream&)>
definiert ist. Fügen Sie einen hinzu, und der Anruf wird erfolgreich ausgeführt.
Alternativ können Sie functionManip
als
Dies funktioniert, ohne die operator<<
-Definition hinzuzufügen.
Wie bei Ihrer Frage zur Rückgabe eines Lambda kann das Lambda, das von getAdditionFunctor
zurückgegeben wird, ein Capture-less Lambda sein, das implizit in einen Funktionszeiger umgewandelt werden kann.
Die vorherigen Antworten haben den neuesten Stand der Technik, aber wenn Sie schwer mit std::function
s und / oder lambdas als Stream-Manipulatoren in Ihrem Code verwenden wollen, dann möchten Sie vielleicht nur Hinzufügen der folgenden Funktionsschablonendefinition zu Ihrer Codebase im globalen Bereich:
Der nachfolgende Rückgabetyp verwendet Ausdruck SFINAE , so dass diese besondere operator<<
Überladung gewonnen hat Nehmen Sie nicht einmal an der Überladungsauflösung teil, es sei denn m(os)
ist ein wohlgeformter Ausdruck. (Das ist was du willst.)
Dann kannst du sogar Dinge wie
tun %Vor% (Beachten Sie das vollständige Fehlen von std::function
-Objekten im obigen Code! Versuchen Sie, lambdas nicht in std::function
-Objekte einzufüllen, es sei denn, Sie müssen dies unbedingt tun, da das Erstellen eines std::function
-Objekts teuer sein kann Speicherzuweisung.)
Es wäre sinnvoll, wenn C ++ 17 diese operator<<
overload der Standardbibliothek hinzufügt, aber mir sind momentan keine konkreten Vorschläge in diesem Bereich bekannt.
Tags und Links c++ lambda c++11 iostream manipulators