c++ - namespace - std::cout
¿Cómo verificar correctamente si std:: function está vacía en C++ 11? (2)
Me preguntaba cómo comprobar correctamente si una std::function
está vacía. Considera este ejemplo:
class Test {
std::function<void(int a)> eventFunc;
void registerEvent(std::function<void(int a)> e) {
eventFunc = e;
}
void doSomething() {
...
eventFunc(42);
}
};
Este código se compila muy bien en MSVC, pero si llamo doSomething()
sin inicializar eventFunc
el código obviamente se bloquea. Eso es lo esperado, pero me preguntaba ¿cuál es el valor de eventFunc
? El depurador dice ''empty''
. Así que lo arreglé usando una declaración if simple:
void doSomething() {
...
if (eventFunc) {
eventFunc(42);
}
}
Esto funciona, pero todavía me pregunto ¿cuál es el valor de la std::function
no inicializada? Me gustaría escribir if (eventFunc != nullptr)
pero std::function
es (obviamente) no un puntero.
¿Por qué el puro si funciona? ¿Cuál es la magia detrás de esto? Y, ¿es la forma correcta de verificarlo?
Consulte aquí http://www.cplusplus.com/reference/functional/function/operator_bool/
Ejemplo
// 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;
}
Salida
foo no es invocable.
la barra es invocable
No está buscando una lambda vacía, sino si la std::function
tiene un destino invocable almacenado en ella. La comprobación está bien definida y funciona debido a std::function::operator bool
que permite la conversión implícita a bool
en contextos donde se requieren valores booleanos (como la expresión condicional en una sentencia if
).
Además, la noción de una lambda vacía realmente no tiene sentido. Detrás de escena, el compilador convierte una expresión lambda en una definición de struct
(o class
), con las variables que captura almacenadas como miembros de datos de esta struct
. También se define un operador de llamada a función pública, que es lo que le permite invocar el lambda. Entonces, ¿qué sería una lambda vacía?
También puede escribir if(eventFunc != nullptr)
si lo desea, es equivalente al código que tiene en la pregunta. std::function
defines operator==
y operator!=
sobrecargas para comparar con un nullptr_t
.