你只能通過提供所有模板參數專門它明確。類模板的成員函數不允許部分專業化。
template <typename T,bool B>
struct X
{
void Specialized();
};
// works
template <>
void X<int,true>::Specialized()
{
...
}
一個解決辦法是引進重載函數,這在同級別仍然受益,所以他們不得不成員變量,函數相同的訪問,配件
// "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>) {
// ...
}
};
注通過傳遞重載函數並將模板參數推入函數參數中,您可以任意「專門化」您的函數,也可以根據需要對它們進行模板化。另一種常見的方法是推遲到單獨定義
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(); }
};
我發現,通常需要更多的代碼,我找到函數重載就好辦了類模板,而其他人則傾向於將延遲到類模板的方式。最後,這是一個品味問題。在這種情況下,您可以將X
中的其他模板作爲嵌套模板來使用 - 在其他情況下,如果您明確地專門化而不是部分地進行專門化,那麼您不能這樣做,因爲您只能在命名空間範圍內放置明確的特化,不屬於課堂範圍。
您也可以創建一個僅用於功能重載的模板(它的作用類似於我們之前的i2t
),因爲以下變體演示了哪個也會留下第一個參數變量(因此您可以將其與其他參數類型 - 不只是當前實例化的模板參數)
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>) {
// ...
}
};
我有時覺得,推遲到另一個模板是更好的(當涉及到此類案件的數組和指針,超載可以棘手,只是轉發給類模板對我來說一直比較容易),有時候只是在模板內重載會更好 - 尤其是如果你真的喜歡病房函數的參數,如果你觸摸類的成員變量。
這裏並不完全清楚你的意思。你的意思是強制模板參數是某種類型的後代?像你可以在Java中使用? –
2009-10-01 01:07:06
@Alcon當專門研究模板類時,他必須爲整個類提供*不同的實現。在我看來,他想分享專業之間的通用代碼,除了少數功能。 – AraK 2009-10-01 01:15:19
這個問題應該說「成員函數」而不是「成員」?爲了沒有人認爲這是關於數據成員。 – 2015-08-18 16:35:33