leJon
leJon

Reputation: 295

Inheritance and template function c++

I was wondering if there are pattern/ways to inherit template functions ? Template functions can not be virtual so if my base class has a template function and my derived class has the same, the function of the base class will always be called in the following example :

struct Base {
    Base() {}
    template < typename T >
    void do_something(T&  t) const {
        t << "Base" << std::endl ;
    }
    };

struct Foo : Base {
    Foo() : Base () {}
    template < typename T >
    void do_something(T&  t) const {
        t << "Foo" << std::endl ;
    }
};

struct Bar : Foo {
    Bar() : Foo() {}
    template < typename T >
    void do_something(T&  t) const {
        t << "Bar" << std::endl ;
    }
};


int main(int argc, char** argv)
{

    Base *b = new Base() ;
    Base *f = new Foo() ;
    Base *ba = new Bar() ;

    b->do_something(std::cout) ;
    f->do_something(std::cout) ;
    ba->do_something(std::cout) ;

    return 0 ;
}

So this program always print :

Base
Base
Base

Is there a way to make my program print :

Base
Foo
Bar

Actually the only way I found for doing that is to make a static_cast :

...
static_cast<Foo*>(f)->do_something(std::cout) ;
static_cast<Bar*>(ba)->do_something(std::cout) ;
...

Is there any pattern or elegant way to encapsulate the cast so that it will be unnoticeable from the function call ? Thanks for your replies

Upvotes: 6

Views: 7449

Answers (2)

GermaineJason
GermaineJason

Reputation: 589

Do you have the option to change the struct to a Template class rather than template methods?

If so:

Template<typename T>
struct Base
{
public:
    virtual void doSomething();
 };


Template<typename T>
struct Foo : Base<T>
{
public:
    virtual void doSomething();
};

Upvotes: 1

aschepler
aschepler

Reputation: 72271

You can almost always do what you need by splitting the function into smaller parts, making each part templated if necessary, or virtual if necessary. In this example, that's as simple as:

struct Base {
    Base() {}
    template < typename T >
    void do_something(T&  t) const {
        t << something_piece() << std::endl ;
    }
    virtual const char* something_piece() const {
        return "Base";
    }
};

struct Foo : Base {
    Foo() : Base () {}
    const char* something_piece() const {
        return "Foo";
    }
};

struct Bar : Foo {
    Bar() : Foo() {}
    const char* something_piece() const {
        return "Bar";
    }
};

It can get more complicated than that, but the idea is pretty powerful at combining compile-time and run-time differences.

Upvotes: 4

Related Questions