KnuMul
KnuMul

Reputation: 9

Derive template type of derived class from base class pointer

Consider the following:

  1. a class B
  2. a class D, which
    • is derived from class B,
    • has a template parameter T,
    • has a member variable x of type T
  3. a template function F with
    • a template parameter S
    • a parameter y of type S.
  4. a pointer p, which
    • has the type B *
    • is pointing to an object o of class D with the template parameter T equal to e.g. int
  5. that the function F cannot be modfied.
  6. F cannot be invoked directly from classes B or D

Consider furthermore that only the pointer p is given and that F should be called with parameter y equal to the member variable x of object o (this means with the type S equal to int).

How can classes B and D be modfied to achieve this? I guess some kind of mechanism to derive the template type T is required. But I don't know how to do that.

Here is the related code:

File F.h:

#include <iostream>
//////////// Consider that the lines up to the next comment cannot be changed
template< typename S > void F( S y )
{
    std::cout << y <<  " of some type" << std::endl; 
}

template<> void F<>( int y )
{
    std::cout << y << " of int type." << std::endl; 
}
//////////// -----------------------------

File BD.h:

// F.h cannot be included here
class B { };

template<typename T> class D : public B { public:  T x;  };

File main.cpp:

#include "BD.h"
#include "F.h"
int main()
{
    D<int>  o;
    o.x  =  3;
    B* p = &o;

    // Obviously, the following line will not work:
    // F( p->x );

    // Obviously, the following will work:
    F( ( (D<int>*) p)->x );

    // However, consider that 
    //   1) only p is given and
    //   2) that it is not known that p points to an object of type D<int>.
    // How to modify B or D to be able to invoke the correct instantiation of F here
    // , i.e. that for the type of "int"?
    return 0;
}

Upvotes: 0

Views: 1380

Answers (2)

Miles Budnek
Miles Budnek

Reputation: 30494

You could use a callback along with a virtual member function to call it:

class B
{
public:
    virtual ~B() = default;
    virtual void call() const = 0;
};

template <typename T>
class D : public B
{
public:
    explicit D(T t, std::function<void(T)> cb)
        : x(std::move(t)),
          callback(std::move(cb))
    {
    }
    void call() const override
    {
        callback(x);
    }
private:
    T x;
    std::function<void(T)> callback;
};

int main()
{
    D<int> o(3, F<int>);
    B* p = &o;
    p->call();
)

Live Demo

Upvotes: 0

Jarod42
Jarod42

Reputation: 217275

You might do

class B
{
public:
    virtual ~B() = default;
    virtual void f() const = 0;
};

template<typename T>
class D : public B
{
public:
    void f() const override { F(x); }
private:
    T x;
};

Demo

Upvotes: 1

Related Questions