5

My intention in the following code is to be able to call a virtual function with a lambda as its parameter. The way I go about it is clearly not right, as virtual templates are not allowed.

Is there some way around it?

// polymorphic base class
struct B {
    virtual void    set_val(int)    = 0;
    virtual int     get_val()       = 0;
    virtual void    set_next(B*)    = 0;

    template<typename FCall_T>  // compiler error: no virtual templates allowed
    virtual void for_each_node_do(FCall_T) = 0;
};

// derived class
struct D :
    public B
{
    int     val;
    D*      p_next;

    void    set_val(int i)      override { val = i; }
    int     get_val()           override { return val; }
    void    set_next(B* p_next_)override { p_next = dynamic_cast<D*>(p_next_); };

    template<typename FCall_T>
    void for_each_node_do(FCall_T fnc) override {
        fnc(this);

        D* p_cur = p_next;
        while(p_cur) {
            fnc(p_cur);
            p_cur = p_cur->p_next;
        }
    }
};

int main() {
    // set up linked list
    int cnt = 5;
    B** ppB = new B*[cnt];      // array of base class ptrs
    for(int i = 0; i < cnt; ++i)
        ppB[i] = new D;
    for(int i = 0; i < cnt; ++i) {
        ppB[i]->set_val(i);
        ppB[i]->set_next( (i < cnt-1) ? ppB[i+1] : nullptr);
    }
    B* p_root = ppB[0];         // base class ptr

    // do something thru base class ptr
    p_root->for_each_node_do(
        [](B* pB){
            pB->set_val(pB->get_val() * 10);
        }
    );

    // do something else thru base class ptr
    p_root->for_each_node_do(
        [](B* pB){
            cout << pB->get_val() << endl;
        }
    );

    return 0;
}

I considered declaring B::for_each_node_do() as:

virtual void for_each_node_do(void(*)(B*)) = 0;

...and declaring as many free functions to use as its parameter as necessary, but as I stated above, I am wondering if there is a way to make it work with lambdas as its parameter.

Kemal
  • 849
  • 5
  • 21

0 Answers0