2014-02-08 4 views
8

Lassen Sie uns sagen, ich habe eine Klasse:Wie mache ich den Lambda zu einem Klassenkameraden?

class A { 
    int a; 
}; 

Und ich habe eine Lambda:

auto function = [](A* a) { 
    a->a; // <== gives an error in this line. 
}; 

function(new A); 

Gibt es eine Möglichkeit ein eigenes Mitglied/Verfahren in einem Lambda zu benutzen? - Es ist nicht notwendig, den Zeiger an das Lambda zu übergeben - es kann ein Capture-By oder etwas anderes sein.

Alle angemessenen Schemata sind willkommen.

+0

Warum nicht einfach den 'std :: function' Typ verwenden? http://en.cppreference.com/w/cpp/utility/functional/function – user2485710

+1

Könnten Sie einen Anwendungsfall dafür geben? Es gibt viele mögliche Wege, wie das Lambda Zugang zu den privaten Mitgliedern erhalten könnte, aber es ist nicht klar, welcher Ansatz akzeptabel ist, ohne einen Anwendungsfall zu kennen. –

+2

@ user2485710 Wie würde mir der 'std :: function' -Typ beim Zugriff auf private Mitglieder in Lambdas helfen? –

Antwort

12

Sie können es tun, indem Sie einen Freund-Funktion erstellen, die die Lambda-Funktion zurückgibt. Es erbt den Zugang Freund:

struct A { 
    friend std::function<void(A&, int)> f(); 

    private: 
    int i; 
    void test() {std::cout << "test: " << i << "\n";} 
}; 

std::function<void(A&, int)> f() { 
    return [] (A &a, int i) {a.i = i; a.test(); }; 
} 

int main() { 
    A a; 
    f()(a, 13); 

    return 0; 
} 
+1

Ich würde 'f' einen Rückgabetyp von' auto' geben und den Typ löschen, bis der Anrufer es benötigt. Das erleichtert dem Compiler das Inline-Inline-Verfahren und führt möglicherweise andere Optimierungen bei der direkten Verwendung des zurückgegebenen Closure-Objekts durch (z. B. führte das Ersetzen und Kompilieren mit "clang" und "-Ofast" tatsächlich zum Aufruf von "A" :: Test wird in "main" eingezeichnet. –

3

Um ein Lambda zu einem Freund zu machen, müssen Sie sich mit einer Klasse oder einer Funktion vertraut machen, bei der das Lambda definiert ist. Hier ist ein komplettes Beispiel:

#include <iostream> 
using namespace std; 

class A { 
    int a; 
public: 
    A(int _a) : a(_a) {} 
    friend int foo(A*); // Declare foo(A*) a friend of A 
}; 

int foo(A* aa) { 
    auto function = [](A* a) { 
     return a->a; // Now foo(A*) can access A::a, which is private 
    }; 
    return function(aa); 
} 

int main() { 
    A a(123); 
    cout << foo(&a) << endl; 
    return 0; 
} 

Here is a running demo on ideone.

+0

Wie ich aus Ihrer Antwort verstehe, hat es keinen Sinn, "freundliches" Lambda zu verwenden, oder? - Da jede Lambda-Definition innerhalb der "Freund" -Funktion platziert werden sollte, kann ich stattdessen die "Freund" -Funktion selbst verwenden. –

+0

@ abyss.7 Nicht wirklich: Sie können Lambdas in einer Freundes- oder Freundesklasse erstellen und sie dann woanders verwenden, außerhalb einer Freundesfunktion/Klasse. Zum Beispiel können Sie Ihre 'Funktion' als öffentliches Mitglied einer Klasse' B' deklarieren, die ein Freund von 'A' ist, und dann' B :: function' verwenden, um Dinge auszuführen, die Zugriff auf 'A's erfordern private Mitglieder. – dasblinkenlight

1

mit std :: Funktion nimmt zusätzliche Ressource, so zweckmäßig nach mir mit Freund/oder Funktionsmethode Privat Element (friend-Funktion impliziter inlined) zuzugreifen:

class A{ 
    int a; 

    friend int access_member(A*a){ return a->a;} 
}; 

----------------------------------------- 
auto function = [](A*a){ return access_member(a); } 

Live example

EDIT: Ich persönlich std std :: function, aber nicht vergessen, std :: Funktion nimmt immer zusätzliche Speicherressourcen, und möglicherweise nicht inline, also wenn Sie Ihre Quelle ohne STD :: Funktion implementieren, don benutze nicht std :: fun ction. Siehe auch How is std::function implemented? Auch Lambda to std::function conversion performance

Verwandte Themen