2013-04-14 11 views
5

Napisałem prostą klasę dla średniej ruchomej, która może być używana z AVR.Jak specjalizować szablon bez kopiowania i wklejania całego obiektu klasy?

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

Ale teraz chcę się specjalizować tę klasę dla pływaka bez kopiowania i wklejania na cały organizm i zmienić wszystkie klasy T i Tsum się unosić i że nie trzeba używać dwóch parametrów szablonu. Tsum jest typem zmiennej "sum", w której sumowane są wszystkie wartości typu T. Jeśli T jest "uint8_t", dobrym pomysłem jest użycie "uint32_t" dla sumy, ale dla float lub double nie ma potrzeby używania typu danych z większą precyzją, więc chcę tylko jeden parametr do tego celu. Myślałam, że to działa w ten sposób:

typedef MovingAverage<float, float> MovingAverage<float> 

lub w ten sposób:

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

Ale myliłem się i znalazłem tylko rozwiązania gdzie mam napisać kod dwukrotnie.

Czy istnieje sposób, aby napisać klasę tylko raz, a następnie specjalizować ją w ten sposób? Z góry dziękuję!

Odpowiedz

5

Można napisać prostą klasę cech

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

a następnie wyodrębnić tego typu w szablonie klasy

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

Zauważ, że to działa tylko jeśli MovingAverage ma regularnie parametryczne realizację. Jeśli faktycznie robisz coś specjalnego dla float (np. Przepisuj wyrażenia, aby zająć się nie asocjacyjnym charakterem arytmetyki zmiennoprzecinkowej), musisz wykonać więcej pracy.

Jeśli poważnie myślisz o pracy z szablonami C++, uruchom -nie przejdź do najbliższego księgarni i zdobądź książkę C++ Templates: The Complete Guide. Sekcja 15.1 zawiera 15-stronicową dyskusję na temat definiowania ogólnego szablonu klasy kumulacji.

+0

+1 dla książki, przypomina mi, że powinienem przeczytać :) –

+1

@ Książka DanielFrey jest również miłym czytaniem, bardzo pedagogicznym, nie może doczekać się wersji C++ 11. – TemplateRex

8

Jeśli chcesz różnych typów domyślnych Tsum, to powinno być zlecone do innej klasy, który może być określony, na przykład:

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 dla sztuczki 'std :: is_floating_point'. – TemplateRex

+0

Dziękuję, @ ​​Daniel! To jest naprawdę fajne i działa doskonale z gcc. Niefortunność Przekonałem się, że nie zainstalowałem wersji boostów typu_traits dla avr-gcc. W tej chwili szukam google dla pakietu debian do zainstalowania, aby to działało. W przeciwnym razie skopiuję potrzebne części z mojej instalacji x86_64 do katalogu include avr-gcc. – user2280245

Powiązane problemy