2012-11-22 13 views
5

Rozważ poniższą wykładniczą gładszą klasę szablonów. Ta klasa służy do wygładzania/filtrowania danych sekwencyjnych w trybie wykładniczym (patrz metoda aktualizacji). Elemtype może być wektorem, a Float typ jest zwykle skalarem. Na przykład.C++ sprawdź zagnieżdżony typedef parametru szablonu, aby uzyskać jego bazowy typ skalarny

ExponentialSmoother<Eigen::Vector2f, float> x(0.1, Vector2f(0.5, 0.5)); 

W tym przykładzie drugi parametr szablonu Floattype można by uniknąć, ponieważ klasa Matrix EIGEN zawiera zagnieżdżone typedef aby uzyskać skalarnego Typ podstawy:

Vector2f::Scalar 

Jest to również rozsądne wystąpienia zarówno Elemtype i Floatype jako pływaki do wygładzania jednowymiarowych danych. W tym przypadku można również pominąć drugi parametr szablonu.

template <class Elemtype, class Floattype> 
class ExponentialSmoother 
{ 
public: 
    // ctor 
    ExponentialSmoother(Floattype alpha, Elemtype& initial_estimate); 

    // getters 
    inline const Elemtype& getValue() const {return estimate_;} 
    inline const Floattype getAlpha() const {return alpha_;} 

    const Elemtype& update(const Elemtype& curr) 
    { 
     estimate_ = (alpha_ * curr) + (((Floattype)1-alpha) * estimate_); 
     return estimate_; 
    } 

private: 
    Elemtype estimate_; 
    Floattype alpha_; // smoothing factor within [0,1] 
} 

Teraz moje pytanie brzmi: co to jest „najbardziej eleganckie” rozwiązanie wdrożyć ExponentialSmoother tylko jeden parametr szablonu (typu elementu)? Powinien działać z wektorami i macierzami Eigen, ale także z typami zmiennoprzecinkowymi.

Innymi słowy, czy możliwe jest sprawdzenie, czy Elemtype :: Scalar istnieje, a jeśli nie (np. Elemtype jest zmiennoprzecinkowe lub podwójne), należy zdefiniować Floattype jako Elemtype?

Podobne pytanie zostało zadane here. Ale zastanawiam się, jakie jest najbardziej ogólne rozwiązanie, jeśli na przykład należy wspierać wektory STL. Czy wszystkie typy wymagałyby tego samego zagnieżdżonego typedef (lub klasy niektórych cech ze spójnym nazewnictwem)?

+0

* Czy wszystkie typy wymagają tego samego zagnieżdżonego typedef (lub klasy niektórych cech z konsekwentnym nazwaniem)? * - Tak. –

Odpowiedz

3

Możesz użyć pomocnika. Łącze daliście niemal zawiera rozwiązanie:

template<class T, class R = void> 
struct enable_if_type 
{ 
    typedef R type; 
}; 

template<class E, class Enable = void> 
struct GetFloatType 
{ 
    typedef E type; 
}; 

template<class E> 
struct GetFloatType<E, typename enable_if_type<typename E::Scalar>::type> 
{ 
    typedef typename E::Scalar type; 
}; 

Następnie w swojej klasie:

template <class Elemtype, class Floattype = typename GetFloatType<Elemtype>::type> 
class ExponentialSmoother 
{ 
    // ... 
}; 

Również z tego użytkownicy mogą nadal ręcznie zapewnić ich typu float. Możesz go zobaczyć live. Bonus: działa z C++ 03 bez problemów.

Pamiętaj, że możesz dodać więcej specjalizacji częściowych GetFloatType. Here is a live example. Nie zapomnij, że ElemType musi być akceptowalny dla tylko jednej specjalizacji z GetFloatType, inaczej będzie niejednoznaczny (i spowoduje błąd kompilatora).

+0

Dzięki, to naprawdę bardzo eleganckie rozwiązanie. Teraz, jeśli chcę obsługiwać inne typy macierzy, mogę w zasadzie dodać więcej specjalizacji szablonowych, np .: 'szablon struct GetFloatType :: type> {...}." – spinxz

+0

Tak, możesz dodać więcej specjalizacji. Zobacz moją edycję (koniec odpowiedzi). – Synxis

Powiązane problemy