Je me demandais comment vérifier correctement si un std::function
est vide. Prenons 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 très bien dans MSVC mais si j'appelle doSomething()
sans initialiser eventFunc
le code se bloque évidemment. C'est attendu mais je me demandais quelle est la valeur du eventFunc
? Le débogueur dit 'empty'
. J'ai donc corrigé cela en utilisant une instruction if simple:
void doSomething() {
...
if (eventFunc) {
eventFunc(42);
}
}
Cela fonctionne mais je me demande toujours quelle est la valeur de non-initialized std::function
? Je voudrais écrire if (eventFunc != nullptr)
mais ce std::function
n'est (évidemment) pas un pointeur.
Pourquoi le pur si fonctionne? Quelle est la magie derrière ça? Et, est-ce la bonne façon de le vérifier?
c++
c++11
std-function
NightElfik
la source
la source
eventFunc
n'est pas un lambda; c'est unstd::function
. Vous pouvez stocker des lambdas dans desstd::function
s, mais ce n'est pas la même chose.Réponses:
Vous ne vérifiez pas un lambda vide, mais si le
std::function
contient une cible appelable. Le chèque est bien défini et fonctionne grâce àstd::function::operator bool
elle permet une conversion implicitebool
dans des contextes où des valeurs booléennes sont requises (comme l'expression conditionnelle dans uneif
instruction).De plus, la notion de lambda vide n'a pas vraiment de sens. Dans les coulisses, le compilateur convertit une expression lambda en une
struct
(ouclass
) définition, avec les variables que vous capturez stockées en tant que données membres de thisstruct
. Un opérateur d'appel de fonction publique est également défini, ce qui vous permet d'appeler le lambda. Alors, que serait un lambda vide?Vous pouvez également écrire
if(eventFunc != nullptr)
si vous le souhaitez, c'est équivalent au code que vous avez dans la question.std::function
définitoperator==
etoperator!=
surcharge pour comparer avec unnullptr_t
.la source
== nullptr
Mais ne fait pas la même chose? Il semble qu'il y ait une surcharge pour l'==
opérateur qui provoque un "vide"std::function
à comparertrue
avecnullptr
: cplusplus.com/reference/functional/function/operatorsnullptr
fonctionnera aussi,if(eventFunc != nullptr)
équivaut àif(eventFunc)
la question ci-dessus.std::function::operator bool
n'autorise pas la conversion implicite enbool
. Il est marquéexplicit
après tout, mais le standard fait une exception pour certaines constructions de langage qui attendent des expressions booléennes, l'appelant "contextuellement converti en bool". Vous pouvez trouver l'extrait pertinent de standardese et une explication ici: chris-sharpe.blogspot.com/2013/07/…explicit
, c'est pourquoi j'ai pris soin de préciser qu'il permet une conversion implicitebool
dans des contextes où des valeurs booléennes sont requises . C'est exactement ce qui se passe dans le code en question.Vérifiez ici http://www.cplusplus.com/reference/functional/function/operator_bool/
Exemple
Production
la source
swap()
. Je pensais que la sortie était à l'envers jusqu'à ce que je m'en rende compte.(Permettez-moi de fournir une réponse claire.)
Vous pouvez vérifier si a
std::function
est vide avecstd::function::operator bool
.Exemple
Production
la source