我有一个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,本地类不能有模板成员函数。
答案 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();
}
答案 1 :(得分:0)
您可以struct callable
成friend
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> { /* ... */ };