Domanda

Qualche tempo fa ho usato std::function più o meno così:

std::function<void(int)> func = [](int i) -> int { return i; };

Fondamentalmente, l'ho fatto perché volevo memorizzare diversi oggetti funzione in un file std::function, ma non volevo limitare i tipi di restituzione di queste funzioni.Dato che sembrava funzionare, l'ho seguito.Ma non sono convinto che sia sicuro da usare e non sono riuscito a trovare alcuna documentazione al riguardo.Qualcuno sa se questo utilizzo è legittimo?O più in generale, quali sono le regole per l'oggetto che può essere tranquillamente assegnato ad a std::function?

Modificare

Per chiarimenti, il problema che mi preoccupa è che la funzione lambda restituisce un int, Mentre func è dichiarato con il tipo restituito void.Non sono sicuro che vada bene, soprattutto una volta chiamata func() è fatto.

È stato utile?

Soluzione

Il tuo codice ha un comportamento indefinito. Può o meno funzionare come prevedi. Il motivo per cui ha un comportamento indefinito è dovuto al 20.8.11.2.1 [func.wrap.func.con]/p7:

Richiede: F deve essere CopyConstructible. f deve essere richiamabile (20.8.11.2) per i tipi di argomentazioni ArgTypes e tipo di ritorno R.

Per f essere richiamabile per il tipo di ritorno R, f deve restituire qualcosa di implicitamente convertibile al tipo di ritorno di std::function (void nel tuo caso). E int non è implicitamente convertibile in void.

Mi aspetto che il tuo codice funzioni sulla maggior parte delle implementazioni. Tuttavia, su almeno un'implementazione (libc ++), non riesce a compilare:

test.cpp:7:30: error: no viable conversion from 'int (int)' to 'std::function<void (int)>'
    std::function<void(int)> ff = f;
                             ^    ~

Ironia della motivazione per questo comportamento deriva da un'altra domanda così.

L'altra domanda ha presentato un problema con std::function utilizzo. La soluzione a tale problema ha comportato l'applicazione dell'implementazione Richiede: clausola al momento della compilazione. Al contrario, la soluzione al problema di questa domanda è proibitivo l'implementazione dall'applicazione del Richiede: clausola.

Altri suggerimenti

Il tuo caso d'uso è ben definito secondo lo standard.

Stai costruendo a std::function da un oggetto richiamabile[1]

§20.8.11.2.1/7:

template<class F> function(F f);

Richiede:F deve essere CopyConstructible.f deve essere richiamabile (20.8.11.2) per i tipi di argomentazioni argtypes e tipo di ritorno R.

Quindi la tua f è chiamabile?

§20.8.11.2/2 dice:

Un oggetto Filant F del tipo F è richiamabile per i tipi di argomentazioni argtypes e il tipo di ritorno R se l'espressione INVOKE (f, declval<ArgTypes>()..., R), considerato come un operando non valutato (clausola 5), è ben formata (20.8.2).

E la definizione di INVOKE dice:

§20.8.2

  1. Definire INVOKE (f, t1, t2, ..., tN) come segue:...cose che riguardano i puntatori a funzioni membro/var ...— f(t1, t2, ..., tN) in tutti gli altri casi.

  2. Definire INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN) implicitamente convertito in R.

E poiché qualsiasi tipo può essere convertito implicitamente in void, il tuo codice dovrebbe andare bene con un compilatore conforme agli standard. Come sottolineato da litb di seguito, non esiste una conversione implicita in void, quindi non è ben definita.

[1]:Penso che lambda conti come oggetto richiamabile qui, anche se non ho un riferimento per questo.Il tuo lambda potrebbe anche essere utilizzato come puntatore a funzione poiché non cattura alcun contesto

Sembra che potrebbe essere ok per le funzioni anonime.

Citazione da http://www.alorelang.org/release/0.5/doc/std_function.html (Questo non proviene dalla libreria standard C ++, tuttavia sembra che stiano usando qualcosa di simile nei legami fino a C ++)

Gli oggetti della funzione possono essere creati solo con una definizione di funzione, un'espressione della funzione anonima o accedendo a un metodo associato usando l'operatore DOT (.).

Un altro modo in cui questo potrebbe essere fatto è memorizzare il puntatore della funzione in Auto come visto qui: http://en.wikipedia.org/wiki/anonymous_function (Sezione C ++)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top