此問題是有點難以解釋,所以我將用一個例子開始:爲模板基類的子類模板專業化
我有一個類模板,需要一個類型和一個整數常數作爲模板的參數,和我有很多的子類,從該模板的實例得出:
template <class V, int i>
struct Base
{
static void doSomething() { cout << "something " << i << endl; };
};
struct Child : public Base<int,12>
{
};
我想使用這些類與其他一些模板(姑且稱之爲測試),這對於不同類型的專業。因爲對於從Base的任何實例派生的所有類,行爲應該完全相同,所以我只想定義一個Test的專門化特性來處理從Base派生的所有類。
我知道我不能直接專注於基地< V,我>因爲這不會檢測子類。相反,我的第一種方法是使用Boost的enable_if和類型特點:
// empty body to trigger compiler error for unsupported types
template <class T, class Enabled = void>
struct Test { };
// specialization for ints,
// in my actual code, I have many more specializations here
template <class Enabled>
struct Test <int, Enabled>
{
static void test (int dst)
{
cout << "Test<int>::test(" << dst << ")" << endl;
}
};
// this should handle all subclasses of Base,
// but it doesn't compile
template <class T, class V, int i>
struct Test <T, typename enable_if <is_base_and_derived <Base <V,i>, T>>::type>
{
static void test (const T &dst)
{
dst.doSomething();
}
};
int main (int argc, char **argv)
{
Test <int>::test (23);
Test <Child>::test (Child());
return 0;
}
的想法是專業化應該處理這些從基地派生與V和我的任意值的所有課程。這不起作用,GCC抱怨:
error: template parameters not used in partial specialization: error: ‘V’ error: ‘i’
我想這個問題是,這種方法需要編譯器嘗試v的所有可能的組合,我來檢查其中是否匹配。現在,我工作圍繞這一問題通過添加一些基類:
template <class V, int i>
struct Base
{
typedef V VV;
static constexpr int ii = i;
static void doSomething() { cout << "something " << i << endl; };
};
這樣,專業化不再需要擁有V和我的免費模板參數:
template <class T>
struct Test <T, typename enable_if <is_base_and_derived <Base <typename T::VV, T::ii>, T>>::type>
{
static void test (const T &dst)
{
dst.doSomething();
}
};
然後它編譯。
現在,我的問題是:如何在不修改基類的情況下做到這一點?在這種情況下,這是可能的,因爲我自己寫了它,但是如果必須在我的Test模板中處理第三方庫代碼,我該怎麼辦?有沒有更優雅的解決方案?
編輯另外,有人可以給我一個詳細的解釋,爲什麼第一種方法不工作?我有一個粗略的想法,但我寧願有一個正確的理解。 :-)
感謝Base_Base提示,它使我當前的代碼更具可讀性。但是,對於第三方庫,這不起作用,至少在子類同樣屬於庫時不起作用。 –
@BenjaminSchug:也許[這](http://stackoverflow.com/a/6398983/1324131)在編輯的問題中回答你的新問題。 – user2k5
謝謝,這解釋了爲什麼第一種方法不起作用。似乎我的直覺是正確的。 –