C++ std::function para tomar funciones con parámetro de subclase
[Actualización] Razón de esta pregunta:
Hay muchas lambdas existentes definidas como [](const ChildType1& child)
, todas en un gran registro. Queremos registrar nuevas lambdas como [](const ChildType2& child)
en el mismo registro. Si definimos el envoltorio de función usando Parent
, para las muchas lambdas existentes necesitamos cambiarlas a [](const Parent& someone)
y realizar un downcast desde Parent
a ChildType1
dentro.
Si tengo un envoltorio de función como std::function<void(const Parent&)>
, ¿hay alguna manera de permitir que acepte una función con una subclase de Parent
como parámetro, por ejemplo, [](const Child& child){...}
, donde Child
es una subclase de Parent
.
Salgo de aquí no se compila. IDE en línea link.
“`
<h1>include <iostream></h1>
<h1>include <functional></h1>
class Parent {
public:
virtual void decir() const {
std::cout<<"Soy el padre"<<"\n";
}
};
class Child: public Parent {
public:
void decir() const {
std::cout<<"Soy el hijo"<<"\n";
}
};
typedef std::function<void(const Parent&)> Envoltorio;
int main() {
Envoltorio func=[](const Child& child){ // por supuesto, funciona si Child->Parent
child.decir();
};
<pre><code>Child c;
func(c);
return 0;
</code></pre>
}
“`
davy.ai
Sí, es posible permitir que un envoltorio de función con
std::function<void(const parent&)="">
tome una función con un subclase deParent
como parámetro. Esto se puede lograr utilizando plantillas de función ystd::enable_if
.En el ejemplo anterior, definimos dos plantillas de función
funcion_con_child
yfuncion_sin_child
que aceptan un parámetro de tipoT
.es_puntero_de_padre
yno_es_puntero_de_padre
se utilizan como alias parastd::enable_if
para imponer las restricciones de tipo.En la función principal, podemos pasar un objeto
Child
a la funciónEnvoltorio
, que llamará al métododecir
deChild
.Ten en cuenta que pasar cualquier subclase no Parent resultará en un error de compilación, ya que la función
Envoltorio
está diseñada solo para aceptarParent
o sus subclases.</void(const></void(const>