2. Basado en Meyers "C ++ efectivo y moderno" - detalles de inferencia de tipo de plantilla para matrices

Buenas tardes, querido lector!


Este artículo es el segundo de una serie de artículos abstractos que escribiré mientras leo el libro más vendido de Scott Meyers, Effective and Modern c ++. Cada uno de estos artículos tendrá un directorio separado en un proyecto especialmente instituido en github.com con ejemplos en vivo del uso de lo que estamos leyendo hoy.


Este artículo complementa las reglas de inferencia de tipos del artículo anterior y analiza ciertos aspectos de la inferencia de tipos de plantilla para argumentos que son una matriz y una función.


Inferencia de tipo de patrón para matriz


El compilador de c ++ tiene una propiedad tal que una matriz declarada siempre, cuando se pasa a una función de plantilla con un parámetro declarado no como un enlace, siempre se convierte en un puntero al tipo almacenado y viceversa, si el parámetro se declara como un enlace, entonces dicha conversión no se realiza.


Funciones de plantilla:


Para empezar, daré el código de funciones de plantilla que deducen los tipos codiciados, y luego el proceso de derivación en sí:


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 &param, const char *initType) { std::cout << initType << " -> (T &param) -> " << type_id_with_cvr<T>().pretty_name() << std::endl; }; 

Inferencia 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[]"); 

El siguiente pseudocódigo refleja la salida a la consola de estas instrucciones:


 ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF CHAR ************************************************************************************************************************ char [] -> (T param) -> char* char [] -> (T &param) -> char [13] ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF INT ************************************************************************************************************************ int [] -> (T param) -> int* int [] -> (T &param) -> int [3] ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF CLASS A ************************************************************************************************************************ class A[] -> (T param) -> main::A const* class A[] -> (T &param) -> main::A const [3] 

Ejemplo 1: análisis de la longitud de una matriz de tiempo de compilación


Además, el tipo de salida de la matriz almacena información sobre su tamaño, que se puede usar en una función de plantilla para manipular el tamaño de la matriz durante la compilación o generar un código más eficiente.


Utilicé esta función en la función printCaption para limitar la longitud del encabezado que se muestra en la línea de comandos en el momento de la compilación. Un poco, pero agradable.


 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; }; } 

Verifiquemos si habrá un error si introducimos un encabezado obviamente inapropiado.


 cli::printCaption("123456789 123456789 123456789 123456789 123456789 123456789 123456789" "123456789 123456789 123456789 123456789 123456789 !"); 

Y aquí estás, por favor, ¿no es maravilloso?


 /...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"); ^~~~~~~~~~~~~ 

Ejemplo 2 - foreach en una matriz en memoria


Creo que aquí hay otro enfoque que puede parecer útil si tenemos un tamaño de matriz en tiempo de compilación, ¿por qué no usarlo para organizar un bucle en dicha 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]); }; 

El uso de esta función es el siguiente:


  auto printInt = [](int value) { std::cout << " " << value; }; forEachOnAnArray(intSeq, printInt); 

En general, el uso de esta función no se limita a extraer el tamaño de la matriz.


Inferencia de tipo para una función


Hablar de inferencia de tipos para la función Meyers es conciso. Menciona exactamente que se reducen a un puntero de la misma manera que para las matrices, excepto cuando el parámetro de la función de plantilla mediante la cual se muestra nuestro tipo de función no se declara como un enlace.


Probablemente debería haber hablado sobre algún tipo de envoltorios de plantillas para funciones, pero supongo que eso va más allá de la cuestión de c ++ eficiente y moderno.


¡Nosotros, mi querido lector, definitivamente volveremos a este tema!


Gracias y que tengas un buen día !!

Source: https://habr.com/ru/post/es415347/


All Articles