Verwenden Sie `std :: function ` Aufrufe Nicht-Void-Funktion
-
27-10-2019 - |
Frage
Vor einiger Zeit habe ich benutzt std::function
ziemlich ähnlich:
std::function<void(int)> func = [](int i) -> int { return i; };
Grundsätzlich habe ich das getan, weil ich verschiedene Funktionsobjekte in a speichern wollte std::function
, aber ich wollte die Rückgabetypen dieser Funktionen nicht einschränken. Da dies zu funktionieren schien, ging ich damit ein. Aber ich bin nicht davon überzeugt, dass es sicher zu bedienen ist, und ich konnte keine Dokumentation dazu finden. Weiß jemand, ob diese Verwendung legitim ist? Oder allgemeiner, welche Regeln sind für das Objekt, das einem sicher zugewiesen werden kann std::function
?
Bearbeiten
Zur Klarstellung ist das Problem, mit dem ich befasst bin, dass die Lambda -Funktion eine zurückgibt int
, während func
wird mit Rückgabetyp deklariert void
. Ich bin mir nicht sicher, ob dies in Ordnung ist, besonders wenn ein Anruf angerufen wird func()
wird gemacht.
Lösung
Ihr Code hat ein undefiniertes Verhalten. Es kann wie Sie erwarten oder nicht. Der Grund, warum es ein undefiniertes Verhalten hat, liegt bei 20.8.11.2.1 [func.wrap.func.con]/p7:
Erfordert:
F
mussCopyConstructible
.f
muss für Argumentypen abrufbar sein (20.8.11.2)ArgTypes
und RückkehrtypR
.
Zum f
für den Rückgabetyp aufrufbar sein R
, f
Muss etwas zurückgeben, das implizit auf den Rückgabetyp der zurückkehrt std::function
(void
in Ihrem Fall). Und int
ist nicht implizit konvertierbar zu void
.
Ich würde erwarten, dass Ihr Code an den meisten Implementierungen funktioniert. Jedoch bei mindestens einer Implementierung (libc ++), es kann nicht kompiliert werden:
test.cpp:7:30: error: no viable conversion from 'int (int)' to 'std::function<void (int)>'
std::function<void(int)> ff = f;
^ ~
Ironischerweise stammt die Begründung für dieses Verhalten aus eine andere Frage.
Die andere Frage zeigte ein Problem mit std::function
Verwendungszweck. Die Lösung für dieses Problem bestand darin, die Umsetzung durchzusetzen Erfordert: Klausel zur Kompilierungszeit. Im Gegensatz dazu ist die Lösung für das Problem dieser Frage verbieten die Umsetzung durch Durchsetzung der Erfordert: Klausel.
Andere Tipps
Ihr Anwendungsfall ist nach dem Standard gut definiert.
Sie konstruieren a std::function
von einem Callable -Objekt [1
§20.8.11.2.1/7:
template<class F> function(F f);
Erfordert: F ist einkundig zu sein. F ist für Argumenttypen Argtypes und Rückgabe Typ R.
Ist Ihr F -Callable?
§20.8.11.2/2 sagt:
Ein Callable-Objekt f vom Typ F ist für Argumenttypen ArgTTYPES und Rückgabetyp R, wenn die Auswirkung zurückgibt
INVOKE (f, declval<ArgTypes>()..., R)
, als unegelegener Operand (Klausel 5), ist gut gebildet (20,8,2).
Und die Definition von INVOKE
sagt:
§20.8.2
Definieren
INVOKE (f, t1, t2, ..., tN)
wie folgt: ... Sachen, die sich mit Mitgliederfunktion/VAR -Zeigern befassen ... - - - - - - -f(t1, t2, ..., tN)
In allen anderen Fällen.Definieren
INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN)
implizit konvertiert inR
.
Und da jeder Typ implizit auf konvertiert werden kann Wie von LitB unten hervorgeht, gibt es keine implizite Umwandlung in Leere, sodass dies nicht gut definiert ist.void
, Ihr Code sollte mit einem Standard-Compiler in Ordnung sein.
1]: Ich denke, die Lambda zählt hier als ein Callable -Objekt, obwohl ich dafür keine Referenz habe. Ihr Lambda könnte auch als Funktionszeiger verwendet werden, da er keinen Kontext erfasst
Dies sieht so aus, als wäre es für anonyme Funktionen in Ordnung.
Zitat aus http://www.alorelang.org/release/0.5/doc/std_function.html (Dies stammt nicht aus der C ++ - Standardbibliothek, es sieht jedoch so aus, als würden sie etwas Ähnliches in Bindungen bis c ++ verwenden.)
Funktionsobjekte können nur mit einer Funktionsdefinition, einem anonymen Funktionsausdruck oder durch Zugriff auf eine gebundene Methode unter Verwendung des DOT -Operators erstellt werden.
Eine andere Möglichkeit, wie dies möglicherweise getan werden könnte, besteht darin, den Funktionszeiger in auto zu speichern, wie hier zu sehen ist: http://en.wikipedia.org/wiki/anonymous_function (C ++ - Abschnitt)