2010-10-15 50 views
11

我的問題是關於如何template'ize應使用類成員的如何模板化變量NAMES,而不是類型?

也許簡化&僞例如:

/** 
Does something with a specified member of every element in a List. 
*/ 
template<membername MEMBER> // <-- How to define such thing? 
void doSomething(std::vector<MyClass> all){ 

    for(i=0; i < all.size(); i++) 
     all[i].MEMBER++; // e.g.; use all[i].MEMBER in same way 

} 

class MyClass{ 
public: 
    int aaa, bbb, ccc; 
} 

和應用:

main(){ 
    vector<MyClass> all = .... 

    // applicate doSomething() to all aaa's 
    doSomething<aaa>(all); // or: 
    doSomething<MyClass::aaa>(all); // or: 
    doSomething<?????>(all); 
} 

應該如何模板定義的樣子,我可以開關, MyClass的成員變量(aaa,bbb或ccc)在do中被訪問/修改什麼(。)?
在我的現實世界任務的所有部件相同類型的,如上面。

謝謝, Tebas

回答

17

模板參數被限制爲類型,整數常量,指針/引用函數或對象具有外部鏈接和構件指針 - 但沒有標識符。

但是你可以使用一個成員指針作爲模板參數:

template<int MyClass::* MemPtr> 
void doSomething(std::vector<MyClass> & all) { 
    for(i=0; i < all.size(); i++) 
     (all[i].*MemPtr)++; 
} 

: 

doSomething<&MyClass::aaa>(all); 

注意,我改變了DoSomething的功能採取了參考,而不是由價值接受的載體。

+0

感謝。 通過值調用'all'是爲了簡化問題...但通過成員指針模板所請求的引用進行調用?或者我也可以使用副本? – Tebas 2010-10-15 13:23:47

+0

@Tebas:你可以使用副本,但這意味着'doSomething'的效果在函數外部是不可見的。使用引用調用來確保結果在調用者的向量中可見。 – 2010-10-15 13:45:23

+0

@Tebas:不,它沒有任何區別。無論哪種情況,所有[i]都將是類型MyClass的左值表達式。 – sellibitze 2010-10-15 13:45:26

1

我會用lambda表達式來解決這個問題。類似這樣的:

#include <vector>  // vector 
#include <algorithm> // for_each 
#include <functional> // function 

struct MyClass { 
    void func1() const { std::cout << __FUNCTION__ << std::endl; } 
    void func2() const { std::cout << __FUNCTION__ << std::endl; } 
}; 

void doSomething(std::vector<MyClass> all, std::function<void (MyClass& m)> f) 
{ 
    std::for_each(all.begin(), all.end(), f); 
} 

int main() 
{ 
    std::vector<MyClass> all; 
    all.push_back(MyClass()); 

    // apply various methods to each MyClass: 
    doSomething(all, [](MyClass& m) { m.func1(); }); 
    doSomething(all, [](MyClass& m) { m.func2(); }); 
} 

當然在這種情況下函數doSomething是不必要的。我可以直接在all上直接撥打for_each

10

sellibitze的解決方案是好的(雖然說實話不怎麼:看到我的編輯),只有它限制你只使用int類型的成員。一個更普遍的解決方案將是這個(雖然成員不是一個模板參數點擊這裏)

#include <vector> 

struct MyClass 
{ 
    int i; 
    char c; 
}; 

template <class T> 
void DoSomething(std::vector<MyClass>& all, T MyClass::* MemPtr) 
{ 
    for(std::vector<MyClass>::size_type i = 0; i < all.size(); ++i) 
     (all[i].*MemPtr)++; 
} 

int main() 
{ 
    std::vector<MyClass> all; 
    DoSomething(all, &MyClass::i); 
    DoSomething(all, &MyClass::c); 
} 

編輯: 同時請注意,這不是一般的指針成員一個好主意,是一個模板參數因爲作爲已知編譯時只有這樣的指針可以傳遞,那就是你不能確定指針運行,然後把它作爲一個模板PARAM。

+0

'vector :: all()'返回'size_t'而不是'unsigned' - 請使用'size_t'代替'i'。 ) – 2010-10-15 14:38:52

+1

@Steve:我完全同意迭代器,我只是複製了op的代碼中的文本,我不會改變它,size()不返回size_t,它返回std :: vector :: size_type。是矢量::所有?:D – 2010-10-15 14:47:01

+0

糟糕,你在第1點是正確的,我不知道我在第2點的想法是什麼,奇怪的是,我只是回答了一個與矢量有關的問題,知道要使用'size_type'而不是'size_t'。有時我很糟糕。 – 2010-10-15 15:16:13

相關問題