Me preguntaba cómo comprobar correctamente si un std::function
está vacío. Considere 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 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 simple declaración if:
void doSomething() {
...
if (eventFunc) {
eventFunc(42);
}
}
Esto funciona, pero todavía me pregunto cuál es el valor de no inicializado std::function
. Me gustaría escribir if (eventFunc != nullptr)
pero std::function
(obviamente) no es un puntero.
¿Por qué el puro si funciona? ¿Cuál es la magia detrás de esto? Y, ¿es la forma correcta de comprobarlo?
c++
c++11
std-function
NightElfik
fuente
fuente
eventFunc
no es una lambda; es unstd::function
. Puede almacenar lambdas enstd::function
s, pero no son lo mismo.Respuestas:
No está comprobando una lambda vacía, sino si
std::function
tiene un objetivo invocable almacenado en él. La verificación está bien definida y funciona, por lostd::function::operator bool
que permite la conversión implícitabool
en contextos donde se requieren valores booleanos (como la expresión condicional en unaif
declaración).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
struct
(oclass
) definición, con las variables capturadas almacenadas como miembros de datos de estastruct
. También se define un operador de llamada de función pública, que es lo que le permite invocar la 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
defineoperator==
yoperator!=
sobrecarga para comparar con anullptr_t
.fuente
== nullptr
Pero no hace lo mismo? Parece que se supone que hay una sobrecarga para el==
operador que causa un "vacío"std::function
para comparartrue
connullptr
: cplusplus.com/reference/functional/function/operatorsnullptr
funcionará también,if(eventFunc != nullptr)
es equivalente aif(eventFunc)
en la pregunta anterior.std::function::operator bool
no permite la conversión implícita abool
.explicit
Después de todo, está marcado , pero el estándar hace una excepción para ciertas construcciones de lenguaje que esperan expresiones booleanas, llamándolo "convertido contextualmente a bool". Puede encontrar el fragmento relevante de standardese y una explicación aquí: chris-sharpe.blogspot.com/2013/07/…explicit
, por eso tuve cuidado de indicar que permite la conversión implícitabool
en contextos donde se requieren valores booleanos . Esto es exactamente lo que sucede en el código en cuestión.Consulte aquí http://www.cplusplus.com/reference/functional/function/operator_bool/
Ejemplo
Salida
fuente
swap()
. Estaba pensando que la salida estaba al revés hasta que me di cuenta.(Déjame darte una respuesta clara).
Puede comprobar si a
std::function
está vacío constd::function::operator bool
.Ejemplo
Salida
fuente