2010-01-15 87 views
1

編譯器如何知道正確的類型,這樣的代碼:模板扣和函數指針

class Base 
{ 
protected: 
    typedef View * ViewType; 
    typedef boost::function<ViewType()> ActionType; 
    typedef boost::unordered_map<std::string, ActionType> ActionMapType; 

    ActionMapType actions; 

    template <class ControllerType> 
    inline void addAction(std::string actionName, ViewType (ControllerType::*action)()) { actions.insert(ActionMapType::value_type(actionName, bind<ViewType>(&action, static_cast<ControllerType *>(this)))); } 
}; 

class Derived : public Base 
{ 
    Derived() 
    { 
     addAction("someAction", &Derived::foo); // No template 
    } 

    ViewType foo() { cout << "foo"; } 
} 

我知道,我傳遞推導ControllerType但是編譯器怎麼能知道肯定派生是模板參數?

回答

2

模板參數爲ControllerType,它在函數參數列表中用作參數ViewType (ControllerType::*action)()。當您提供ViewType (Derived::*)()類型的實際參數時,編譯器立即認識到ControllerType = Derived。而已。這被稱爲模板參數推導。

在C++的某些上下文中,編譯器無法從函數參數的類型推導出模板參數。這種上下文被稱爲未推導的上下文。語言規範提供了未推導的上下文列表。而你的不是其中之一。

+0

我已經得到了。我在問爲什麼會發生。看到布魯斯的回答。 – 2010-01-15 02:22:27

+0

你的意思是,你知道模板參數演繹如何工作,但你不知道模板參數演繹存在嗎? – AnT 2010-01-15 02:24:15

+0

我知道模板演繹可能會發生,我實際上並不知道什麼時候。當它工作時,我猜想它與函數指針有關,但我不確定。此外,我不知道存在模板參數推理。 – 2010-01-15 02:37:57

0

它知道Derived是模板參數,因爲您在addAction()函數調用中指定了&Derived::foo(而不是&SomethingElse::foo)。這是在編譯時確定的,所以不需要RTTI。

1

函數模板將推導出它們的類型。

您有ViewType (ControllerType::*action)(),其中ControllerType可以是任何類別。所以基本上它正在尋找一個指向一個不需要任何東西並返回一個ViewType的類函數的指針,並且該類可以是任何類。 「任何類型」必須是Derived