编译器如何知道此代码的正确类型:
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"; }
}
我知道我将Derived作为ControllerType传递,但编译器如何确定Derived是模板参数?
答案 0 :(得分:2)
模板参数为ControllerType
,在函数参数列表中用作ViewType (ControllerType::*action)()
参数。当您提供ViewType (Derived::*)()
类型的实际参数时,编译器会立即意识到ControllerType = Derived
。而已。这称为模板参数推导。
在C ++的某些上下文中,编译器无法从函数参数的类型推导出模板参数。这种上下文称为非推导的上下文。语言规范提供了非推断的上下文列表。而你的不是其中之一。
答案 1 :(得分:1)
功能模板将推断出它们的类型。
您有ViewType (ControllerType::*action)()
,其中ControllerType
可以是任何类。所以基本上它正在寻找一个指向类函数的指针,该函数不需要任何东西并返回ViewType
,并且该类可以是任何类。 “任何类型”必须为Derived
。
答案 2 :(得分:0)
它知道Derived
是模板参数,因为您在&Derived::foo
函数调用中指定了&SomethingElse::foo
(而不是addAction()
)。这是在编译时确定的,因此不需要RTTI。