La última vez , usamos SFINAE para determinar si un tipo tiene una definición, y lo usamos en combinación con
if constexpr
y expresiones lambda genéricas para que el código pueda usar el tipo si está definido, mientras el compilador todavía lo acepta (y descartado) si el tipo no está definido.
Sin embargo, hay varios problemas con esta aplicación:
- Cada vez que necesitas escribir una
struct
. - Si el tipo no existe, entonces asignándole un nombre, este tipo se ingresa en el espacio de nombres actual , y no en el espacio de nombres en el que desea que esté el tipo.
struct
usar una struct
con un nombre no calificado. No puede usarlo para verificar un tipo que no importó en el espacio de nombres actual.
Podemos solucionar los tres problemas con una solución: primero declare el tipo en el espacio de nombres deseado.

Después de haber hecho esto, no necesita escribir una
struct
porque la estructura ha sido declarada. Usarlo como un parámetro de tipo de plantilla en
call_if_defined
no conducirá a la creación de una nueva declaración, ya que todo ya ha sido declarado. Y desde que fue declarada, puede acceder a ella a través de su nombre no calificado, su nombre de espacio de nombre completo o cualquier cosa intermedia. También a través de un alias de tipo o un tipo dependiente (desafortunadamente, no están entre).
namespace app { void foo() { call_if_defined<awesome::special>([&](auto* p) {
Aquellos que han estado siguiendo esta serie de artículos desde el principio pueden haber notado que el método
call_if_defined
no coincide con la versión que escribimos anteriormente. La nueva versión admite varios parámetros de tipo y llama a una lambda solo si todos los tipos están definidos.
Echemos un vistazo más de cerca:
template<typename... T, typename TLambda> void call_if_defined(TLambda&& lambda) { if constexpr ((... && is_complete_type_v<T>)) { lambda(static_cast<T*>(nullptr)...); } }
Los corchetes dobles en si constexpr ((...)) se ven raros, pero son obligatorios. La
if constexpr
requiere paréntesis externos, y
una expresión de convolución requiere paréntesis internos. La expresión de convolución se expande a
if constexpr ( (is_complete_type_v<T1> && is_complete_type_v<T2> && ... is_complete_type_v<Tn>))
La llamada lambda utiliza la
extensión del paquete de parámetros :
lambda(static_cast<T*>(nullptr)...);
Se expande a
lambda(static_cast<T1*>(nullptr), static_cast<T2*>(nullptr), ..., static_cast<Tn*>(nullptr));
donde
static_cast<T*>(nullptr)
repite una vez para cada tipo.
Como señalé anteriormente, podemos usar esta función para llamar a lambda si todos los tipos están definidos:
void foo(Source const& source) { call_if_defined<special, magic>( [&](auto* p1, auto* p2) { using special = std::decay_t<decltype(*p1)>; using magic = std::decay_t<decltype(*p2)>; auto s = source.try_get<special>(); if (s) magic::add_magic(s); }); }
C ++ 20 te permite escribirlo así:
void foo(Source const& source) { call_if_defined<special, magic>( [&]<typename special, typename magic> (special*, magic*) { auto s = source.try_get<special>(); if (s) magic::add_magic(s); }); }
que le permite nombrar el tipo de plantilla, eliminando así la necesidad de volver a extraerla mientras juega con
std::decay_t
.
En el próximo artículo, utilizaremos esto como trampolín y ampliaremos el circuito.
Nota : esta es la cuarta parte de la serie principal de artículos, pero todavía hay otras partes (
1 ,
2 ,
3 ,
5 ). Para los impacientes: esto es lo que necesita copiar y pegar:
template<typename, typename = void> constexpr bool is_type_complete_v = false; template<typename T> constexpr bool is_type_complete_v <T, std::void_t<decltype(sizeof(T))>> = true; template<typename... T, typename TLambda> void call_if_defined(TLambda&& lambda) { if constexpr ((... && is_complete_type_v<T>)) { lambda(static_cast<T*>(nullptr)...); } }
Por cierto, tenemos un trabajo genial
Durante más de una década,
Havok ha estado a la vanguardia de la innovación en el desarrollo de juegos y 3D interactivo. Como parte de Cognition, el equipo de HoloLens, ahora estamos combinando esta experiencia y el poder de la nube de Azure para desarrollar muchos nuevos y emocionantes servicios de realidad mixta. Entre ellos está el recientemente anunciado servicio Azure Remote Rendering. Nos apasiona combinar AR, VR y tecnologías en la nube, que juntas nos permiten crear prácticas innovadoras utilizando la realidad mixta.
Empleos en Havok:- Trabajarás en pequeños equipos con desarrolladores talentosos.
- Tendrá la oportunidad de trabajar con nuevas tecnologías en una variedad de plataformas y dispositivos de hardware.
- Trabajará para resolver problemas técnicos complejos con grandes perspectivas
- Colaborarás con equipos geniales de todo el mundo.
Responsabilidades
- Diseñe, desarrolle y pruebe código C ++ multiplataforma de alta calidad, eficiente y limpio
- Desarrolle servicios de Azure bien escalables
- Trabajar directamente con clientes internos y externos para estimular el desarrollo de productos.
Calificaciones
- Programación en C ++ y habilidades de depuración
- Capacidad para trabajar en equipo con un código común.
- Experiencia con tecnologías de servicios distribuidos y en la nube (por ejemplo, Azure Batch, Azure Blob Storage, Docker, Telemetry)
Será un plus
- C #, ASP.Net, JavaScript, TypeScript, React
- Unity, Unreal o motores de juegos relacionados
- Experimente 3D interactivo, AR o VR
- Servicios de red y servidor
- Optimización del rendimiento
Puede obtener más información y enviar su solicitud
aquí o a través de
LinkedIn .