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

3
  • 2
    Please make your question title describe the question, not just list things Commented May 11, 2017 at 9:48
  • 2
    Furthermore this question is not clear. Does the code you posted not work? If not, in what way? And what did you want to do instead? (we cannot deduce that from code that doesn't do that thing) Commented May 11, 2017 at 9:49
  • 2
    Please include actual error messages. They're not random gibberish, but useful information, and truncating them does not help. Commented May 11, 2017 at 10:22

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

@Quentin Goes to show I don't actually use pointers to member function at all, my (very) bad. Thanks.
No worries :) -

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.