Search code examples
c++templatestypestype-deduction

Infer 'this' pointer type when called from derived class?


I have a method in a baseclass that needs the type passed to it for some type-related operations (lookup, size, and some method invocation). Currently it looks like this:

class base
{
    template<typename T>
    void BindType( T * t ); // do something with the type
};

class derived : public base
{
    void foo() { do_some_work BindType( this ); } 
};

class derivedOther : public base 
{
    void bar() { do_different_work... BindType( this ); } 
};

However, I wonder if there's a way to get the caller's type without having to pass this so that my callpoint code becomes:

class derived : public base
{
  void foo() { BindType(); } 
};

Without the explicit this pointer. I know that I could supply the template parameters explicitly as BindType<derived>(), but is there a way to somehow extract the type of the caller in some other way?


Solution

  • It will not work as you expect

    The result of foo() might be different of what you expect:

    class derived : public base           // <= YOU ARE IN CLASS DERIVED
    {
    public:
        void foo() { BindType( this ); }  // <= SO this IS OF TYPE POINTER TO DERIVED
    };
    

    The template paramter is deducted at compile time, so that it will be derived*. If you would call foo() from a class derived_once_more derived from derived, it would still use the type derived*.

    Online demo

    But you can get rid of the dummy parameter*

    You may use decltype(this) to represent the typename of a variable. It's still defined at compile time:

    class base
    {
    public: 
        template<typename T>
        void BindType( ) 
        { 
             cout << typeid(T*).name()<<endl;  // just to show the type 
        }
        virtual ~base() {};                    // for typeid() to work 
    };
    class derived : public base
    {
    public: 
        void foo() { BindType<decltype(this)>( ); } 
    };
    

    Online demo

    Edit: other alternatives

    As template parameters need to be provided at compile-time and not a run time, you can use:

    • template parameter deduction (your first code snippet)
    • decltype (see above)
    • if you intend to add this in all the derived classes you could use a macro to get it done, using one of the above mentionned solution
    • you could use the CRTP pattern (already explained in another answer).