2011-10-01 21 views
12

Chciałbym zdefiniować specjalizację szablon C++, która dotyczy wszystkich podklas danej klasy bazowej. czy to możliwe?Specjalizacja szablonu dla wszystkich podklas

W szczególności chciałbym to zrobić dla hash STL's <>. hash <> jest zdefiniowany jako pusty parametryzowaną szablonu, a rodzinę specjalności dla poszczególnych typów:

template<class _Key> 
    struct hash { }; 

template<> 
    struct hash<char> 
    { 
    size_t 
    operator()(char __x) const 
    { return __x; } 
    }; 

template<> 
    struct hash<int> 
    { 
    size_t 
    operator()(int __x) const 
    { return __x; } 
    }; 
... 

chciałbym zdefiniować tak:

template<class Base> 
    struct hash { 
    size_t operator()(const Base& b) const { 
     return b.my_hash(); 
    } 
    }; 

class Sub : public Base { 
    public: 
    size_t my_hash() const { ... } 
}; 

i móc używać go jak to:

hash_multiset<Sub> set_of_sub; 
set_of_sub.insert(sub); 

Jednak moje konflikty szablonów mieszających ze standardowym z STL. Czy istnieje sposób (być może przy użyciu cech) do zdefiniowania specjalizacji szablonu, która dotyczy wszystkich podklas danej klasy bazowej (bez modyfikowania definicji STL)?

Zauważ, że wiem, że mogę to zrobić z kilku dodatkowych parametrów szablonu, gdy jest to potrzebne specjalizacja hash, ale chciałbym tego uniknąć, jeśli to możliwe:

template<> 
    struct hash<Base> { 
    size_t operator()(const Base& b) const { 
     return b.my_hash(); 
    } 
    }; 

.... 

// similar specialization of equal_to is needed here... I'm glossing over that... 
hash_multiset<Sub, hash<Base>, equal_to<Base> > set_of_sub; 
set_of_sub.insert(sub); 
+0

jeśli jest to sprzeczne, dlaczego nie używać przestrzeni nazw? – Arunmu

+1

Możliwy duplikat http://stackoverflow.com/questions/1032973/how-to-partially-specialize-a-class-template-for-all-derived-types –

+0

... gdzie rozwiązaniem jest podanie wszystkich pochodne klasy w podobny sposób, który nie jest całkiem zadowalający. – jpalecek

Odpowiedz

1

Rozwiązaniem jest użycie SFINAE zdecydować czy zezwolić na specjalizację w zależności od struktury dziedziczenia klas. W Boost możesz użyć enable_if i is_base_of, aby to zaimplementować.

+0

Obawiam się, że nie można użyć 'enable_if' w tym konkretnym przypadku. – jpalecek

+0

jpalecek: Dlaczego nie? BTW, jeśli boost jest tu odpowiedzią, to i tak może mi nie pomóc, ponieważ moje miejsce pracy ogranicza biblioteki, których możemy użyć, i boost :: enable_if nie jest częścią przepisanego podzbioru. –

+0

Następnie możesz musieć rzucić własną, ale powinieneś być w stanie uzyskać coś, co działa jak chcesz, używając SFINAE. – KayEss

0

To było najlepsze co mogłem zrobić:

template<> 
    struct hash<Sub> : hash<Base> { 
    }; 

Jestem trochę zaniepokojony, że nie trzeba wprowadzać operator() wirtualny, choć .

Powiązane problemy