2013-04-14 12 views
5

AVR ile kullanılabilen hareketli ortalama için basit bir sınıf yazdım.Tüm sınıf gövdesini kopyalamadan ve yapıştırmadan bir şablon nasıl uzmanlaşır?

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

Ama şimdi kopyalamadan şamandıra için bu sınıfı uzman ve bütün sınıf vücudu yapıştırarak ve ben iki şablon parametreleri kullanmak gerekmez T ve TSUM yüzer tüm ve bunu değiştirmek istiyorum. Tsum, T türünün tüm geçirilen değerlerinin toplandığı 'toplam' değişkenin türüdür. Eğer 'uint8_t' ise, 'uint32_t' değerini toplam için kullanmak iyi bir fikirdir, ancak float veya double için daha yüksek hassasiyetli bir veri türü kullanmaya gerek yoktur, bu yüzden bu amaç için sadece bir parametre istiyorum.

typedef MovingAverage<float, float> MovingAverage<float> 

veya bu şekilde: Ben bu şekilde çalışır diye düşündüm

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

Ama yanılmışım ve ben iki kez kod yazmak zorunda sadece çözüm buldum.

Sınıfı sadece bir kez yazmak için bir yol var mı? Şimdiden teşekkürler!

cevap

5

Basit özellikleri sınıf

// 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. 

yazıp sınıf şablonunda

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

Not bu tip ayıklamak ki senin MovingAverage düzenli parametreli bir uygulama vardır bu sadece çalışır eğer. Aslında float için özel bir şey yapıyorsanız (ör. Kayan nokta aritmetiğinin ilişkisel olmayan karakterine dikkat çekmek için yeniden yazma ifadeleri), daha fazla iş yapmanız gerekir.

C++ şablonlarıyla çalışma konusunda ciddi iseniz, en yakın kitapçıya koşmayın ve C++ Templates: The Complete Guide numaralı kitabı alın. Bölüm 15.1, jenerik bir birikim sınıfı şablonunun tanımlanmasıyla ilgili 15+ sayfalık bir tartışmaya sahiptir.

+0

+1, ben daha okumalısınız :) –

+1

hatırlatıyor @ DanielFrey kitap da güzel bir okuma, çok pedagojik, bir C++ 11 sürümü için sabırsızlanıyorum. Std :: is_floating_point' hilesi için – TemplateRex

8

Eğer Tsum için farklı varsayılan türlerini istiyorsanız, bu örneğin belirtilebilir başka bir sınıfa dışarıdan alınmalıdır: Kitabın

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. – TemplateRex

+0

Teşekkür ederiz, @Daniel! Bu gerçekten güzel ve gcc ile mükemmel çalışıyor. Talihsizliği avr-gcc için tip_traits desteği olan bir sürüm yüklemediğimi anladım. Şu anda çalışmamı sağlamak için yüklenebilir bir debian paketi için google'da arama yapıyorum. Aksi takdirde, gerekli parçaları x86_64 kurulumumdan avr-gcc'nin içerme dizinine kopyalarım. – user2280245

İlgili konular