2011-10-04 4 views
7

Desidero scrivere una struttura modello foo tale che foo<N>::value_type sia il numero intero più vicino (arrotondando per eccesso) a N. Ad esempio foo<32>::value_type => uint32_t, foo<33>::value_type => uint64_t e foo<72>::value_type => uint64_t.Specializzazione modello per un intervallo di valori

Per fare ciò, ho bisogno di un mezzo elegante per fornire specializzazioni parziali di foo per un intervallo di valori, ad esempio 1 <= N <= 8 per restituire uint8_t e così via e così quarto. C'è un mezzo per raggiungere questo obiettivo senza dover specializzare tutto da 0 a 64.

+0

Non ci sarà un modo diretto (come Mark ha detto), ma forse qualche trucco di metaprogrammazione modello intelligente. Bella domanda, in attesa di vedere le risposte. –

risposta

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; 
}; 

In è possibile utilizzare 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; 

È possibile decidere quale è meno leggibile.

+1

Mi piace essere smentito. –

+2

Ottima risposta. L'enum non dovrebbe essere enum {D = (N> 32? 3: (N> 16? 2: (N> 8? 1: 0)))}; ', comunque? Qui funziona: http://ideone.com/OgXaz – filipe

+0

Oh wow, l'ho già fatto in passato, ma questo è molto più semplice della mia versione! Anche se il mio aveva bool (1), char (2-8), ..., long long (33-64) e void (65+) –

1

I parametri del modello devono essere concreti, quindi non credo ci sia modo di evitare la specializzazione per ogni valore richiesto.

7

@hansmaad risposta è una risposta bello, ma preferirei usare (indovinate un po '?!) Boost:

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

Il,, tipo integrale più piccolo built-in non firmato con almeno N bit . Il parametro deve essere un numero positivo. Un errore in fase di compilazione risulta se il parametro è maggiore del numero di bit nel tipo intero maggiore .

+0

Molto carino, ancor più che sto usando boost nel mio progetto, ma non gestisce il caso di pippo <72> :: value_type che risolve il più grande numero intero disponibile. –