C++ 如何在C+中提供像lambda这样的可调用对象保护访问+;?
我有一个lambda,我需要将它转换成一个可调用对象,以便专门化调用操作符。我的印象一直是,带有C++ 如何在C+中提供像lambda这样的可调用对象保护访问+;?,c++,lambda,c++14,C++,Lambda,C++14,我有一个lambda,我需要将它转换成一个可调用对象,以便专门化调用操作符。我的印象一直是,带有void(auto)签名的lambda相当于大致如下所示的可调用结构: struct callable { Foo & capture; template< typename T > void operator()( T arg ) { /* ... */ } } struct可调用{ Foo&capture; 模板 void运算符()(T arg){/
void(auto)
签名的lambda相当于大致如下所示的可调用结构:
struct callable {
Foo & capture;
template< typename T >
void operator()( T arg ) { /* ... */ }
}
struct可调用{
Foo&capture;
模板
void运算符()(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();
}
#包括
使用名称空间std;
甲级{
受保护的:
void a(){cout您仍然可以捕获此
和&B::a
struct callable {
B* mB;
void (A::*m)();
void operator()() const {
(mB->*m)();
}
};
void B::call2() {
callable c{ this, &B::a };
c();
}
您可以使B
的struct可调用afriend
,而无需为其提供定义。在遇到真正的声明之前,这样的声明甚至不会使名称可见:
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> { /* ... */ };
B类:公共A类{
// ...
模板友元结构可调用;
};
//在执行中:
模板
结构可调用{/*…*/};
模板
结构可调用{/*…*/};
OP声明“未在标头中声明并使其成为朋友类?”。您不必在标头中给出callable
的完整定义。我不清楚OP是否认为转发声明是“在标头中声明”.是的,将父类声明为friend并从该类继承可能是一个不错的解决方案,如果friend status是继承的。不幸的是,它不是。您可以使用我添加的模板hack简洁地创建许多friend。(这避免了让一个朋友为您想要使用的a
的每个成员提供转发功能。)聪明!但是,让我惊讶的是,在实例化callable时,使用'void a::a()'编译时的错误在此上下文中受到保护。您必须使用&B::a
。“这样我就可以专门负责呼叫接线员了”——听起来真的是个糟糕的计划。为什么,你愿意重新考虑吗?过载更容易造成麻烦。