Boa tarde, querido leitor!
Este artigo é o segundo de uma série de artigos abstratos que escreverei ao ler o best-seller de Scott Meyers, Effective and Modern c ++. Cada um desses artigos terá um diretório separado em um projeto especialmente instituído no github.com com exemplos ao vivo do uso do que estamos lendo hoje.
Este artigo complementa as regras de inferência de tipo do artigo anterior e discute certos aspectos da inferência de tipo de modelo para argumentos que são uma matriz e uma função.
Inferência de tipo de padrão para matriz
O compilador c ++ tem uma propriedade que uma matriz declarada sempre, quando passada para uma função de modelo com um parâmetro declarado não como um link, é sempre convertida em um ponteiro para o tipo armazenado e vice-versa, se o parâmetro for declarado como um link, essa conversão não será realizada.
Funções do modelo:
Para começar, darei o código das funções de modelo que deduzem os tipos cobiçados e, em seguida, o processo de derivação:
template<typename T> void paramDeductInfo(T param, const char *initType) { std::cout << initType << " -> (T param) -> " << type_id_with_cvr<T>().pretty_name() << std::endl; }; template<typename T> void refParamDeductInfo(T ¶m, const char *initType) { std::cout << initType << " -> (T ¶m) -> " << type_id_with_cvr<T>().pretty_name() << std::endl; };
Inferência de tipo:
cli::printCaption("TYPE DEDUCTION FOR ARRAY OF CHAR"); char charSeq[] = "Hi everyone!"; paramDeductInfo(charSeq, "char []"); refParamDeductInfo(charSeq, "char []"); cli::printCaption("TYPE DEDUCTION FOR ARRAY OF INT"); int intSeq[] = {1, 2, 3}; paramDeductInfo(intSeq, "int []"); refParamDeductInfo(intSeq, "int []"); cli::printCaption("TYPE DEDUCTION FOR ARRAY OF CLASS A"); class A { } const classASeq[] = {A(), A(), A()}; paramDeductInfo(classASeq, "class A[]"); refParamDeductInfo(classASeq, "class A[]");
O pseudocódigo a seguir reflete a saída para o console destas instruções:
************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF CHAR ************************************************************************************************************************ char [] -> (T param) -> char* char [] -> (T ¶m) -> char [13] ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF INT ************************************************************************************************************************ int [] -> (T param) -> int* int [] -> (T ¶m) -> int [3] ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF CLASS A ************************************************************************************************************************ class A[] -> (T param) -> main::A const* class A[] -> (T ¶m) -> main::A const [3]
Exemplo 1 - analisando o comprimento de uma matriz de tempo de compilação
Além disso, o tipo de saída da matriz armazena informações sobre seu tamanho, que podem ser usadas em uma função de modelo para manipular o tamanho da matriz durante a compilação ou gerar código mais eficiente.
Eu usei esse recurso na função printCaption para limitar o comprimento do cabeçalho exibido na linha de comando no tempo de compilação. Um pouco, mas legal.
namespace cli { template<typename T, std::size_t N> constexpr void printCaption(T (&capValue)[N]) { static_assert(N <= 121, "caption length should be less than 120"); std::cout << std::endl << "*******************************************************************************" << std::endl << capValue << std::endl << "*******************************************************************************" << std::endl << std::endl; }; }
Vamos verificar se haverá um erro se introduzirmos um cabeçalho obviamente inapropriado.
cli::printCaption("123456789 123456789 123456789 123456789 123456789 123456789 123456789" "123456789 123456789 123456789 123456789 123456789 !");
E aqui está você, por favor, bem, não é maravilhoso?
/...sources/cli.h:12:3: error: static assertion failed: caption length should be less than 120 static_assert(N <= 121, "caption length should be less than 120"); ^~~~~~~~~~~~~
Exemplo 2 - foreach em uma matriz na memória
Eu acho que aqui está outra abordagem que pode parecer útil se tivermos um tamanho de matriz em tempo de compilação, por que não usá-la para organizar um loop em tal matriz?
template<typename T, size_t N, typename F> void forEachOnAnArray(T (&inmemArray)[N], F &callback) { for (int i = 0; i < N; ++i) callback(inmemArray[i]); };
O uso desta função é o seguinte:
auto printInt = [](int value) { std::cout << " " << value; }; forEachOnAnArray(intSeq, printInt);
Em geral, o uso desse recurso não se limita a retirar o tamanho da matriz.
Inferência de tipo para uma função
Falando em inferência de tipo para a função Meyers é conciso. Ele menciona exatamente que eles são reduzidos a um ponteiro da mesma maneira que para matrizes, exceto quando o parâmetro da função de modelo pelo qual nosso tipo de função deve ser exibido não é declarado como um link.
Ele provavelmente deveria ter falado sobre algum tipo de wrapper de modelo para funções, mas acho que vai além da questão do c ++ eficiente e moderno.
Nós, meu caro leitor, definitivamente voltaremos a esta questão!
Obrigado e tenha um bom dia !!