HOWTO · C++
El value_type en contenedores STL en C++
STL es una abreviatura de la biblioteca de plantillas estándar. Es un conjunto de estructuras de datos y algoritmos utilizados para implementar contenedores genéricos y funciones para el lenguaje de programación C++.
En esta página
El value_type de un contenedor STL es un alias de tipo para el tipo de elemento que almacena. En std::vector<int>, ese tipo es int; en un contenedor asociativo como std::map<std::string, int>, es un par de clave y valor. Puedes nombrar este alias a través del tipo del contenedor y usarlo en código genérico cuando el tipo del contenedor es un parámetro de plantilla.
Qué significa value_type
Los contenedores definen value_type para indicar el tipo de cada elemento de su secuencia o colección. Por ejemplo, std::vector<int>::value_type es int, mientras que el tipo de elemento de un mapa es un par que contiene su clave y el valor asociado. En std::map<std::string, int>, ese elemento es un std::pair: el primer miembro es la clave y el segundo, el valor asociado. La clave es constante en el par almacenado para que el orden del mapa siga siendo válido. Este alias permite que el código que trabaja con un contenedor se refiera al tipo de sus elementos sin tener que escribir ese tipo por separado. Describe un elemento almacenado, no el objeto contenedor: los elementos de un vector de enteros son de tipo int, mientras que el vector tiene un tipo de contenedor distinto.
Cómo acceder al value_type de un contenedor
Usa el tipo del contenedor antes del operador de ámbito: std::vector<int>::value_type. Como se trata de un nombre de tipo, myVector::value_type no es válido si myVector es un objeto. Si quieres asignar un nombre local al tipo de los elementos, escribe using Element = std::vector<int>::value_type;. La forma Container::value_type también se usa cuando Container es un parámetro de plantilla; como es un nombre de tipo dependiente, C++ exige anteponer typename. A partir de la declaración de la plantilla, el compilador no puede saber si un nombre dependiente se refiere a un tipo o a un valor, así que typename hace explícita esa interpretación. En el código ordinario, cuando el tipo del contenedor ya es concreto, como en std::vector<int>::value_type, el compilador puede identificar directamente el tipo anidado y no hace falta esa desambiguación.
Cómo usar value_type en código genérico
Una función genérica puede usar typename Container::value_type para nombrar el tipo de los elementos y aceptar distintos contenedores. Este ejemplo imprime cada elemento de un vector y una lista:
Ejecuta este ejemplo:
#include <iostream>
#include <list>
#include <string>
#include <vector>
template <typename Container>
void printElements(const Container& container) {
for (const typename Container::value_type& element : container) {
std::cout << element << '\n';
}
}
int main() {
const std::vector<int> numbers{1, 2, 3};
const std::list<std::string> colors{"red", "blue"};
printElements(numbers);
printElements(colors);
}
La salida observada es:
1
2
3
red
blue
En la función, Container se deduce a partir del argumento, por lo que el mismo cuerpo funciona tanto con std::vector<int> como con std::list<std::string>. Container::value_type depende de ese parámetro de plantilla; por eso la declaración lleva typename. El bucle accede a cada elemento mediante una referencia constante: puede leerlo sin copiarlo y no puede modificar el elemento del contenedor a través de esa referencia. Este patrón resulta útil cuando una función necesita nombrar un tipo de elemento para una variable local, un parámetro o un tipo de retorno, sin depender de un contenedor específico. Aun así, el contenedor debe admitir las operaciones que usa la función; aquí, el requisito compartido es permitir la iteración basada en rangos. El ejemplo imprime 1, 2, 3, red y blue; los nombres de colores aparecen tal como están en el ejemplo sin cambios.
Qué no hace value_type
value_type nombra un tipo de elemento; no asigna ni libera memoria. El contenedor y su asignador gestionan el almacenamiento según sus propias reglas. El alias tampoco hace que un contenedor sea siempre más rápido o seguro que otro. En este caso, su utilidad práctica es permitir que el código genérico nombre el tipo de elemento que proporciona cada contenedor, incluidos los tipos definidos por el usuario. Que un contenedor tenga value_type no garantiza que todos esos contenedores ofrezcan la misma interfaz: el código debe limitarse a las operaciones admitidas por los contenedores que acepta. Elige un contenedor según las operaciones necesarias y sus características de rendimiento; después, usa su alias cuando el tipo de los elementos deba depender de esa elección. En resumen, value_type indica al código genérico qué tipo tiene un elemento, pero no determina cómo almacena o gestiona esos elementos el contenedor.