2014-11-03 69 views
1

我正在瀏覽一些模板示例代碼,還有一件事我不明白。需要關於C++模板格式的說明

取模板梅索德:

template<class Seq, class T, class R> 
void apply(Seq &sq, R(T::*f)() const) { 
    typename Seq::iterator it = sq.begin(); 
    while(sq.end() != it) { 
     ((*it++)->*f)(); 
    } 
} 

樣本類:

class MyClass {  
public: 
    MyClass() {} 
    void doSomething() const { 
     std::cout << "doing stuff..." << std::endl; 
    } 
}; 

並測試代碼:

void testMyClass() { 
    vector<MyClass*> v; 
    for(size_t i = 0; i < 5; ++i) { 
     v.push_back(new MyClass()); 
    } 
    // call a member methode on all elements in container 
    apply(v, &MyClass::doSomething); 
} 

我將不勝感激,如果有人可以解釋我是什麼那class R,就像在模板定義中定義的那樣?

回答

2

class R指向傳遞給函數apply的函數指針的返回類型。它會自動從實際傳遞的函數指針類型中推導出來,所以當調用apply時,您從不需要關心它。

apply丟棄函數的返回值,實現這樣你就可以簡單地強制傳遞函數返回void

template<class Seq, class T> 
void apply(Seq &sq, void(T::*f)() const) { 
    typename Seq::iterator it = sq.begin(); 
    while(sq.end() != it) { 
     ((*it++)->*f)(); 
    } 
} 

但是,現在你限制呼叫現場只有通過這樣的函數指針。可悲的是,一個函數返回的指針不是可以轉化爲一個沒有的,儘管它會非常「直觀」。

所以,當你把一個函數指針作爲參數,並且你不關心返回類型時,最好接受「any」返回類型比「none」更好。

2

class R在模板中用於推導函數的返回類型。在你的情況下,它被推斷爲void類型。

+1

你不知道由於我們還沒有給出'Gromit :: doSomething'的定義,推導出的返回類型是'void'。給定的代碼不應該編譯。 – 2014-11-03 22:32:41

+2

@CrazyEddie,非常有洞察力。我希望OP意味着使用'&MyClass :: doSomething'或打算使用'Gromit'而不是'MyClass'。 – 2014-11-03 22:36:29