web-dev-qa-db-fra.com

Comment vérifier correctement si std :: function est vide dans C ++ 11?

Je me demandais comment vérifier correctement si un std::function Est vide. Considérons cet exemple:

class Test {
    std::function<void(int a)> eventFunc;

    void registerEvent(std::function<void(int a)> e) {
        eventFunc = e;
    }

    void doSomething() {
        ...
        eventFunc(42);
    }
};

Ce code se compile parfaitement dans MSVC mais si j'appelle doSomething() sans initialiser le eventFunc, le code se bloque évidemment. C'est prévu, mais je me demandais quelle est la valeur de eventFunc? Le débogueur dit 'empty'. J'ai donc corrigé cela en utilisant une simple déclaration if:

   void doSomething() {
        ...
        if (eventFunc) {
            eventFunc(42);
        }
   }

Cela fonctionne mais je me demande toujours quelle est la valeur de std::function Non initialisé? J'aimerais écrire if (eventFunc != nullptr) mais std::function N'est (évidemment) pas un pointeur.

Pourquoi le pur si fonctionne? Quelle est la magie derrière tout ça? Et, est-ce la bonne façon de vérifier?

87
NightElfik

Vous ne recherchez pas un lambda vide, mais vérifiez si std::function contient une cible appelable. La vérification est bien définie et fonctionne à cause de std::function::operator bool qui permet la conversion implicite en bool dans des contextes dans lesquels des valeurs booléennes sont requises (telle que l'expression conditionnelle dans une déclaration if).

En outre, la notion de lambda vide n'a pas vraiment de sens. En coulisse, le compilateur convertit une expression lambda en une définition de struct (ou class), les variables que vous capturez étant stockées en tant que membres de données de ce struct. Un opérateur d'appel de fonction publique est également défini, ce qui vous permet d'appeler le lambda. Alors, quel serait un lambda vide?


Vous pouvez également écrire if(eventFunc != nullptr) si vous le souhaitez, cela équivaut au code que vous avez dans la question. std::functiondéfinitoperator== Et operator!= Surchargent pour permettre la comparaison avec un nullptr_t.

91
Praetorian

Vérifiez ici http://www.cplusplus.com/reference/functional/function/operator_bool/

Exemple

// function::operator bool example
#include <iostream>     // std::cout
#include <functional>   // std::function, std::plus

int main () {
  std::function<int(int,int)> foo,bar;
  foo = std::plus<int>();

  foo.swap(bar);

  std::cout << "foo is " << (foo ? "callable" : "not callable") << ".\n";
  std::cout << "bar is " << (bar ? "callable" : "not callable") << ".\n";

  return 0;
}

Sortie

foo n'est pas appelable.

bar est appelable.

19
Dawid Drozd