tamaño - Con C++ 17, ¿es posible detectar si una estructura/clase tiene alguna base?
funciones con estructuras en c (2)
Necesito un rasgo de tipo que será verdadero si el tipo dado se deriva de algo, y falso de lo contrario.
Por ejemplo:
template<class T>
struct is_inherit
//... logic of inheritance detection
;
template<class T>
void AppLogic(){
if constexpr(is_inherit<T>::value) {
puts("T has base");
//...
} else {
puts("T doesn''t have base");
//...
}
}
struct A {};
struct C {};
struct B: C {};
int main() {
AppLogic<A>(); // print: T doesn''t have base
AppLogic<B>(); // print: T has base
}
¿Es posible de alguna manera implementar esa estructura de rasgo "is_inherit"?
¿Por qué?
Estoy desarrollando un generador manual de cuadernos de pila para Windows x64. Según la https://docs.microsoft.com/en-us/cpp/build/return-values-cpp documentación, si es un tipo:
- tiene una longitud de 1, 2, 4, 8, 16, 32 o 64 bits;
- no tiene ningún operador de asignación de copia, destructor o constructor definido por el usuario;
- no tiene miembros de datos no estáticos ni protegidos ni privados;
- no tiene miembros de datos no estáticos de tipo de referencia;
- no tiene clases base;
- no tiene funciones virtuales;
- y no tiene miembros de datos que tampoco cumplan con estos requisitos;
entonces su valor de retorno está en el registro RAX; de lo contrario, la función tiene un argumento oculto que debo detectar y manejar.
Esta solía ser la definición de un C ++ 03 POD, sin embargo en C ++ 11 esto cambió:
Debido a que la definición ha cambiado en el estándar C ++ 11, no recomendamos utilizar
std::is_pod
para esta prueba.
Hasta ahora, con algunos rasgos conjugados podía detectar si el tipo cumplía con la definición de C ++ 03 POD o no. Sin embargo, con C ++ 17 las reglas agregadas han cambiado, y eso rompió mi solución.
Si de alguna manera puedo detectar si un tipo T tiene alguna clase base, mi solución funcionará nuevamente.
Creo que no es posible verificar si " T
deriva de algo", al menos no de una manera estándar. Si está utilizando esta técnica para verificar si un tipo es un POD / trivial / agregado, existen algunos rasgos de tipo que pueden ayudarlo:
Sí, esto es posible, al menos para agregados.
Primero construimos una plantilla de clase que es convertible a cualquier base adecuada de su parámetro de plantilla:
template<class T>
struct any_base {
operator T() = delete;
template<class U, class = std::enable_if_t<std::is_base_of_v<U, T>>> operator U();
};
Luego detectamos si un parámetro de plantilla T
es any_base<T>
construible a partir de un valor de tipo any_base<T>
:
template<class, class = void> struct has_any_base : std::false_type {};
template<class T>
struct has_any_base<T, std::void_t<decltype(T{any_base<T>{}})>> : std::true_type {};
Example .