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.

War es hilfreich?

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 muss CopyConstructible. f muss für Argumentypen abrufbar sein (20.8.11.2) ArgTypes und Rückkehrtyp R.

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

  1. 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.

  2. Definieren INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN) implizit konvertiert in R.

Und da jeder Typ implizit auf konvertiert werden kann void, Ihr Code sollte mit einem Standard-Compiler in Ordnung sein. Wie von LitB unten hervorgeht, gibt es keine implizite Umwandlung in Leere, sodass dies nicht gut definiert ist.

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)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top