Na última vez , usamos o SFINAE para descobrir se um tipo tem uma definição e o usamos em combinação com
if constexpr
e expressões lambda genéricas, para que o código possa usar o tipo se for definido, enquanto ainda estiver sendo aceito pelo compilador (e descartado) se o tipo não estiver definido.
No entanto, existem vários problemas com este aplicativo:
- Toda vez que você precisa escrever uma
struct
. - Se o tipo não existir, quando você o nomear, esse tipo será inserido no espaço para nome atual e não no espaço para nome em que você deseja que o tipo seja.
- Você precisa usar uma
struct
com um nome não qualificado. Você não pode usá-lo para verificar um tipo que não importou para o espaço para nome atual.
Podemos resolver todos os três problemas com uma solução: primeiro declare o tipo no espaço para nome desejado.

Depois de fazer isso, você não precisa escrever uma
struct
porque a estrutura foi declarada. Usá-lo como um parâmetro do tipo de modelo em
call_if_defined
não levará à criação de uma nova declaração, pois tudo já foi declarado. E desde que ela foi declarada, você pode acessá-la através do nome não qualificado, do nome completo do espaço para nome ou de qualquer outro meio. Também através de um alias de tipo ou de um tipo dependente (infelizmente, eles não estão entre).
namespace app { void foo() { call_if_defined<awesome::special>([&](auto* p) {
Quem acompanha essa série de artigos desde o início pode ter notado que o método
call_if_defined
não corresponde exatamente à versão que escrevemos anteriormente. A nova versão suporta vários parâmetros de tipo e chama um lambda apenas se todos os tipos estiverem definidos.
Vamos dar uma olhada:
template<typename... T, typename TLambda> void call_if_defined(TLambda&& lambda) { if constexpr ((... && is_complete_type_v<T>)) { lambda(static_cast<T*>(nullptr)...); } }
Os colchetes duplos em se constexpr ((...)) parecem estranhos, mas são necessários. Parênteses externos são requeridos pela
if constexpr
e parênteses internos são requeridos
por uma expressão de convolução . A expressão de convolução se expande para
if constexpr ( (is_complete_type_v<T1> && is_complete_type_v<T2> && ... is_complete_type_v<Tn>))
A chamada lambda usa a
extensão do pacote de parâmetros :
lambda(static_cast<T*>(nullptr)...);
Expande para
lambda(static_cast<T1*>(nullptr), static_cast<T2*>(nullptr), ..., static_cast<Tn*>(nullptr));
onde
static_cast<T*>(nullptr)
repetido uma vez para cada tipo.
Como observei anteriormente, podemos usar esta função para chamar o lambda se todos os tipos estiverem 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); }); }
O C ++ 20 permite que você escreva assim:
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 permite nomear o tipo do modelo, eliminando assim a necessidade de extraí-lo novamente ao jogar com
std::decay_t
.
No próximo artigo, usaremos isso como um trampolim e estenderemos o circuito.
Nota : esta é a quarta parte da série principal de artigos, mas ainda existem outras partes (
1 ,
2 ,
3 ,
5 ). Para os impacientes: eis o que você precisa para copiar e colar:
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)...); } }
By the way, temos um trabalho legal
Por mais de uma década, a
Havok está na vanguarda da inovação no desenvolvimento de jogos e em 3D interativo. Como parte da Cognition, a equipe HoloLens, agora estamos combinando esse conhecimento e o poder da nuvem do Azure para desenvolver muitos novos serviços emocionantes de realidade mista. Entre eles está o serviço de renderização remota do Azure anunciado recentemente. Somos apaixonados pela combinação de tecnologias de RA, VR e nuvem, que juntas nos permitem criar práticas inovadoras usando realidade mista.
Trabalhos na Havok:- Você trabalhará em pequenas equipes com desenvolvedores talentosos
- Você terá a oportunidade de trabalhar com novas tecnologias em uma variedade de plataformas e dispositivos de hardware.
- Você trabalhará na solução de problemas técnicos complexos com grandes perspectivas
- Você colaborará com equipes legais em todo o mundo.
Responsabilidades
- Projete, desenvolva e teste código C ++ multiplataforma eficiente, limpo e de alta qualidade
- Desenvolver serviços do Azure bem escalonáveis
- Trabalhe diretamente com clientes internos e externos para estimular o desenvolvimento de produtos
Qualificações
- Habilidades de programação e depuração em C ++
- Capacidade de trabalhar em equipe com um código comum
- Experiência com nuvem e tecnologias de serviço distribuído (por exemplo, Lote do Azure, Armazenamento de Blob do Azure, Docker, Telemetria)
Será um plus
- C #, ASP.Net, JavaScript, TypeScript, React
- Unity, motores de jogo irreais ou relacionados
- Experimente 3D interativo, AR ou VR
- Serviços de rede e servidor
- Otimização de desempenho
Você pode saber mais e enviar sua inscrição
aqui ou através do
LinkedIn .