Novedades del blog - Octubre de 2020

Durante los últimos tres meses, el blog ha visto modificado su diseño general, adoptando un estilo de presentación más homogéneo y minimalista.

Asimismo, se han revisado numerosas entradas --particularmente las correspondientes al período 2015-2018-- con el fin de remaquetar sus códigos. La práctica totalidad de los artículos se encuentra ahora adaptada a las técnicas de programación propias de C++17 y/o C++20, empleando de forma consistente el estilo always auto.

Por supuesto, los posts seguirán siendo sometidos a revisiones periódicas con el objetivo de mejorar sus contenidos y corregir posibles erratas.

Programando con C++20 (Parte II): Lambdas 'templatizadas'

Artículos de la serie:
  1. Concepts
  2. Lambdas 'templatizadas'


Introducción


En C++20, las expresiones lambda genéricas pueden adoptar una sintaxis análoga a la de las plantillas de función (function templates) tradicionales [1]:
   [capture_list] <template_parameter_list>(optional C++20)  (parameters)(optional)    mutable-constexpr-consteval(optional)  noexcept(optional)       -> return_type(optional)       requires(optional C++20)    { body }

En la especificación general anterior, template_parameter_list es una lista no vacía de parámetros de plantilla --expresada entre llaves angulares-- que podemos emplear de forma opcional para dotar de nombres específicos a los parámetros de una expresión lambda genérica. Su inclusión vendrá acompañada típicamente por el uso de conceptos que impongan ligaduras sobre los tipos (cláusula requires).

Gracias a esta sintaxis, podemos requerir, por ejemplo, que varios argumentos de una lambda sean del mismo tipo genérico (en el código inferior, el tipo I se encuentra restringido por el concepto std::input_iterator):

   auto f = []<std::input_iterator I>(I first, I last) { /* ... */ };

Como ejemplo adicional, la siguiente lambda genérica opera únicamente con contenedores de tipo std::array:

   auto g = []<typename T, std::size_t N>(std::array<T, N>& m) { /* ... */ };

Referencias de reenvío y auto&&

Artículos de la serie:

Reglas de deducción de tipos


Dada una plantilla de función, una referencia de reenvío es una referencia rvalue a uno de los parámetros de la plantilla. Dicha referencia debe carecer, además, de calificadores const-volatile. A modo de ejemplo, consideremos la plantilla de función f siguiente:

template<typename T> void f(T&& t); // referencia de reenvío en la lista de parámetros de la función

Programando con C++20 (Parte I): Concepts

Artículos de la serie:

Introducción

En este post consideraremos el problema de codificar el bien conocido algoritmo de ordenación por inserción mediante técnicas propias de programación genérica, de manera que éste pueda ser empleado con contenedores diversos. Analizaremos su implementación a la luz de la inclusión de conceptos (concepts), rangos y proyecciones en el estándar del lenguaje C++20 [1-4].

Un concepto es un predicado con nombre, evaluado en tiempo de compilación, que forma parte de la interfaz de una plantilla de clase o de función (template) y restringe el tipo de datos con los que ésta puede operar. La detección temprana de cualquier incumplimiento de tales restricciones, durante los primeros pasos en la generación de una instancia de la plantilla, conducirá por lo general a mensajes de error de fácil comprensión y rastreo. Más que meras ligaduras sintácticas, el objetivo es aquí el de modelar auténticas categorías semánticas que puedan ser reutilizadas por el programador.