0

I have a case where I can pass a lambda to std::sort, and I can also supply the predicate by calling a function that returns a std::function which wraps this same lambda, but, if I try to call a similar function which allows me to specify a pointer to member function, this compiles but fails at run time.

This works:

std::sort(myContainer.begin(), myContainer.end(), [&](type lhs, type rhs)
{
    return MyMemberFunction(lhs, rhs);
});

And this works:

std::function<bool(type,type)> ReturnPred()
{
    std::function<bool(type,type)> pred = [&](type lhs, type rhs)
    {
        return MyMemberFunction(lhs, rhs);
    };
    return pred;
}

std::sort(myContainer.begin(), myContainer.end(), ReturnPred());

But this does not work:

std::function<bool(type,type)> ReturnGeneralPred(
     bool(MyClass::Func*)(type lhs, type rhs))
{
    std::function<bool(type,type)> pred = [&](type lhs, type rhs)
    {
        return (this->*Func)(lhs, rhs);
    };
    return pred;
}

std::function<bool(type,type)> ReturnThisPred()
{
    return ReturnGeneralPred(&MyClass::MyMemberFunction);
}

std::sort(myContainer.begin(), myContainer.end(), ReturnThisPred());

When I try to do it this last generic way and I step through the debugger, when std::sort calls the predicate, it steps into what I've call ReturnGeneralPred above, and Func seems to be undefined, as though it was a local variable that went out of scope.

At the moment I can get the same functionality by losing some genericness, but I was wondering if maybe there's a way to accomplish what I was trying to do.

  • Try to capture local `Func` by value instead of by reference. – Jarod42 Dec 30 '13 at 10:46
  • "Func seems to be undefined, as though it was a local variable that went out of scope.". I'm almost tempted to close this as "Missing an actual question.", given that the only apparent question is already answered. – MSalters Dec 30 '13 at 17:40
  • I didn't quite catch the fact that it wouldn't store a pointer it could see by reference for later use, but that would functionally be a pointer copy anyway, so the below answer makes sense to me now. Thanks =) – Charles J. Daniels Jan 01 '14 at 08:15

1 Answers1

1

Func is local to ReturnGeneralPred, and the lambda is used when Func is out of its scope (dangling pointer).
Capture Func by copy should solve your issue:

std::function<bool(type,type)> ReturnGeneralPred(bool(MyClass::Func*)(type lhs, type rhs))
{
    std::function<bool(type,type)> pred = [this, Func](type lhs, type rhs)
    {
        return (this->*Func)(lhs, rhs);
    };
    return pred;
}

or use [=] syntax instead of explicit capture [this, Func].

Jarod42
  • 203,559
  • 14
  • 181
  • 302