13

Let's say, I have a class:

class A {
  int a;
};

And I have a lambda:

auto function = [](A* a) {
  a->a;  // <== gives an error in this line.
};

function(new A);

Is there any way to use a private member/method inside a lambda? - It's not necessary to pass the pointer to the lambda - it may be a capture-by or something else.

All reasonable schemes are welcome.

abyss.7
  • 13,882
  • 11
  • 56
  • 100
  • 1
    why not just use the `std::function` type ? http://en.cppreference.com/w/cpp/utility/functional/function – user2485710 Feb 08 '14 at 14:18
  • 1
    Could you give a use case for this? There are many potential ways that the lambda might gain access to the private members, but it isn't clear what approach is acceptable without knowing a use case. – Vaughn Cato Feb 08 '14 at 14:19
  • 2
    @user2485710 how the `std::function` type would help me with accessing private members inside lambdas? – abyss.7 Feb 08 '14 at 14:19
  • @abyss.7 I dind't realize this was your intention, but I still have my doubts about this kind of design choices. – user2485710 Feb 08 '14 at 14:36
  • @VaughnCato I want to use lambdas as callbacks, that I pass to my mock object (say, `test_process->CallOnRun([](...) {...})`) - the callback will be called on some reasonable action, like `virtual Process::Run()`, and check some internal states of the base class - in unit-tests. Thus, each callback have to do different checks. I want to use lambdas for this purpose, but it looks like, it's not the best approach. If my example is not clear enough, I can post it as a part of my question. – abyss.7 Feb 08 '14 at 14:47
  • 1
    @abyss.7: Perhaps you want to make your testing class a friend. – Vaughn Cato Feb 08 '14 at 14:54
  • @VaughnCato And that's what I came to. Especially, since my test framework is `gtest`... – abyss.7 Feb 08 '14 at 14:59
  • 1
    Note that if the lambda is *defined* in the scope of the class, it *does* have access to private members. – Kyle Strand Jan 19 '16 at 18:31

3 Answers3

16

You can do it by creating a friend function that returns the lambda function. It inherits the friend access:

struct A {
  friend std::function<void(A&, int)> f();

  private:
    int i;
    void test() {std::cout << "test: " << i << "\n";}
};

std::function<void(A&, int)> f() {
  return [] (A &a, int i) {a.i = i; a.test(); };
}

int main() {
    A a;
    f()(a, 13);

    return 0;
}
Jaa-c
  • 5,017
  • 4
  • 34
  • 64
  • 3
    I would give `f` a return type of `auto` and delay the type erasure until the caller needs it. That'll make it a lot easier for the compiler to inline and possibly perform other optimizations on direct uses of the returned closure object (for example, performing the replacement and compiling with clang and `-Ofast` actually resulted in the call to `A::test` being inlined into `main`). – Stuart Olsen Feb 08 '14 at 21:49
  • `f()` doesn't return a lambda function. It returns type-erased `std::function` that holds a lambda inside it. – Evg May 01 '20 at 15:12
5

In order to make a lambda a friend, you need to befriend a class or a function where the lambda is defined. Here is a complete example:

#include <iostream>
using namespace std;

class A {
  int a;
public:
    A(int _a) : a(_a) {}
    friend int foo(A*); // Declare foo(A*) a friend of A
};

int foo(A* aa) {
    auto function = [](A* a) {
        return a->a;    // Now foo(A*) can access A::a, which is private
    };
    return function(aa);
}

int main() {
    A a(123);
    cout << foo(&a) << endl;
    return 0;
}

Here is a running demo on ideone.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • As I understand from your answer, there is no point in using "friendly" lambda at all, is it? - Since each lambda definition should be placed inside `friend` function, so, instead, I may use the `friend` function it-self. – abyss.7 Feb 08 '14 at 14:37
  • @abyss.7 Not really: you can produce lambdas inside a friend function or a friend class, and then use them elsewhere, outside of a friend function/class. For example, you can declare your `function` as a public member of a class `B` that is a friend of `A`, and then use `B::function` to perform things that require access to `A`'s private members. – Sergey Kalinichenko Feb 08 '14 at 14:42
2

using std::function takes extra resource, so I recomendet using friend/or method function to access private member (friend function implicit inlined):

class A{
    int a;

    friend int access_member(A*a){ return a->a;}
};

-----------------------------------------
auto function = [](A*a){   return access_member(a); }

Live example

EDIT: I personally like std::function, but don't forgot, std::function always takes extra memory resources, and may not inlined , so if you may implement your source without std::function, don't use std::function. See, How is std::function implemented? Also, Lambda to std::function conversion performance

Community
  • 1
  • 1
Khurshid
  • 2,654
  • 2
  • 21
  • 29