2011-10-04 9 views
7

Deseo escribir una estructura de plantilla foo de modo que foo<N>::value_type sea el entero de mayor tamaño (redondeando) a N. Por ejemplo, foo<32>::value_type => uint32_t, foo<33>::value_type => uint64_t y foo<72>::value_type => uint64_t.Especialización de plantilla para un rango de valores

Para hacer esto necesito un medio elegante de proporcionar especializaciones parciales de foo para un rango de valores, por ejemplo, 1 <= N <= 8 para devolver uint8_t, y así sucesivamente. ¿Hay alguna forma de lograr esto sin tener que especializar todo de 0 a 64.

+0

No habrá una manera directa (como dijo Mark), pero tal vez algún truco inteligente de metaprogramación de plantillas. Buena pregunta, esperando ver las respuestas. –

Respuesta

14
template<size_t N> struct select { typedef uint64_t result; }; 
template<> struct select<0> { typedef uint8_t result; }; 
template<> struct select<1> { typedef uint16_t result; }; 
template<> struct select<2> { typedef uint32_t result; }; 

template<size_t N> 
struct foo 
{ 
    enum{D = (N > 32 ? 3 : (N > 16 ? 2 : (N > 8 ? 1 : 0)))}; 

    typedef typename select<D>::result value_type; 

    value_type value; 
}; 

En puede utilizar std::conditional:

typedef 
    typename std::conditional<(N > 32), uint64_t, 
    typename std::conditional<(N > 16), uint32_t, 
    typename std::conditional<(N > 8), uint16_t, uint8_t> 
    ::type>::type>::type value_type; 

Puede decidir cuál es el menos legible.

+1

Me encanta que se demuestre lo contrario. –

+2

Gran respuesta. ¿No debería el enum ser 'enum {D = (N> 32? 3: (N> 16? 2: (N> 8? 1: 0)))};', ¿no? Aquí está funcionando: http://ideone.com/OgXaz – filipe

+0

¡Oh vaya, ya he hecho esto en el pasado, pero esto es _much_ más simple que mi versión! Aunque el mío tenía bool (1), char (2-8), ..., long long (33-64) y void (65+) –

1

Los parámetros de la plantilla deben ser concretos, por lo que no creo que haya forma de evitar especializarse para cada valor requerido.

7

respuesta @hansmaad es una respuesta agradable, pero yo preferiría usar (adivinar qué ?!) Boost:

boost::uint_t<N>::least // N: bits 

El, el tipo más pequeño incorporado, sin signo integral con al menos N bits . El parámetro debe ser un número positivo. Se genera un error de tiempo de compilación si el parámetro es mayor que el número de bits en el tipo entero más grande .

+0

Muy lindo, más aún cuando estoy usando boost en mi proyecto, pero no maneja el caso de foo <72> :: value_type que se resuelve en el entero más grande disponible. –

Cuestiones relacionadas