Można tylko specjalizują się go wyraźnie, dostarczając wszystkie argumenty szablonu. Brak częściowej specjalizacji dla funkcji członkowskich szablonów klas jest dozwolony.
template <typename T,bool B>
struct X
{
void Specialized();
};
// works
template <>
void X<int,true>::Specialized()
{
...
}
Dzieło wokół jest wprowadzenie przeciążone funkcje, które mają korzyści z jeszcze będąc w tej samej klasie, a więc mają taki sam dostęp do członkowskich zmiennych, funkcji i środków
// "maps" a bool value to a struct type
template<bool B> struct i2t { };
template <typename T,bool B>
struct X
{
void Specialized() { SpecializedImpl(i2t<B>()); }
private:
void SpecializedImpl(i2t<true>) {
// ...
}
void SpecializedImpl(i2t<false>) {
// ...
}
};
Note że przechodząc do przeciążonych funkcji i przesuwając parametry szablonu do parametru funkcji, możesz dowolnie "wyspecjalizować" swoje funkcje, a także może je w razie potrzeby zmienić. Inną powszechną techniką jest odroczyć do szablonu klasy zdefiniowane oddzielnie
template<typename T, bool B>
struct SpecializedImpl;
template<typename T>
struct SpecializedImpl<T, true> {
static void call() {
// ...
}
};
template<typename T>
struct SpecializedImpl<T, false> {
static void call() {
// ...
}
};
template <typename T,bool B>
struct X
{
void Specialized() { SpecializedImpl<T, B>::call(); }
};
uważam, że zazwyczaj wymaga więcej kodu i uważam funkcja przeciążenia łatwiejsze w obsłudze, podczas gdy inni wolą odraczać klasa szablonu sposób. W końcu to kwestia gustu. W takim przypadku możesz umieścić ten inny szablon wewnątrz X
również jako szablon zagnieżdżony - w innych przypadkach, w których jawnie specjalizujesz się zamiast tylko częściowo, nie możesz tego zrobić, ponieważ możesz umieszczać jawne specjalizacje tylko w obszarze przestrzeni nazw, nie do zakresu klasy.
Można również stworzyć taki SpecializedImpl
szablon tylko dla celów funkcji przeciążenia (to wtedy działa podobnie do naszego i2t
z wcześniej), co ilustruje poniższy wariant pokazuje, który opuszcza pierwszy parametr zmienny też (tak można nazwać to z innych rodzaje - nie tylko z parametrami szablonu bieżącej instancji'S)
template <typename T,bool B>
struct X
{
private:
// maps a type and non-type parameter to a struct type
template<typename T, bool B>
struct SpecializedImpl { };
public:
void Specialized() { Specialized(SpecializedImpl<T, B>()); }
private:
template<typename U>
void Specialized(SpecializedImpl<U, true>) {
// ...
}
template<typename U>
void Specialized(SpecializedImpl<U, false>) {
// ...
}
};
myślę czasami, odroczenie na inny szablon jest lepiej (jeśli chodzi o takich przypadkach jak tablice i wskaźniki, przeciążenia może trudne i tylko przekierowanie do szablonu klasy było mi wtedy łatwiej), a czasami po prostu przeciążenie w szablonie jest lepsze - zwłaszcza jeśli naprawdę argumenty funkcji Ward i jeśli dotkniesz zmiennych członków klasy.
To nie do końca jasne, co masz na myśli. Czy masz na myśli wymuszenie, że parametr szablonu jest potomkiem określonego typu? Jak możesz w Javie z? –
@Alcon Specjalizując się w klasie szablonów, musi podać * inną * implementację dla całej klasy. Wydaje mi się, że chce dzielić wspólny kod pomiędzy specjalizacjami, z wyjątkiem kilku funkcji. – AraK
Czy to pytanie powinno brzmieć "funkcja członka" zamiast "członek"? Aby nikt nie myślał, że chodzi o członków danych. –