template<typename ClassT>
void F( ClassT myType)
{
void F( ClassT myType)
{
if ( myType is ClassA)
{
{
// operating for ClassA
}
else
{
else
{
// operaing for ClassB, C, D
}
}
雖然 F 可以對這四種型別做運算,但有時候可能因為此四種型別的實作方式不一,某些型別對於 F 運算,可以有更有效率的作法 (或是不同的作法),例如 STL 中,對於某種 iterator 的運算,會因為 iterator 的不同類型 (STL 有五種 iterators:input, output, forward, bidirectional, random access) 而有不一樣的方法,所以我們希望能在 template 中辨視型別。
首先我們建立一些 tag struct 用以表示型別的特徵:
struct classA_tag {} ;
struct classBCD_tag {} ;
然後在目的型別中,利用 typedef 定義一個子型別
class ClassA
{
{
public:
typedef classA_tag category ;
};
class ClassB
{
{
public:
typedef classBCD_tag category ;
};
class ClassC
{
{
public:
typedef classBCD_tag category ;
};
class ClassD
{
{
public:
typedef classBCD_tag category ;
};
接著,建立 traits class template:
template<typename ClassT>
struct MyTraits
{
struct MyTraits
{
typedef typename ClassT::category category;
};
此時我們的 function template F 大概變成這樣:
template<typename ClassT>
void F( ClassT myType)
{
void F( ClassT myType)
{
if ( typeid (typename myTraits<ClassT>::category ) == typeid (classA_tag ) )
{
{
// operating for ClassA
}
else
{
else
{
// operaing for ClassB, C, D
}
}
但是這樣的程式碼在編譯時可能會有問題 (因為 operating for ClassA 當中的所有敘述,必需被 ClassT 型別所支援,既使這些敘述不會被執行到),但此時有件更重要的事要解決,ClassT 也就是 myType 的型別在編譯時期就可以決定,而myTraits<ClassT>::category 也是在編譯時期就可以決定,但 if else 卻是執行期才會執行的語句,因此我們必須將 if else 提到編譯時期確定,做法即是使用 function overloading。我們 overload 兩個 function template F如下:
template<typename ClassT>
void doF( ClassT myType, classA_tag)
{
void doF( ClassT myType, classA_tag)
{
// operaing for ClassA
}
template<typename ClassT>
void doF( ClassT myType, classBCD_tag)
{
void doF( ClassT myType, classBCD_tag)
{
// operaing for ClassB, C, D
}
最後,我們就可以將 F 改寫如下:
template<typename ClassT>
void F( ClassT myType)
{
void F( ClassT myType)
{
doF ( myType , typename MyTraits<ClassT>::category( ) );
}
完工。
沒有留言:
張貼留言