如何在C 中提供一个可呼叫的对象访问,例如lambda

How to provide a callable object protected access like lambda in C++?

本文关键字:呼叫 一个 对象 访问 lambda 例如      更新时间:2023-10-16

我有一个lambda,我需要转换为可呼叫的对象,以便我可以专门使用呼叫操作员。我的印象一直是,具有void(auto)签名的lambda等同于这样的可呼叫结构:

struct callable {
    Foo & capture;
    template< typename T >
    void operator()( T arg ) { /* ... */ }
}

但是,lambda在成员函数中声明时可以访问私人和受保护的成员。

这是一个简化的示例:

#include <iostream>
using namespace std;
class A {
protected:
    void a() { cout << "YES" << endl; }
};
class B : public A {
public:
    void call1();
    void call2();
};

struct callable {
    B * mB;
    void operator()() {
        // This does not compile: 'void A::a()' is protected within this context
        // mB->a();
    }
};
void B::call1() {
    // but then how does this access a() ?!
    [&]() { a(); }();
}
void B::call2() {
    callable c{ this };
    c();
}

int main()
{
    B b;
    b.call1();
    b.call2();
}

是否有任何方法可以在可呼出的结构中模仿这种行为,而无需在标题中宣布它并将其作为朋友类?这似乎是有问题的,因为我会有很多不同的可喊声。我也只是对此感到好奇,因为我的印象是lambdas在功能上与用呼叫操作员声明结构相同。

lambda的访问权限捕获了这一点,似乎说lambda的访问权限与本地班级相同。但是就我而言,我需要效仿通用的lambda,而本地类则不能具有模板成员函数。

您仍然可以捕获this&B::a

struct callable {
    B* mB;
    void (A::*m)();
    void operator()() const {
        (mB->*m)();
    }
};
void B::call2() {
    callable c{ this, &B::a };
    c();
}

demo

您可以在不提供定义的情况下使struct callable A的CC_4 A friend。在遇到真实声明之前,这样的声明甚至没有使名称可见:

class B : public A {
  // ...
  friend struct callable;
}
// ERROR: callable isn't visible here:
// callable *foo;

如果简短非常重要,则可以将其扩展到大量的朋友中,并以一份声明为例:

class B : public A {
  // ...
  template<int> friend struct callable;
};
// In implementation:
template<>
struct callable<0> { /* ... */ };
template<>
struct callable<1> { /* ... */ };