Fallback por defecto para funciones de plantilla en C++ usando enable_if
Quiero escribir un mecanismo de C++, donde diferentes instanciaciones de una función son llamadas si una clase dada Param
es derivada de una cierta clase base.
Esto funciona bastante bien con std::is_base_of
y std::enable_if
.
Sin embargo, me gustaría tener una “versión por defecto” de esta función doStuff()
que sea llamada para “todas las demás clases”.
Esto básicamente funcionaría haciendo algo como “si Param no es derivado de A y si no es derivado de B”, pero me pregunto si hay una solución más elegante.
#include <iostream>
class A {};
class B : public A {};
class X {};
class Y : public X {};
class Other {};
template <typename param,=""></typename><><a, param="">::value, bool> = true>
void doStuff() {std::cout << "Base A" << std::endl;}
template <typename param,=""></typename><><x, param="">::value, bool> = true>
void doStuff() {std::cout << "Base X" << std::endl;}
int main()
{
doStuff<b>();
doStuff<y>();
// doStuff<other>(); esto no es derivado ni de B ni de Y, por lo que se llama al caso por defecto
}
La solución debe funcionar con C++14.</x,></a,>
davy.ai
Una posible solución es utilizar una combinación de
std::is_base_of
ystd::disjunction
para crear un rasgo de tipo que verifique siParam
no está derivado de ninguna de las clases especificadas. Luego, utilizastd::enable_if
con la negación de este rasgo de tipo para habilitar la versión predeterminada dedoStuff()
para todas las demás clases:“`c++
#include
#include
class A {};
class B : public A {};
class X {};
class Y : public X {};
class Other {};
template <><a, param=””>::value, bool> = true>
void doStuff() { std::cout << “Base A” << std::endl; }
template <><x, param=””>::value, bool> = true>
void doStuff() { std::cout << “Base X” << std::endl; }
template <!std::disjunction_v<std::is_base_of<A, Param>,
std::is_base_of<x, param=””>>, bool> = true>
void doStuff() { std::cout << “Caso predeterminado” << std::endl; }
int main() {();(); // llama al caso predeterminado
doStuff();
doStuff
doStuff
}
“`
Aquí, el rasgo de tipo
std::disjunction
se utiliza para combinar varias comprobaciones destd::is_base_of
, y su variable miembro estáticastd::disjunction_v
devuelvetrue
si al menos una de las comprobaciones devuelvetrue
. Utilizandostd::enable_if
con la negación de este rasgo de tipo significa que la versión predeterminada dedoStuff()
solo se habilita siParam
no está derivado de ninguna de las clases especificadas.</x,></x,></a,>