4

I need to generate some members/methods of a class with a script. I'm trying to break up this class in two, with base class being generated members, and derived class having hand coded members. However, I'm getting stuck in figuring out how to call derived member function D::f2() from the base class B::f1().

Here is the simplified code:

#include <cstdio>

template <typename _T>
class B { 
public:
    void f3() {
        puts("okay");
    }
    void f1() {   
        f2();   // What C++ Magic to call f2() properly !!!
    }
};

class D : public B<D> {
public:
    void f2() {
        f3();
    }

};

int main() {
    D d;
    d.f1();
}

Is there any way, I can call D::f2() from B::f1() without using virtual functions ?

Added later:

If we do pointer manipulation, we will end up with injection, and I understand it's not a good idea, and I'll take the advice of not doing it. Let's stop that thread.

I am trying to find a solution using template only. I can generate any complex thing for the generated code. It can even be a several functors etc. However the hand coded written part should be hand-codable.

vrdhn
  • 4,024
  • 3
  • 31
  • 39
  • How about dynamic_cast<_T>(this)->f2();? ( not writing this as answer as needs proper formating and more expanded answer about how there is a deper problem probably ) – UldisK Dec 16 '13 at 14:20
  • @UldisK - there are no virtual functions, so dynamic_cast will not work! – Sean Dec 16 '13 at 14:20
  • 2
    You shouldn't be using [reserved names](http://stackoverflow.com/questions/228783) like `_T`. – Mike Seymour Dec 16 '13 at 14:26
  • @Vardhan - if you don't want to use virtual functions, which are there to solve problems like this, then you're going to have to use some sort of compromise solution. You can avoid injecting the derived name into the base class by using the type parameter, as I've done in my answer. – Sean Dec 16 '13 at 14:30
  • @Vardhan As soon as you call `f2()` which is defined only in your derived class, you "inject" the derived into the base. – Johan Dec 16 '13 at 14:36
  • yes @sean, i realized later that using type parameters will avoid injection of derived class name. However I'm still convinved that a template based scheme is possible, probably using functor etc, .. – vrdhn Dec 16 '13 at 14:37

5 Answers5

7

If you really really really want to do it:

static_cast<_T*>(this)->f2();

As people have mentioned, this is the curiously recuring template pattern!

Dinei
  • 4,494
  • 4
  • 36
  • 60
Sean
  • 60,939
  • 11
  • 97
  • 136
  • 4
    @IvayloStrandjev - there are no virtual functions, dynamic_cast will not work! – Sean Dec 16 '13 at 14:19
  • Care to explain that comment @Sean? – Eric Dec 16 '13 at 14:24
  • 3
    @Eric - dynamic_cast requires RTTI to be available in order to check the cast. This information is placed alongside the vtable, and you need at least one virtual function for your class to have a vtable. – Sean Dec 16 '13 at 14:26
1

This is a typical Curiously recuring template pattern. You can do:

template <typename _T>
class B { 
public:
     void f3() {
      puts("okay");
     }
     void f1() {      
      static_cast<_T>(this)->f2();
     }

};
Johan
  • 3,728
  • 16
  • 25
0

A base class should have no notion of its children. Attempt to call a child method from base class is a sure sign of bad architecture. Virtual functions will not help you here by the way.

If you have to call a child's function from the base class you can do so just like you would do from any other function in your code. Still you will need an instance of the base class to call it on or alternatively you will have to static_cast the this pointer to a pointer of the child class type. This is a very bad idea!

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
  • This is a known pattern, nothing fancy. [Even referenced on isocpp blog site !](http://isocpp.org/blog/tag/crtp) – Johan Dec 16 '13 at 14:33
  • While this is the CRTP, I disagree with the downvote. Using this pattern is *usually* (though, not always) a sign of a poor design. – Zac Howland Dec 16 '13 at 14:36
  • @Johan actually reading through the link you posted the author is not suggesting to use similar solution. Appart from a good c++11 solution he suggests using macros – Ivaylo Strandjev Dec 16 '13 at 14:43
  • 1
    @IvayloStrandjev The problem presented in this paper is quite more complicated. I was just pointing out that this a well-known, well established design. And one where parent class **does** know the child. – Johan Dec 16 '13 at 14:52
0

You can use the Curiously Recurring Template Pattern.

kwanti
  • 435
  • 2
  • 8
0

There is another way, but at the cost of an ugly C style/reinterpret cast:

#include <cstdio>
#include <functional>


class B { 
public:
    typedef std::function<void (B*)> Function;    

    void f3() {
        puts("okay");
    }
    void f1() {   
        _func(this);
    }

    Function _func;
};

class D : public B 
{
public:
    D()
    {
        _func = (void (B::*)()) &D::f2; // Here is the awfull cast I hate to do
    }

    void f2() {
        f3();
    }

};

int main() {
    D d;
    d.f1();
}

http://ideone.com/yOR0xT

I find this a lot less clean than the CRTP, because you have no compile time check...

Community
  • 1
  • 1
Johan
  • 3,728
  • 16
  • 25