如何在C ++中提供像lambda这样的可调用对象保护访问?

时间:2017-09-11 23:47:40

标签: c++ lambda c++14

我有一个lambda,我需要将其转换为可调用对象,以便我可以专门调用call运算符。我的印象一直是带有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();
}

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

这是一个简化的例子:

{{1}}

有没有办法在可调用的结构中模拟该行为,而不在标题中声明它并使其成为朋友类?这似乎有问题,因为我将有很多不同的callables。我也对此感到好奇,因为我的印象是lambdas在功能上与声明带有调用操作符的结构相同。

Access rights of a lambda capturing this似乎说lambda具有与本地类相同的访问权限。但就我而言,我需要模拟一个通用的lambda,本地类不能有模板成员函数。

2 个答案:

答案 0 :(得分:2)

您仍然可以捕获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

答案 1 :(得分:0)

您可以struct callablefriend B而不提供其定义。在遇到真正的声明之前,这样的声明甚至不会使名称可见:

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> { /* ... */ };