# C++17

C++17 fue una versión del estándar del lenguaje de programación C++. La especificación final de C++17 fue aprobada por el comité de estandarización de C++ (WG21) de la Organización Internacional de Normalización (ISO) el 6 de septiembre de 2017 y fue publicada oficialmente como la norma ISO/IEC 14882:2017 en diciembre del mismo año. C++17 reemplazó a la anterior especificación C++14 publicada en el año 2014. El nombre sigue la tradición de denominar a las versiones del lenguaje C++ a partir de la fecha de publicación de la especificación. Antes de conocerse la fecha exacta de su publicación, el borrador del estándar era informalmente conocido como C++1z para distinguirlo de C++11 (C++1x) y C++14 (C++1y). La próxima revisión de ésta especificación se denominará C++20.

## Nuevas características

Las nuevas características que presentó en aquel entonces fueron estas.

### Variables en línea

Permite la definición de variables en archivos de cabecera. El compilador elige donde se instancia la variable.
El especificador inline puede ser aplicado tanto a funciones como variables. Una variable declarada inline tiene la misma semántica que una función declarada inline: puede ser definida, de forma idéntica, en múltiples unidades de traducción (esto es, un archivo .c/.cpp una vez que todos los archivos de cabecera han sido incluidos), y ha de ser definida en cada una de esas unidades de traducción donde va a ser usada.
El comportamiento del programa es como si hubiese exactamente una variable.
En C++14, aunque había soporte para usar variables estáticas en plantillas de clase, no había modo conveniente de hacerlo. Por tanto, uno debía recurrir a trucos como este:
Y desde C++17, podemos hacer en un archivo de encabezado:

### Nuevas reglas para la deducción auto desde la lista de inicialización arriostrada

Para la inicialización de copia de lista, la deducción auto deducirá un std::initializer_list (si los tipos de entradas en la lista de inicialización arriostrada son todos idénticos) o de lo contrario estará mal constituida.
Para la inicialización de listas directa:
* Para una lista de inicialización arriostrada con un solo elemento, la deducción automática deducirá a partir de esa entrada.
* Para una lista de inicialización arriostrada con más de un elemento, la deducción automática se constituirá de forma errónea.
Las reglas para los for basados en rango no serán afectadas por los cambios propuestos aquí, ya que las reglas para la inicialización de copia de lista no se han modificado.

### Enlaces Estructurados

Enlaza los nombres especificados a subobjetos o elementos del inicializador.
Como una referencia, un enlace estructurado es un alias a un objeto existente. Sin embargo, y al contrario que en una referencia, el tipo del enlace estructurado no tiene que ser un tipo referencia.
La declaración de un enlace estructurado introduce todos los identificadores en la lista de identificadores como nombres del scope circundante y los enlaza a subobjetos o elementos del objeto denotado por expresión. Los enlaces de este tipo son llamados enlaces estructurados. Lo que permite expresiones como:

### std::invoke

Invoca cualquier llamable (puntero de función, función, puntero miembro) con una única sintaxis. Viene del concepto del estándar INVOKE.
Como ejemplo, considera el deref_fn wrapper, que debería aceptar cualquier objeto llamable f y retornar un functor que invoca al llamable proveído y desreferencia el resultado.
Usando C++14, podría implementarse así:
La función invoke propuesta permite una implementación más simple, que no depende del uso de la sobrecarga de función SFINAE:

### Generalización del sistema basado en rango para bucles

El actual sistema basado en rango para bucles es demasiado restrictivo. El iterador end nunca es incrementado, decrementado o desreferenciado. El requerimiento de que sea un iterador no tiene sentido por tanto.
Hoy en día, los algoritmos STL requieren que el begin y end de un rango tengan el mismo tipo. Es algo sensato teniendo en cuenta que los algoritmos toman el begin y el end de un rango como parámetros separados. En la ausencia de comprobación, permitir que sus tipos difieran hace bastante fácil el pasar iteradores que no se correspondan entre ellos. Esto no ocurre con el sistema basado en rango para bucles, puesto que se hace cargo de los rangos de forma completa.
Perder los requerimientos de tipo basados en rango para bucles proporciona a los usuarios de Ranges TS la mejor experiencia posible. Si los usuarios crean rangos con Ranges TS que no son usables con los rangos basados en bucle por defectos, se sentirían frustrados, y no tendrá mucha utilidad. Con toda probabilidad, una solución basada en macro como BOOST_FOREACH será inventada para llenar el hueco.
Por tanto, es un apoyo a centinelas, o iteradores end que no son del mismo tipo que el begin iterator, que ayuda con los bucles terminados en null y parecidos.

### Expresiones plegables

Si necesitas una función suma, que admita un número ilimitado de parámetros, en C++17 se puede hacer de una forma muy simple:

### Definición de espacio de nombres anidados

Permite declarar varios namespaces en una sola sentencia:

### Una biblioteca de sistema de archivos basado en boost::filesystem

Se añade a la librería estándar este namespace con el tipo path y métodos para iterar y operar con directorios:

### Inicializadores if switch

Inicializadores en las sentencias if y switch, ahora permiten evaluar condiciones en inicializadores que no son convertibles a booleanos.

### Clase std::any

Un objeto de la clase any almacena una instancia de cualquier tipo que satisface los requisitos del constructor o que está vacío,. El objeto almacenado es conocido como objeto contenido. Dos estados son equivalentes si ambos están vacíos o si los objetos contenidos son iguales. Las implementaciones de esta clase deben evitar el uso de memoria reservada dinámicamente para el objeto contenido.

### Plantilla de clase std::optional

Representa objetos que pueden o no existir. El uso más común para esto es asignarlo a un valor que devuelve una función que puede fallar. El objeto contenido puede ser inicializado después de que el objeto opcional haya sido inicializado, y puede ser destruido antes de que el objeto opcional lo haya sido. El estado de inicialización del objeto contenido está monitorizado por el objeto opcional.

### Plantilla de clase std::variant

La plantilla de clase std::variant representa un tipo de unión segura. Una instancia de std::variant en cualquier tiempo dado sostiene un valor de los tipos alternativos o, en caso de error, ningún valor. A la variante no se le permite asignar memoria dinámicamente.

### Fallthrough

Permite usar los switches en cascada sin que el compilador emita warning.

## Otras características

* La adición de un mensaje de texto por defecto para static_assert. Ya no es obligatorio especificar el error por defecto que muestra el static_assert.
* La adición de std::string_view, una referencia no propietaria a una secuencia de caracteres o sectores, que es de solo lectura. La plantilla de clase basic_string_view describe un objeto que puede referirse a una sentencia contigua constante de objetos char-like con el primer elemento de la secuencia en la posición 0. Una implementación típica consiste en dos elementos: un puntero a un objeto CharT y un tamaño.
* Eliminación de trígrafos. Pueden seguir siendo usados si son implementados en el código fuente.
* Permite typename en una parámetro de una plantilla.
* std::uncaught_exceptions, como reemplazo de std::uncaught_exception.
* Atributos para espacios de nombres y enumeradores.
* UTF-8 caracteres literales.
* Constante evaluación para todos los argumentos de las plantillas sin tipo.
* Nuevas funciones de inserción para std::map y std::unordered_map.
* Acceso al contenedor Uniforme.
* Definición de "Iteradores contiguos".
* La eliminación de algunos tipos y funciones en desuso como std::auto_ptr, std::random_shuffle o adaptadores de función antiguas.
* Conceptos, proporcionando "especificación y verificación de las restricciones sobre los argumentos de plantilla".
* Sintaxis de llamada unificada.
* std::apply, toma una función o algo que se comporte como tal y una tupla, y desempaqueta la tupla en la llamada.
* Versiones paralelas de algoritmos STL. Con std::execution::par indicamos que queremos que el algoritmo se ejecute en paralelo: std::sort(std::execution::par, first, last);. Los nuevos algoritmos compatibles son: for_each_n, reduce, transform_reduce, exclusive_scan, inclusive_scan, transform_exclusive_scan, transform_inclusive_scan.
* Funciones especiales de matemática adicional.
* La mayoría de las librerías de fundamentos TS I (ejemplos: std::optional, std::any).
* Un tiempo de compilación estático if (condicional) con el formulario if constexpr(expression).
* Algunas extensiones en asignación alineada de memoria.
* Plantilla de deducción de constructores, permitiendo pair(5.0, false) en vez de pair<double,bool>(5.0, false).
* Pequeños cambios a punteros.