views:

65

answers:

3

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;

    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"; }
}

I am aware that I am passing Derived as ControllerType but how can the compiler know for sure that Derived is the template parameter?

A: 

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.

Mike DeSimone
+2  A: 

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.

AndreyT
That I already got. I was asking for why that happened. See Bruce's answer.
the_drow
You mean, you know how template argument deduction works, but you don't know that template argument deduction exists?
AndreyT
I knew that template deduction can happen, I didn't actually know when. When it worked I guessed it had something to do with the function pointer but I wasn't sure. Also I wasn't aware that template argument deduction exists.
the_drow
+1  A: 

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.

Bruce