2011-06-27 22 views
2

我需要編寫一個模板,它根據模板參數是否是某個類的實例來生成一些代碼。可以爲所有類生成模板,但只有在該類是其他類的代碼應該執行的子類時纔可以生成該模板。在沒有類實例的情況下在C++模板中檢查類

問題是,應該實現的函數沒有收到類的任何實例,所以唯一已知的是類名。所以這是不可能的dynamic_cast實現這一目標,因爲它要求的對象

template<T> 
class A 
{ 
    void somefunction(void) 
    { 
    if (T instanceof Foo) then ... 
    else ... 
    } 
} 

的情況下增加了一些解釋

class X: public Foo {}; 
class Y {}; 

class A<X> {} // special logic is generated 
class A<Y> {} // special logic is NOT generated 
+0

如果你需要在模板實例美孚特殊行爲,我Ť嗨,你不需要一個模板類,你需要一個模板方法模式... ...# –

+1

@Miguel天使:他只需要**它,如果他需要運行時多態性。 –

回答

3

您可以使用boost traits library 中的模板專業化或boost :: is_base_of,或者編寫自己的特徵,但不應該,因爲您還沒有掌握模板。

使用專業化,你可以

template<T> 
class A 
{ 
    void somefunction() { 
    // generic version 
    } 
}; 
template<> 
class A <Foo> 
{ 
    void somefunction() { 
    // foo version 
    } 
}; 

與往常一樣,讓我推薦Vandevoorde /約祖蒂斯 「C++模板:完全指南」。

如果擔心代碼膨脹,因爲需要專業化只有一個memberfunction出許多,你仍然可以外包這個函數:

template <typename T> struct somefunction_helper { 
    static void thatfunction() { 
     // generic form 
    } 
}; 
template <> struct somefunction_helper<Foo> { 
    static void thatfunction() { 
     // Foo form 
    } 
}; 

template<T> 
class A 
{ 
    void somefunction() { 
    somefunction_helper<T>::thatfunction(); 
    } 
}; 
+0

is_base_of似乎很有前途 – Boris

1

無論是專業A或委託someFunction()成員函數模板的工作,一些免費的功能模板,你可以(完全)專注於T

+0

與上面相同的註釋 - Foo僅爲基類從未將其作爲參數實例化的模板 – Boris

2

這是模板專門化的用途。他們更難寫,但這就是你對他們所做的。例如:

template<T> class A 
{ 
    void somefunction(void) { 
     ...//default for any object type. 
    } 
}; 

template<> class A<Foo> 
{ 
    void somefunction(void) { 
     ...//specific to the type Foo. 
    } 
}; 

是的,它需要額外的工作。有一些模板元編程方法可以按照你想要的方式來完成,但其他人將不得不解釋這些。

+0

Foo僅爲基類從未將其作爲參數實例化的模板 – Boris

+0

@Boris:您的評論沒有任何意義。如果'A'永遠不會被實例化,那麼你的成員函數將永遠不會被調用。 _If_實際上使用了'A',這裏_will_是'T'的一個實際參數,並且這將起作用。 (請注意,Nicol和我的解決方案都不需要實例化類型爲「T」的對象。) – sbi

+0

class X:Foo {},class Y {},A僅用X和Y作爲參數實例化,而不是Foo本身(A 和A ) - 對於X類,應調用特殊邏輯。 – Boris

-1

編輯#2 - 請參閱工作示例。請注意,這是模板特化的運行時間(在編譯時發生),並且需要啓用RTTI。

#include <iostream> 
#include <typeinfo> 
using namespace std; 

class Foo {}; 
class X: public Foo {}; 
class Y {}; 

template<typename T> class A { 
public: 
    void somefunction() 
    { 
    if (typeid(T) == typeid(X)) { 
     cout << "X specific logic happening" << endl; 
    } 
    else { 
     cout << "Default behavior" << endl; 
    } 
    } 
}; 

int main() { 
    A<X> ax; 
    A<Y> ay; 
    ax.somefunction(); // prints "X specific logic happening" 
    ay.somefunction(); // prints "Default behavior" 
} 

typeid可以與模板被用來提取模板參數的類型 - 如下所述:

// expre_typeid_Operator_3.cpp 
// compile with: /c 
#include <typeinfo> 
template < typename T > 
T max(T arg1, T arg2) { 
    cout << typeid(T).name() << "s compared." << endl; 
    return (arg1 > arg2 ? arg1 : arg2); 
} 

來自http://msdn.microsoft.com/en-us/library/fyf39xec(v=vs.80).aspx

注意,值name()是實現定義的。

+0

name()的返回值是實現定義的,不應該依賴其內容。 –

+0

好吧 - 我正在更新答案,以包含'name()'的可移植性注意事項 – Nick

+0

這究竟是如何應用於解決手頭的問題? – sbi

0

由於專業化將無法工作,因爲模板參數將只導出從Foo,用什麼另一個答案說:is_base_of,無論是從升壓或標準庫,如果它已經支持的部分地區的C++ 0x:

#include <type_traits> // C++0x 

class Foo{}; 

template<class T> 
class A{ 
    void specialOnFoo(){ 
    // dispatch the call 
    specialOnFoo(std::is_base_of<T, Foo>::type()); 
    } 

    void specialOnFoo(std::true_type){ 
    // handle Foo case 
    } 

    void specialOnFoo(std::false_type){ 
    // non-Foo case 
    } 
}; 
相關問題