Derive class template function call

I had a problem in C ++ with calling a function of a derived class with a pointer to a base class.

EDIT: Some answers referred to CRTP

but I want to say that I need to have a pointer to the "Base *" class, and not "Base *", because I do not know about the current type being processed (the current instance is created from a kind of factory).

Classes:

class Base 
{
..
template<typename T>
func (T arg) { ... };
};

class Derived1 : public Base
{
...
template<typename T>
func (T arg) { ... };
};


class Derived1 : public Base
{
...
template<typename T>
func (T arg) { ... };
};

Using:

int main()
{
   Base* BasePtr = new Derived1();

   // The expected function to be called is Derived1::func<int>()
   BasePtr->func<int>();

   return 0; // :)
}

I cannot make func virtual, because the language does not support the virtual template function.

Permitted only if the class has template arguments, but not if the function inside it has template arguments.

I saw a similar problem resolved in Boost.Serialization, but could not figure out the solution.

Thank,

Koby Meir

+5
3

. , , : CRTP , . Derived1 Derived2 , ... , , , . .

, ( , , ). , Base, - . , Base, apply, :

class Base;
class Derived1;  // inherits from Base, implements Visitor
class Derived2;  // inherits from either Base or Derived2
struct Visitor {
   virtual void visit( Base& ) = 0;     // manually unrolled for all types
   virtual void visit( Derived1& ) = 0;
   virtual void visit( Derived2& ) = 0;
};
struct Base {
   virtual void apply( Visitor& v ) {   // manually replicate this in Derived1, 2
      v.visit( *this );
   }
   template <typename T> void foo(T);   // implement 
};

template <typename T>
struct FooCaller : Visitor {
    T& ref_value;
    FooCaller( T& v ) : ref_value(v) {}
    template <typename U> void call_foo( U& o ) {
       o.foo(ref_value);
    }
    virtual void visit( Base & b )      { call_foo(b); }
    virtual void visit( Derived1 & d1 ) { call_foo(d1); }
    virtual void visit( Derived2 & d2 ) { call_foo(d2); } 
};

, , Visitor, ( , , ).

:

int main()                     // main returns int, not void!!!
{
   Base* BasePtr = new Derived1();
   int i = 5;
   FooCaller<int> c(i)
   BasePtr->apply(c);          // [1] magic happens here
}

i c , ( ) const-. , [1] ++ Derived1::apply, , BasePtr. Visitor::visit( Derived1& ) . FooCaller<int>::visit( Derived1& ), . FooCaller<int>::visit call_foo, U Derived1, Derived1::foo, int, Derived1::foo<int>... ...

( , CRTP, ) ( : Base Visitor), , , . .

, , , , , ... , , , , .

, ++, , , , : .

+5

(CTRP).

:

template<typename D>
class Base 
{
public:
    template<typename T>
    void func (T arg) 
    {
         static_cast<D*>(this)->func(arg);
    }
};

class Derived1 : public Base<Derived1>
{
public:
    template<typename T>
    void func (T arg) { /*...*/ }
};


Base<Derived1> *basePtr = new Base<Derived1>();
basePtr->func(100);
+5

Check this box to help you implement CRTP.

+2
source

All Articles