2011-06-19 12 views
7

¿Cómo puedo obtener el nombre del tipo más grande disponible en mi compilador? ¿Es posible?
Algo así como:Obtener el tipo más grande disponible

auto largest = get_largest_type(); 

y concesionarios en mi caso sería mucho, mucho.

+1

¿te refieres al tipo primitivo más grande? ¿Qué pasa con 'int [100000]'? Es un tipo bastante grande, ¿eso cuenta?Y, por supuesto, ¿para qué es esto? – jalf

+0

@jalf sí, me refería al tipo primitivo más grande disponible – smallB

Respuesta

4

Bueno, dependiendo de lo mal que necesita esto, se puede probar algunos metaprograming serio aquí ...

En primer lugar, es obvio que se necesita algún tipo de "paquete" que define todos los tipos primitivos disponibles, así que aquí está :

template<typename... TYPES> 
class pack 
{}; 

typedef pack<float, double, long double, unsigned short, unsigned int, 
    unsigned long, unsigned long long, short, int, long, long long> primitive_types; 

entonces necesitará una manera de ordenar este tipo en cuanto al tamaño, por lo que en primer lugar, vamos a definir una metafunción capaz de implementar un ordenamiento débil stric para los tamaños:

template<typename L, typename R> 
class smaller 
{ 
    public: 
     static const bool value = sizeof(L) < sizeof(R); 
}; 

Ahora, el algoritmo de clasificación. Aquí he escogido arbitrariamente sort sort, que requiere 3 otras metafunciones: pack_cat para concatenar paquetes, fusionar para fusionarlos según el orden y dividir a la mitad para romper paquetes en otros 2 paquetes.

template<typename, typename> 
class pack_cat; 

template<typename... L, typename... R> 
class pack_cat<pack<L...>, pack<R...>> 
{ 
    public: 
     typedef pack<L..., R...> type; 
}; 

template<template<typename, typename> class, typename, typename> 
class pack_merge; 

template<template<typename, typename> class MF, typename HL, typename... TL, typename HR, typename... TR> 
class pack_merge<MF, pack<HL, TL...>, pack<HR, TR...>> 
{ 
    public: 
     typedef typename std::conditional<MF<HR, HL>::value, 
       typename pack_cat<pack<HR>, typename pack_merge<MF, pack<HL, TL...>, pack<TR...>>::type>::type, 
       typename pack_cat<pack<HL>, typename pack_merge<MF, pack<TL...>, pack<HR, TR...>>::type>::type>::type type; 
}; 

template<template<typename, typename> class MF, typename H, typename... T> 
class pack_merge<MF, pack<H, T...>, pack<>> 
{ 
    public: 
     typedef pack<H, T...> type; 
}; 

template<template<typename, typename> class MF, typename... R> 
class pack_merge<MF, pack<>, pack<R...>> 
{ 
    public: 
     typedef pack<R...> type; 
}; 

template<typename> 
class halve; 

template<typename A, typename B, typename... T> 
class halve<pack<A, B, T...>> 
{ 
    public: 
     typedef typename pack_cat<pack<A>, typename halve<pack<T...>>::L>::type L; 
     typedef typename pack_cat<pack<B>, typename halve<pack<T...>>::R>::type R; 
}; 

template<typename T> 
class halve<pack<T>> 
{ 
    public: 
     typedef pack<T> L; 
     typedef pack<> R; 
}; 

template<> 
class halve<pack<>> 
{ 
    public: 
     typedef pack<> L; 
     typedef pack<> R; 
}; 

template<template<typename, typename> class MF, typename P> 
class pack_sort 
{ 
    private: 
     typedef typename halve<P>::L L; 
     typedef typename halve<P>::R R; 

    public: 
     typedef typename pack_merge<MF, typename pack_sort<MF, L>::type, typename pack_sort<MF, R>::type>::type type; 
}; 

template<template<typename, typename> class MF, typename H> 
class pack_sort<MF, pack<H>> 
{ 
    public: 
     typedef pack<H> type; 
}; 

template<template<typename, typename> class MF> 
class pack_sort<MF, pack<>> 
{ 
    public: 
     typedef pack<> type; 
}; 

Por último se necesita un metafunción para recuperar el último argumento de un paquete, que es fácil de implementar:

template<typename> 
class pack_get_last; 

template<typename H, typename... T> 
class pack_get_last<pack<H, T...>> 
{ 
    public: 
     typedef typename pack_get_last<pack<T...>>::type type; 

}; 

template<typename H> 
class pack_get_last<pack<H>> 
{ 
    public: 
     typedef H type; 
}; 

Ahora, un programa de prueba para demostrar que que todo este código basura que escribió allí realmente funciona:

#include <iostream> 
#include <utility> 

/* all those metafunctions come here */ 

int main() 
{ 
    typename pack_get_last<typename pack_sort<smaller, primitive_types>::type>::type largest; 

    if(std::is_same<decltype(largest), long double>::value) 
     std::cout << "MATCH!\n"; 
} 

de salida en una máquina x64 Linux con gcc 4.6, donde siempre es el doble de grande disponible sencilla tipo primitivo:

MATCH! 
+0

eso es algo. Gracias. – smallB

0

Supongo que podría escribir un pequeño programa que vuelva a procesar su programa principal. El pequeño programa podría usar sizeof() para comparar todos los tipos numéricos para determinar el más grande. Luego reemplazaría el símbolo "MÁS GRANDE" en su programa principal con el tipo que realmente era el más grande.

0

Puede usar la clase de plantilla std::numeric_limits para obtener información acerca de los tipos primitivos que tienen especializaciones.

No es que en algunos compiladores un long double es mayor que el long long aunque en otros un long double es del tamaño de un double (MSVC).

2

No, esto no es posible. Sin embargo, puede garantizar que 64 bits es el tipo más grande. No conozco ningún compilador que ofrezca 128 bits. En su defecto, haga que su usuario lo pase como un parámetro de plantilla o use definiciones específicas del compilador para crear un typedef.

+0

[Hay al menos uno] (http://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html), aunque no en todos los destinos. – Damon

+0

¿Qué hay de los tipos SIMD? – Simon

+0

Long double tiene 128 bits de longitud en algunas máquinas. –

2

Para los tipos enteros solamente, se puede utilizar la cabecera <cstdint>, lo que le permite hacer:

std::intmax_t largest; 

No estoy al tanto de cualquier funcionalidad que incluye flotante apunta tipos, sin embargo.

Cuestiones relacionadas