2017-09-11 16 views
4

我有一個lambda,我需要轉換成一個可調用對象,以便我可以專門調用操作符。我的印象一直是與void(auto)簽名拉姆達相當於一個可調用的結構大致是這樣的:如何在C++中提供可調用的對象保護訪問像lambda?

struct callable { 
    Foo & capture; 

    template< typename T > 
    void operator()(T arg) { /* ... */ } 
} 

然而,當一個成員函數中聲明的拉姆達可以訪問private和protected成員。

這裏有一個簡單的例子:

#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函數在功能上與使用調用操作符聲明結構相同。

Access rights of a lambda capturing this似乎認爲lambda具有與本地類相同的訪問權限。但在我的情況下,我需要模擬一個通用的lambda,本地類不能有模板成員函數。

+1

「這樣我就可以專門調用操作符」 - 聽起來像是一個糟糕的計劃。爲什麼,你是否願意重新考慮?超載更爲緊張。 – Yakk

回答

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

+0

聰明!但是 - 令我驚訝的是,在實例化可調用時,用'void A :: a()'進行編譯的錯誤在此上下文中受到保護。 http://coliru.stacked-crooked.com/a/8bc612b89ab1dc5e – Ian

+0

您必須改用'&B :: a'。 – Jarod42

0

可以使struct callableB一個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> { /* ... */ }; 
+0

OP狀態*「沒有在標題中聲明它並將它變成朋友類?」*。 – Jarod42

+0

您不必在標題中給出'callable'的完整定義。我不清楚OP是否認爲前向聲明是「在聲明中聲明」。 –

+0

是的,如果朋友狀態是繼承的,那麼聲明一個父類是一個朋友並且繼承這個類可能是一個好的解決方案。不幸的是,它不是。 – Ian

相關問題