2

Here is what I try to achieve:

class MyClass
{
public:
    using Callback = void(MyClass::*)(uint8_t idx);
    void forEach(Callback callback);

private:
    int       m_buf[64];

    int       m_x;
    int       m_y;
    MyObject  m_object;
}

void MyClass::forEach(Callback callback)
{
    size_t s = m_object.size();
    for(size_t i = 0; i < s; i++)
        callback(i);
}

void MyClass::f1()
{
    forEach([this](uint8_t idx)
    {
        m_buf[idx]++;
    });
}

void MyClass::f2()
{
    forEach([this](uint8_t idx)
    {
        m_buf[idx] = m_x + m_y * idx;
    });
}

So there are a bunch of ways to modify m_buf[]. In order to avoid copying and pasting 'get size + for loop', I want to add a forEach method and pass lambdas as callbacks. this is captured to have access to class members.

What is the right way to achieve the same result?
Thanks.

PS: compilation of this example returns error 'cannot convert ::lambda ....'

ANSWER: With "Passer By" answer, I finished with the code:

// Class declaration in header
using Callback = std::function<void(uint8_t)>;
void forEach(Callback callback);

// forEach() is as above
// forEach() call looks like
forEach([this](uint8_t idx) {
    m_buf[idx] = m_x + m_y * idx;
});

Also I found some related questions-anwers which might be useful

Passing lambda as function pointer - "5gon12eder" answer.
C++ lambda with captures as a function pointer

Community
  • 1
  • 1
user3124812
  • 1,861
  • 3
  • 18
  • 39

1 Answers1

2

You have mistaken the semantics of a member function pointer

void (MyClass::*)(uint8_t idx)

is a pointer to a member function of MyClass that accepts a uint8_t, it is not anything else. You call it as

MyClass::Callback c = &MyClass::SomeMemberFunction;
MyClass mc;
(mc.*c)(0); // equivalent to...
mc.SomeMemberFunction(0);

Secondly, the purpose of for_each is so that the callable object passed in need not know the internals of the object, as such, you shouldn't pass in an index in the loop.

What you actually want is to pass in a callable object accepting a reference called on each object. This can be done in two ways

template<typename Callable>
void for_each1(Callable&& call)
{
    for(size_t i = 0; i < size(); i++)
        call(m_buf[i]);
}

#include<functional>

void for_each2(std::function<void (int&)>&& fn)
{
    for(size_t i = 0; i < size(); i++)
        fn(m_buf[i]);
}

Both can be called with a lambda

MyClass mc;
mc.for_each1([](int& i) { i++; });
mc.for_each2([&mc](int& i) { i += mc.increment(); });

where mc.increment is what that instance wants to be incremented by.

Quentin
  • 62,093
  • 7
  • 131
  • 191
Passer By
  • 19,325
  • 6
  • 49
  • 96