Template deduction and function pointers
How does the compiler know the correct type for this code:
class Base
{
protected:
typedef View * ViewType;
typedef boost::function<ViewType ()> ActionType;
typedef boost::unordered_map<std::string, ActionType> ActionMapType;
ActionMapType actions;
templ开发者_开发技巧ate <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"; }
}
I am aware that I am passing Derived as ControllerType but how can the compiler know for sure that Derived is the template parameter?
The template parameter is ControllerType
which is used in the function parameter list as ViewType (ControllerType::*action)()
parameter. When you supply an actual argument of ViewType (Derived::*)()
type, the compiler immediately realizes that ControllerType = Derived
. That's it. This is called template argument deduction.
In some contexts in C++ the compiler cannot deduce the template argument from the type of function argument. Such contexts are called non-deduced contexts. The language specification provides a list of non-deduced contexts. And yours is not one of them.
Function templates will deduce their types.
You have ViewType (ControllerType::*action)()
, where ControllerType
can be any class. So basically it's looking for a pointer to a class function that takes nothing and returns a ViewType
and the class can be any class. The "any type" must be Derived
.
It knows Derived
is the template parameter because you specified &Derived::foo
(and not, say, &SomethingElse::foo
) in the addAction()
function call. This is determined at compile time, so no RTTI is needed.
精彩评论