Tak i nie.
Nie możesz wyspecjalizować pojedynczej funkcji, ani "wciągnąć" implementacji podstawowej do specjalizacji.
template<typename T>
struct X{
void foo(){}
int bar(){
return 1;
}
};
template<typename T>
struct X<T*>{
// a foo?
int bar(){
return 2;
}
};
Możesz to ominąć poprzez ustalenie wspólnej klasy bazowej:
struct Baza{
void foo(){}
};
template<typename T>
struct X : Baza{
int bar(){
return 1;
}
};
template<typename T>
struct X<T*> : Baza{
int bar(){
return 2;
}
};
Jeśli z jakiegoś powodu nie chcesz rozbijać implementacji klasy na kilka części możesz użyć std::enable_if
lub metody znanej jako tag dispatching. enable_if
jest "łatwiejszy" dla pojedynczej zmiennej, ale ogółem nie jest polecanym rozwiązaniem ponieważ ilość przeładowań dla różnych kombinacji rośnie wykładniczo, a już dla jednej wygląda średnio.
enable_if
:
template<typename T>
struct X{
void foo(){}
template<typename U=T>
typename enable_if<!is_pointer<U>::value,int>::type
bar(){
return 1;
}
template<typename U=T>
typename enable_if<is_pointer<U>::value,int>::type
bar(){
return 2;
}
};
I tag dispatch:
template<typename T>
struct X{
void foo(){}
int bar(){
return bar_impl(typename is_pointer<T>::type{});
}
private:
int bar_impl(true_type){
return 2;
}
int bar_impl(false_type){
return 1;
}
};
Jest to rozwiązanie w/g mnie najlepsze, ponieważ pozwala wyraźnie (i czytelnie) określić która implementacja kiedy ma się wykonać.
Każde z powyższych rozwiązań powinno wypisać
1
2
dla poniższej funkcji main:
int main()
{
X<int> a;
X<int*> b;
cout << a.bar() << endl;
cout << b.bar() << endl;
return 0;
}