2010-12-28 15 views
20
struct Bar { 
    enum { Special = 4 }; 
}; 

template<class T, int K> struct Foo {}; 
template<class T> struct Foo<T,T::Special> {}; 

Zastosowanie:Czy można specjalizować szablon za pomocą wyliczenia członka?

Foo<Bar> aa; 

nie skompilować za pomocą gcc 4.1.2 narzeka o wykorzystaniu T::Special częściowego specilization Foo. Jeśli Special byłaby klasą, rozwiązaniem byłaby nazwa pliku przed nim. Czy istnieje coś podobnego do wyliczenia (lub liczb całkowitych)?

+6

Interesujące pytanie. –

+0

Jeśli zastąpisz T :: Special konkretną liczbą całkowitą (99, powiedzmy), to nadal nie skompiluje się pod g ++ 4.4.0: "błędna liczba argumentów szablonu (1, powinna być 2)." Zdaję sobie sprawę, że jest to oddzielny problem, ale czy kompilator nie powinien tego akceptować? – TonyK

Odpowiedz

9

Typ argumentu szablonu innego niż typ nie może zależeć od parametru szablonu częściowej specjalizacji.

ISO C++ 03 14.5.4/9 mówi

Częściowo wyspecjalizowanym wyrażenie argumentem non-type nie wiąże parametr szablonu częściowego specjalizacji z wyjątkiem gdy wyrażenie argument jest prosty identyfikator.

template <int I, int J> struct A {}; 
template <int I> struct A<I+5, I*2> {}; //error 
template <int I, int J> struct B {}; 
template <int I> struct B<I, I> {};  //OK 

Więc coś w tym jest nielegalne template<class T> struct Foo<T,T::Special> {}; ponieważ T::Special zależy T

Użycie jest również nielegalne. Podałeś jeden argument szablonu, ale musisz podać dwa.

+1

Dlaczego typ parametru szablonu nie typu zależy od parametru szablonu specjalizacji częściowej? Typ wciąż jest "int", nie? –

+0

Mówię o argumencie szablonu (nie o parametrze szablonu 'int K')' T :: Special', który zależy od 'T'. –

+0

Ah. Typ argumentu zależy od 'T', typem parametru jest' int'. –

16

Ponieważ nie jest dozwolone przez C++ jako explained przez Prasoon, więc alternatywnym rozwiązaniem byłoby wykorzystanie EnumToType klasy szablon, kod

struct Bar { 
    enum { Special = 4 }; 
}; 

template<int e> 
struct EnumToType 
{ 
    static const int value = e; 
}; 

template<class T, class K> //note I changed from "int K" to "class K" 
struct Foo 
{}; 

template<class T> 
struct Foo<T, EnumToType<(int)T::Special> > 
{ 
    static const int enumValue = T::Special; 
}; 

próbki w ideone: http://www.ideone.com/JPvZy


Lub możesz po prostu specjalizować się w ten sposób (jeśli rozwiąże twój problem),

template<class T> struct Foo<T,Bar::Special> {}; 

//usage 
Foo<Bar, Bar::Special> f; 
+3

Bardzo ładne rozwiązanie! –

+1

Rzeczywiście dobre rozwiązanie. +1 ode mnie. :) –

+0

@ James i Prasoon: dzięki za uznanie :-) – Nawaz

Powiązane problemy