Извлечь тип шаблона производного класса из указателя базового класса - PullRequest
0 голосов
/ 07 сентября 2018

Рассмотрим следующее:

  1. класс B
  2. класс Д , который
    • является производным от класса B ,
    • имеет параметр шаблона T ,
    • имеет переменную-член x типа T
  3. шаблон функции F с
    • параметр шаблона S
    • параметр y типа S .
  4. указатель p , который
    • имеет тип B *
    • указывает на объект o класса D с параметром шаблона T , равным, например, INT
  5. что функция F не может быть изменена.
  6. F нельзя вызывать напрямую из классов B или D

Кроме того, учтите, что указывается только указатель p и что F следует вызывать с параметром y , равным переменной-члену x объекта o (это означает, что тип S равен int ).

Как можно изменить классы B и D для достижения этой цели? Я предполагаю, что нужен какой-то механизм для получения шаблона типа T . Но я не знаю, как это сделать.

Вот соответствующий код:

Файл 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; 
}
//////////// -----------------------------

Файл BD.h:

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

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

Файл 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;
}

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

Вы можете использовать обратный вызов вместе с функцией виртуального члена, чтобы вызвать его:

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

0 голосов
/ 07 сентября 2018

Вы могли бы сделать

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

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...