Inferência de tipo é a dedução automática do tipo de dado a partir de uma expressão. No caso do C++ moderno a dedução é feita pelo compilador.
Os templates do C++ já possuiam um forma limitada de dedução de tipos, ou seja, você não precisa indicar o tipo de dado explicitamente como demonstrado no exemplo abaixo:
https://gist.github.com/fabiogaluppo/743932759542f8a11d50
Note que ao chamar a função template display, ela não foi parametrizável, pois o mecanismo de templates soube deduzir T a partir do argumento indicado na chamada da função. Porém como indicado anteriormente, a inferência via templates é limitada e não tem a mesma abrangência e usabilidade da inferência de tipos introduzidas no C++ moderno com auto e decltype.
Inferência de tipo com auto
A inferência no C++ é muito simples. Uma vez que você sabe declarar uma variável, basta substituir o tipo da variável pela palavra chave auto. O contéudo a direita da declaração, logo após a inicialização ou atribuição, é uma expressão (variável, chamada de função, ...) que possui um tipo associado. O compilador utilizará a informação para "substituir" e indicar o valor da variável declarada com auto. Abaixo, três variáveis estão declaradas explicitamente com seus tipos e outras três utilizam auto para a dedução do tipo a partir da expressão a direita.
https://gist.github.com/fabiogaluppo/9223837880fbe0c777c5
O problema ou caracteristica da dedução de tipos com auto é que os qualificadores para constante e referência são ignorados, apenas o tipo de dado é absorvido. No exemplo a seguir, a variável y1 não será constante, mas a variável y2 será constante.
https://gist.github.com/fabiogaluppo/361c45bdfcaaff2f914d
Portanto, basta utilizar const e/ou & para qualificar a nova declaração:
https://gist.github.com/fabiogaluppo/659b242782b83ae85726
A inferência de tipo também é uma conveniência para poupar os esforços de digitação ou deixar as declarações menos redundantes, como no caso de um container na forma de dicionário:
https://gist.github.com/fabiogaluppo/812f6453072c97983fed
Inferência de tipo com decltype
Com decltype a utilização é similar ao auto, porém ela preserva as qualificações da expressão. É possível indicar uma expressão completa dentro do parâmetro de decltype.
https://gist.github.com/fabiogaluppo/c717c5a0189f577cdb1c
No entanto, na maioria das vezes seu uso com expressão não é tão conveniente devido a redundância que desejamos evitar. Imagine digitar algo assim:
Isso não parece ser simples.
O C++ 11 vai até aqui, o C++ 14 estende seu mecanismo de inferência de tipo e possui uma combinação dos benefícios de auto e decltype, como veremos a seguir.
Inferência de tipo com decltype(auto) do C++ 14
No C++ 14, decltype(auto) é a inferência de tipo em sua plenitude - além da dedução do tipo ela preservará suas qualificações como constante e/ou referência se este for caso. Abaixo, um exemplo de uso evitando certas redundâncias de notação:
https://gist.github.com/fabiogaluppo/b2a4d68680bd039d445d
Veja a seguinte função que gera uma const std::string aleatória:
https://gist.github.com/fabiogaluppo/f91f41c2bcb7023e64c8
O código acima utiliza inferência com auto em duas ocasiões:
Como se trata de uma função que retornará um valor constante, no consumo desta função, ao usarmos o decltype(auto) para declarar a variável que receberá o resultado desta computação, teremos a seguinte resposta:
https://gist.github.com/fabiogaluppo/5055858a1bd78fb39b35
Como referência, aqui estão as execuções do exemplo deste post compilados com clang++ (7.0.2 (clang-700.1.81)), g++ (g++ (GCC) 5.3.0) e cl (Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x64) respectivamente, todos eles possuem suporte ao C++ 14:



Fontes:
https://github.com/SimplyCpp/examples/blob/master/understanding_inference_program.cpp
Os templates do C++ já possuiam um forma limitada de dedução de tipos, ou seja, você não precisa indicar o tipo de dado explicitamente como demonstrado no exemplo abaixo:
https://gist.github.com/fabiogaluppo/743932759542f8a11d50
Note que ao chamar a função template display, ela não foi parametrizável, pois o mecanismo de templates soube deduzir T a partir do argumento indicado na chamada da função. Porém como indicado anteriormente, a inferência via templates é limitada e não tem a mesma abrangência e usabilidade da inferência de tipos introduzidas no C++ moderno com auto e decltype.
Inferência de tipo com auto
A inferência no C++ é muito simples. Uma vez que você sabe declarar uma variável, basta substituir o tipo da variável pela palavra chave auto. O contéudo a direita da declaração, logo após a inicialização ou atribuição, é uma expressão (variável, chamada de função, ...) que possui um tipo associado. O compilador utilizará a informação para "substituir" e indicar o valor da variável declarada com auto. Abaixo, três variáveis estão declaradas explicitamente com seus tipos e outras três utilizam auto para a dedução do tipo a partir da expressão a direita.
https://gist.github.com/fabiogaluppo/9223837880fbe0c777c5
O problema ou caracteristica da dedução de tipos com auto é que os qualificadores para constante e referência são ignorados, apenas o tipo de dado é absorvido. No exemplo a seguir, a variável y1 não será constante, mas a variável y2 será constante.
https://gist.github.com/fabiogaluppo/361c45bdfcaaff2f914d
Portanto, basta utilizar const e/ou & para qualificar a nova declaração:
https://gist.github.com/fabiogaluppo/659b242782b83ae85726
A inferência de tipo também é uma conveniência para poupar os esforços de digitação ou deixar as declarações menos redundantes, como no caso de um container na forma de dicionário:
https://gist.github.com/fabiogaluppo/812f6453072c97983fed
Inferência de tipo com decltype
Com decltype a utilização é similar ao auto, porém ela preserva as qualificações da expressão. É possível indicar uma expressão completa dentro do parâmetro de decltype.
https://gist.github.com/fabiogaluppo/c717c5a0189f577cdb1c
No entanto, na maioria das vezes seu uso com expressão não é tão conveniente devido a redundância que desejamos evitar. Imagine digitar algo assim:
decltype(e + e + e + e + e) a3 = (e + e + e + e + e);
Isso não parece ser simples.
O C++ 11 vai até aqui, o C++ 14 estende seu mecanismo de inferência de tipo e possui uma combinação dos benefícios de auto e decltype, como veremos a seguir.
Inferência de tipo com decltype(auto) do C++ 14
No C++ 14, decltype(auto) é a inferência de tipo em sua plenitude - além da dedução do tipo ela preservará suas qualificações como constante e/ou referência se este for caso. Abaixo, um exemplo de uso evitando certas redundâncias de notação:
https://gist.github.com/fabiogaluppo/b2a4d68680bd039d445d
Veja a seguinte função que gera uma const std::string aleatória:
https://gist.github.com/fabiogaluppo/f91f41c2bcb7023e64c8
O código acima utiliza inferência com auto em duas ocasiões:
- No linha 8, onde o bind retornará um functor baseado no objeto do tipo função (outro functor) da distribuição informada no primeiro argumento;
- Na linha 11, como uma referência de char, para que seja possível a atribuição na próxima sequência.
Como se trata de uma função que retornará um valor constante, no consumo desta função, ao usarmos o decltype(auto) para declarar a variável que receberá o resultado desta computação, teremos a seguinte resposta:
https://gist.github.com/fabiogaluppo/5055858a1bd78fb39b35
Como referência, aqui estão as execuções do exemplo deste post compilados com clang++ (7.0.2 (clang-700.1.81)), g++ (g++ (GCC) 5.3.0) e cl (Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x64) respectivamente, todos eles possuem suporte ao C++ 14:



Fontes:
https://github.com/SimplyCpp/examples/blob/master/understanding_inference_program.cpp
Comentários
Postar um comentário