2009-07-17 54 views
4

是否有可能有一個C++模板函數可以訪問輸入數據中的不同字段,具體取決於輸入數據的類型是否傳遞給它?C++模板函數僅使用某些數據類型中的字段?

例如我有這樣的代碼:

typedef struct 
{ 
    int a; 
    int b; 
}s1; 

typedef struct 
{ 
    int a; 
}s2; 

template <class VTI_type> void myfunc(VTI_type VRI_data, bool contains_b) 
{ 
    printf("%d", VRI_data.a); 

    if(contains_b) // or suggest your own test here 
    printf("%d", VRI_data.b); // this line won't compile if VTI_type is s2, even though s2.b is never accessed 
} 

void main() 
{ 
    s1 data1; 
    data1.a = 1; 
    data1.b = 2; 
    myfunc <s1> (data1, true); 

    s2 data2; 
    data2.a = 1; 
    myfunc <s2> (data2, false); 
} 

所以我們想要使用來自許多不同數據類型的字段A,並且工作正常。

但是,某些數據還有一個需要使用的字段B,但是如果模板知道它正在查看不包含字段B的數據類型,則需要刪除訪問字段B的代碼。

(在我的例子,該結構是外部API的一部分,因此不能改變)

+0

這個問題似乎是,是有可能做一個編譯時檢查,以一個類型是否有特定名稱的成員變量。我認爲答案是否定的。你*可以*使用SFINAE來完成會員類型。 – 2009-07-17 13:04:23

+0

你有沒有第二個領域的很多結構?爲他們提供模板專業化是否可行? – jalf 2009-07-17 13:04:39

回答

5

爲了詳細說明建議使用模板專業化:

template <class T> void myfunc(T data) 
{ 
    printf("%d", VRI_data.a); 
} 

// specialization for MyClassWithB: 
template <> 
void myfunc<MyClassWithB>(MyClassWithB data) 
{ 
    printf("%d", data.a); 
    printf("%d", data.b); 
} 

然而,這需要每個類別的專業化,沒有「自動檢測」 B的。此外,你重複了很多代碼。

您可以將該「有b」方面排除到輔助模板中。一個簡單的演示:

// helper template - "normal" classes don't have a b 
template <typename T> 
int * GetB(T data) { return NULL; } 

// specialization - MyClassWithB does have a b: 
template<> 
int * GetB<MyClassWithB>(MyClassWithB data) { return &data.b; } 

// generic print template 
template <class T> void myfunc(T data) 
{ 
    printf("%d", VRI_data.a); 
    int * pb = GetB(data); 
    if (pb) 
     printf("%d", *pb); 
} 
3

解決方案1:你可以使用模板專業化。專業化可以按照每個班級進行,也可以在更普遍的特點上進行。

0

如果你不想硬編碼S1代碼& S2專業化那麼你可以做:

typedef struct 
{ 
    int a; 
    int b; 
}s1; 

typedef struct 
{ 
    int a; 
}s2; 

template <class T, bool contains_b> 
struct MyFunc 
{ 

    void operator()(T data) 
    { 
     printf("%d", data.a); 
    } 

}; 


template <class T> 
struct MyFunc<T, true> 
{ 
    void operator()(T data) 
    { 
     printf("%d", data.a); 
     printf("%d", data.b); 

    } 
}; 

template<class T, bool contains_b> 
void myFunc(T t) 
{ 
    MyFunc<T, contains_b> m; 
    m(t); 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
s1 data1; 
    data1.a = 1; 
    data1.b = 2; 

    myFunc<s1,true>(data1) ; 

    s2 data2; 
    data2.a = 1; 
    myFunc<s2,false>(data2); 
    return 0; 
} 
0

爲了詳細說明別人的答案,似乎最好的方法是在多個模板中複製相同的代碼,只需要「額外的東西」功能(對於大多數數據類型爲空,但包含具有附加數據的任何對象的代碼),其中「模板特化」選擇爲每種數據類型運行「額外的東西」函數。

更新代碼:

typedef struct 
{ 
    int a; 
    int b; 
}s1; 

typedef struct 
{ 
    int a; 
}s2; 

template <class VTI_type> void extraStuff(VTI_type VRI_data) 
{ 
} 

template <> void extraStuff<s1>(s1 VRI_data) 
{ 
    printf(" and b = %d\n", VRI_data.b); 
} 

template <class VTI_type> void myfunc(VTI_type VRI_data) 
{ 
    printf("a = %d\n", VRI_data.a); 
    extraStuff(VRI_data); 
} 

void main() 
{ 
    s1 data1; 
    data1.a = 1; 
    data1.b = 2; 
    myfunc <s1> (data1); 

    s2 data2; 
    data2.a = 1; 
    myfunc <s2> (data2); 
} 
相關問題