¿Cómo obtengo un int con un ancho máximo / mínimo?
Me gustaría obtener un int
con un tamaño específico para propósitos de vectorización. Algo como int_atleast < 3 /*bytes*/ >
debería dar como resultado int32_t
, y int_atmost < 5 >
debería dar el mismo resultado int32_t
. Intenté implementar esto con especialización de plantillas, pero me encontré con un obstáculo porque tendría que especializar cada argumento posible. Pensé en la recursión, pero parece una solución demasiado complicada para algo que probablemente ya esté en el estándar. ¿Qué debo hacer?
davy.ai
Una posible solución a este problema es utilizar el tipo trait
std::conditional
proporcionado por la biblioteca estándar. Aquí está una implementación de ejemplo:“`c++
#include
template::type>::type>::type>::type;
struct int_atleast
{
using type = typename std::conditional
};
template= 8, = 4, = 2, = 1,
struct int_atmost
{
using type = typename std::conditional
long long, typename std::conditional
int, typename std::conditional
short, typename std::conditional
char, void>::type>::type>::type>::type;
};
// Ejemplo de uso:
#include
#include
int main()
{
std::vector<int_atleast<3>::type> vec(5); // vec es std::vector
std::cout << sizeof(vec[0]) << std::endl; // imprime 4
}
“`
Las plantillas
int_atleast
eint_atmost
se definen como estructuras. Tienen un único argumento de plantilla, que es el ancho deseado del tipo entero en bytes. El aliastype
dentro de cada estructura se define utilizandostd::conditional
, lo que nos permite elegir entre dos tipos basados en una condición.En la plantilla
int_atleast
, comenzamos verificando si el ancho deseado es menor o igual a 1 byte. Si lo es, elegimoschar
como tipo entero. De lo contrario, pasamos a la siguiente condición, que verifica si el ancho es menor o igual a 2 bytes, y así sucesivamente. Finalmente, si ninguna de las condiciones coincide, elegimosvoid
como tipo entero, lo que causará un error de compilación si la plantilla se instancia con un ancho no admitido.La plantilla
int_atmost
funciona de manera similar, pero en sentido contrario. Comenzamos verificando si el ancho deseado es mayor o igual que 8 bytes. Si lo es, elegimoslong long
como tipo entero. De lo contrario, pasamos a la siguiente condición, que verifica si el ancho es mayor o igual a 4 bytes, y así sucesivamente. Finalmente, si ninguna de las condiciones coincide, elegimosvoid
nuevamente.En la función
main
, demostramos el uso de las plantillasint_atleast
eint_atmost
creando dos vectores, uno con un ancho mínimo de 3 bytes y otro con un ancho máximo de 5 bytes. Usamos el operadorsizeof
para imprimir el tamaño de los elementos en cada vector, que debería ser4
, ya que ambas plantillas eligenint32_t
en este caso.Tenga en cuenta que esta implementación solo admite anchos de enteros que sean potencias de 2. Si necesita admitir anchos de bytes arbitrarios, podría modificar las plantillas para utilizar una búsqueda logarítmica en lugar de una búsqueda lineal, pero esto haría que el código fuera más complicado.</int_atmost<5></int_atleast<3>