Question

Il est nécessaire pour moi d'utiliser std::function Mais je ne sais pas ce que signifie la syntaxe suivante.

std::function<void()> f_name = []() { FNAME(); };

Quel est l'objectif d'utiliser std::function? Est-ce pour faire un pointeur vers une fonction?

Était-ce utile?

La solution

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

Autres conseils

Brisons la ligne:

Fonction STD ::

Il s'agit d'une déclaration pour une fonction ne prenant aucun paramètre et ne renvoyant aucune valeur. Si la fonction renvoyait un int, ça ressemblerait à ceci:

std::function<int()>

De même, s'il a également pris un paramètre int:

std::function<int(int)>

Je soupçonne que votre principale confusion est la prochaine partie.

[]() { FNAME(); };

La [] la partie est appelée un clause de capture. Ici, vous mettez des variables locales à la déclaration de votre lambda, et que vous voulez être disponible dans La fonction lambda elle-même. Cela dit "Je ne veux rien être capturé". Si cela faisait partie d'une définition de classe et que vous vouliez que le cours soit disponible pour la Lambda, vous pourriez faire:

[this]() { FNAME(); };

La partie suivante, ce sont les paramètres transmis à la Lambda, exactement la même chose que si c'était une fonction régulière. Comme mentionné précédemment, std::function<void()> est une signature pointant vers une méthode qui ne prend aucun paramètre, donc c'est vide également.

Le reste est le corps du lambda lui-même, comme s'il s'agissait d'une fonction régulière, que nous pouvons voir appelle la fonction FNAME.

Un autre exemple

Disons que vous aviez la signature suivante, c'est-à-dire pour quelque chose qui peut additionner deux nombres.

std::function<int(int, int)> sumFunc;

Nous pourrions maintenant déclarer un lambda ainsi:

sumFunc = [](int a, int b) { return a + b; };

Je ne sais pas si vous utilisez MSVC, mais voici un lien de toute façon à la syntaxe d'expression LAMDA:

http://msdn.microsoft.com/en-us/library/dd293603.aspx

Les lambdas avec des captures (Stateful Lambdas) ne peuvent pas être attribués les uns aux autres car ils ont des types uniques, même s'ils se ressemblent exactement. Pour pouvoir stocker et faire le tour des lambdas avec des captures, nous pouvons utiliser "Fonction STD ::"Pour maintenir un objet de fonction construit par une expression de lambda. Fondamentalement"Fonction STD ::"est, pour pouvoir attribuer des fonctions lambda avec différentes structures de contenu à un objet de fonction lambda.

Exp:

auto func = [](int a){
 cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //ATTENTION(ERROR!): assigning a new structure to the same object
 cout << "x:" << x << ",a:" << a << endl;
};
func(2);

Ainsi, l'utilisation ci-dessus sera incorrecte. Mais si nous définissons un objet de fonction avec "STD :: Function":

auto func = std::function<void(int)>{};
func = [](int a){
  cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //CORRECT. because of std::function
  //...
}; 

int y = 11;
func = [x,y](int a){ //CORRECT
 //...
}; 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top