Home > Software engineering >  c lambda inside member class function, is it possible?
c lambda inside member class function, is it possible?

Time:06-11

I have a base class with a vector of pointers, and I think to slide the vector outside this class, I wrote the for_each() method:

 class model {
   static std::vector<model*> models;
  ...
   public:
    template <class C>
    static void for_each(C *c,void (C::*f)(model *))
     {
      for (std::vector<model*>::iterator it=models.begin(); it!=models.end();   it) {
      c->f(*it);
     }
   ...
  }

I tryed to use for_each() in a member function:

void v_context::build_cmd()
{
 ...
 auto f1=[&](model* m)->void{commandBuffers.push_back(*(m->build_secondary_buffers(inheritanceInfo, pipelines.gltf)));};
 model::for_each<VulkanExample,void (VulkanExample::*)(model*)>(this,f1);
 ...
}

The compiler (gcc version 10.2.1 20210110 (Debian 10.2.1-6)), rightly returns the error:

error: cannot convert ‘v_context::build_cmd()::<lambda(model*)>’ to ‘void (v_context::)(model)’

note: initializing argument 2 of ‘static void model::for_each(C*, void (C::)(model)) [with C=v_context]’

Is it possible? Does correct syntax template exist?

CodePudding user response:

The simplest is probably to make it even more generic:

class model {
    static std::vector<model *> models;
public:
    template <class Func>
    static void for_each(Func&& func) { // no instance needed
        for (auto ptr : models) {       // simplified loop
            func(ptr);
        }
    }
};

Then just capture [this] in the lambdas you use it with:

void VulkanExample::build_cmd() {
    auto f1 = [this](model *m) {
        // ...
    };
    model::for_each(f1);
}

Demo

CodePudding user response:

You could use std::invoke to implement this logic. A class and a member function pointer this would require swapping the parameters, but otherwise this would allow you to pass any number of additional parameters before the model* parameter:

class model
{
...

    template <class F, class...Args>
    static void for_each(F&& f, Args&&...args)
    {
        for (auto p : models)
        {
            std::invoke(f, args..., p);
        }
    }
    ...

};

Example usages:

struct Foo
{
    void Bar(model*) {}
};

...

Foo foo;
model::for_each(&Foo::Bar, foo);
model::for_each([&](model* m)->void{commandBuffers.push_back(*(m->build_secondary_buffers(inheritanceInfo, pipelines.gltf)));});
  • Related