2013-04-14 13 views
5

Ho scritto una classe semplice per la media mobile che può essere utilizzata con un AVR.Come specializzare un modello senza copiare e incollare l'intero corpo della classe?

template<typename T, typename Tsum = int32_t> 
class MovingAverage { ... } 

Ma ora voglio specializzare questa classe per galleggiare senza copiare e incollare l'intero corpo di classe e cambiare tutto T e Tsum a stare a galla e che non ho bisogno di usare due parametri di modello. Tsum è il tipo per la variabile 'sum' in cui sono stati riassunti tutti i valori passati di tipo T. Se T è 'uint8_t' è una buona idea usare 'uint32_t' per la somma, ma per float o double non c'è bisogno di usare un tipo di dati con maggiore precisione, quindi voglio solo un parametro per questo scopo. Ho pensato che potrebbe funzionare in questo modo:

typedef MovingAverage<float, float> MovingAverage<float> 

o in questo modo:

template<> 
class MovingAverage<float> : public MovingAverage<float, float> {}; 

Ma mi sbagliavo e ho trovato solo soluzioni dove devo scrivere il mio codice due volte.

C'è un modo per scrivere la classe solo una volta e quindi specializzarla in questo modo preferisco? Grazie in anticipo!

risposta

5

Si potrebbe scrivere una semplice classe tratti

// general version 
template<typename T> 
struct sum_type 
{ 
    typedef int32_t type; 
}; 

// specialized version 
template<> 
struct sum_type<float> 
{ 
    typedef float type; 
}; 

// repeat for double, the solution from @DanielFrey is even more sophisticated 
// as it specializes all floating point types in one sweep. 

e quindi estrarre questo tipo nel vostro modello di classe

template<typename T, typename Tsum = typename sum_type<T>::type> 
//         ^^^^^^^^ <-- dependent type disambiguation 
class MovingAverage { ... }; 

Si noti che questo funziona solo se il vostro MovingAverage dispone di un'implementazione regolarmente con parametri. Se stai effettivamente facendo qualcosa di speciale per float (ad esempio, riscrivi le espressioni per occuparti del carattere non associativo dell'aritmetica in virgola mobile), allora devi fare più lavoro.

Se si è seriamente intenzionati a lavorare con i modelli C++, eseguire -non andare al bookstore più vicino e ottenere il libro C++ Templates: The Complete Guide. La Sezione 15.1 ha una discussione di oltre 15 pagine sulla definizione di un modello di classe cumulativo generico.

+0

+1 per il libro, mi ricorda che dovrei leggere di più :) –

+1

@ DanielFrey il libro è una buona lettura, molto pedagogico, non vedo l'ora che arrivi una versione di C++ 11. – TemplateRex

8

Se volete diversi tipi predefiniti per Tsum, questo dovrebbe essere affidata a un'altra classe che può essere specificata, ad esempio:

template< typename, typename = void > 
struct DefaultSum { using type = int32_t; }; 

template< typename T > 
struct DefaultSum< T, typename std::enable_if< 
    std::is_floating_point<T>::value 
>::type > 
{ using type = T; }; 

template<typename T, typename Tsum = typename DefaultSum<T>::type > 
class MovingAverage { ... } 
+0

+1 per il trucco 'std :: is_floating_point'. – TemplateRex

+0

Grazie, @Daniel! Questo è veramente bello e funziona perfettamente con gcc. Unfortunality Ho capito che non ho installato una versione di boost type_traits per l'avr-gcc. Al momento sto cercando su google un pacchetto debian installabile per farlo funzionare. Altrimenti copio le parti necessarie dalla mia installazione x86_64 alla directory include di avr-gcc. – user2280245

Problemi correlati