【问题标题】:How to make the lambda a friend of a class?如何让 lambda 成为班级的朋友?
【发布时间】:2014-02-08 14:08:30
【问题描述】:

比方说,我有一堂课:

class A {
  int a;
};

我有一个 lambda:

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

function(new A);

有没有办法在 lambda 中使用私有成员/方法? - 没有必要将指针传递给 lambda - 它可能是 capture-by 或其他东西。

欢迎所有合理的方案。

【问题讨论】:

  • 为什么不直接使用std::function 类型? en.cppreference.com/w/cpp/utility/functional/function
  • 你能给出一个用例吗? lambda 可以通过多种潜在方式访问私有成员,但在不了解用例的情况下尚不清楚哪种方法是可接受的。
  • @user2485710 std::function 类型如何帮助我访问 lambdas 中的私有成员?
  • @abyss.7:也许你想让你的测试班成为朋友。
  • 请注意,如果 lambda 在类的范围内定义,它确实可以访问私有成员。

标签: c++ c++11 lambda friend


【解决方案1】:

您可以通过创建一个返回 lambda 函数的友元函数来实现。它继承了好友访问权限:

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;
}

【讨论】:

  • 我会给f 一个返回类型auto 并延迟类型擦除,直到调用者需要它。这将使编译器更容易内联并可能对返回的闭包对象的直接使用执行其他优化(例如,使用 clang 和 -Ofast 执行替换和编译实际上导致调用 A::test内联到main)。
  • f() 不返回 lambda 函数。它返回类型擦除的std::function,其中包含一个 lambda。
【解决方案2】:

为了使 lambda 成为朋友,您需要与定义了 lambda 的类或函数成为朋友。这是一个完整的例子:

#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.

【讨论】:

  • 我从你的回答中了解到,使用“友好”的 lambda 根本没有意义,是吗? - 由于每个 lambda 定义都应该放在 friend 函数中,所以,我可以使用 friend 函数本身。
  • @abyss.7 并非如此:您可以在友元函数或友元类中生成 lambda,然后在友元函数/类之外的其他地方使用它们。例如,您可以将您的function 声明为A 的朋友类B 的公共成员,然后使用B::function 执行需要访问A 的私有成员的事情。
【解决方案3】:

使用 std::function 需要额外的资源,所以我建议使用朋友/或方法函数来访问私有成员(朋友函数隐式内联):

class A{
    int a;

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

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

Live example

编辑:我个人喜欢 std::function,但不要忘记,std::function 总是占用额外的内存资源,并且可能不会内联,所以如果你可以在没有 std::function 的情况下实现你的源代码,不要使用 std::function。 见,How is std::function implemented? 另外,Lambda to std::function conversion performance

【讨论】:

    猜你喜欢
    • 2016-02-27
    • 2011-03-23
    • 1970-01-01
    • 2013-06-07
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多