std::function
est un objet d'effacement de type. Cela signifie qu'il efface les détails de la façon dont certaines opérations se produisent et leur fournit une interface de temps d'exécution uniforme. Pour std::function
, le primaire1 Les opérations sont la copie / déménagement, la destruction et «invocation» avec operator()
- la «fonction comme l'opérateur d'appel».
En anglais moins abstrus, cela signifie que std::function
Peut contenir presque n'importe quel objet qui agit comme un pointeur de fonction dans la façon dont vous l'appelez.
La signature qu'il prend en charge va à l'intérieur des supports d'angle: std::function<void()>
Ne prend aucun argument et ne retourne rien. std::function< double( int, int ) >
prend deux int
Arguments et retours double
. En général, std::function
prend en charge le stockage de n'importe quel objet de type fonction dont les arguments peuvent être convertis à partir de sa liste d'arguments et dont la valeur de retour peut être convertie à sa valeur de retour.
Il est important de savoir que std::function
et les lambdas sont des bêtes différentes, si compatibles.
La partie suivante de la ligne est une lambda. Il s'agit d'une nouvelle syntaxe dans C ++ 11 pour ajouter la possibilité d'écrire des objets de fonction simple - des objets qui peuvent être invoqués avec ()
. Ces objets peuvent être effacés et stockés dans un std::function
Au prix de quelques frais généraux d'exécution.
[](){ code }
En particulier, c'est une lambda vraiment simple. Cela correspond à cela:
struct some_anonymous_type {
some_anonymous_type() {}
void operator()const{
code
}
};
Une instance du type de pseudo-fonction simple ci-dessus. Une classe réelle comme ce qui précède est "inventée" par le compilateur, avec un nom unique défini par implémentation (y compris souvent des symboles qu'aucun type défini par l'utilisateur ne peut contenir) (je ne sais pas s'il est possible que vous puissiez suivre la norme sans inventer Une telle classe, mais chaque compilateur que je connais crée réellement la classe).
La syntaxe Lambda complète ressemble:
[ capture_list ]( argument_list )
-> return_type optional_mutable
{
code
}
Mais de nombreuses pièces peuvent être omises ou laissées vides. Le capture_list correspond à la fois au constructeur du type anonyme résultant et de ses variables membre, l'argument_liste les arguments du operator()
, et le type de retour le type de retour. Le constructeur de l'instance lambda est également appelé par magie lorsque l'instance est créée avec CAPTURE_LIST.
[ capture_list ]( argument_list ) -> return_type { code }
devient essentiellement
struct some_anonymous_type {
// capture_list turned into member variables
some_anonymous_type( /* capture_list turned into arguments */ ):
/* member variables initialized */
{}
return_type operator()( argument_list ) const {
code
}
};
Noter que dans C ++ 20 Des arguments de modèle ont été ajoutés aux lambdas, et cela n'est pas couvert ci-dessus.
[]<typename T>( std::vector<T> const& v ) { return v.size(); }
1 De plus, RTTI est stocké (TypeID), et l'opération de type coulé à original est incluse.