variabel ekspresi lambda c++ di kelas

Saya ingin menyimpan variabel ekspresi lambda (seperti di blok kode pertama). Masalahnya adalah kemudian saya menggunakan kelas (seperti blok kode kedua) kompiler mengembalikan saya beberapa kesalahan. Saya tidak tahu bagaimana cara memperbaikinya.

Saya harap seseorang dapat membantu saya dan menjelaskan mengapa ini tidak berfungsi seperti ini. Terima kasih.

Kode Pertama:

// variable for function pointer
void (*func)(int);
// default output function
void my_default(int x) {
    cout << "x =" << "\t" << x << endl << endl;
}


int main() {
    cout << "Test Programm\n\n";

    // 1. Test - default output function
    cout << "my_default\n";
    func = &my_default;
    func(5);

    // 2. Test - special output function 2
    cout << "my_func2\n";
    func = [](int x) {  cout << "x =" << "  " << x << endl << endl; };
    func(5);

    return 0;
}

Kode Kedua:

class test {
private:
    // variable for function pointer
    void (*func)(int);
    // default output function
    void my_default(int x) {
        cout << "x =" << "\t" << x << endl << endl;
    }

public:
    void dummy(void) {
        // 1. Test - default output function
        cout << "my_default\n";
        func = &my_default;
        func(5);

        // 2. Test - special output function 2
        cout << "my_func2\n";
        func =  [](int x)->int{ cout << "x =" << "  " << x << endl << endl; };
        func(5);
    }
};


// entry
int main() {
    cout << "Test Programm\n\n";

    test a;
    a.dummy();

    return 0;
}

Penyusun:

pi@raspberrypi ~/dev/property $ gcc -std=c++0x -o test2 test2.cpp -lstdc++
test2.cpp: In member function ‘void test::dummy()’:
test2.cpp:491:17: error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.  Say ‘&test::my_default’ [-fpermissive]
test2.cpp:491:17: error: cannot convert ‘void (test::*)(int)’ to ‘void (*)(int)’ in assignment
test2.cpp:496:77: error: invalid user-defined conversion from ‘test::dummy()::<lambda(int)>’ to ‘void (*)(int)’ [-fpermissive]
test2.cpp:496:28: note: candidate is: test::dummy()::<lambda(int)>::operator int (*)(int)() const <near match>
test2.cpp:496:28: note:   no known conversion for implicit ‘this’ parameter from ‘int (*)(int)’ to ‘void (*)(int)’

person Heinrich    schedule 28.01.2014    source sumber
comment
Penunjuk fungsi anggota tidak sama dengan penunjuk fungsi. Anda dapat melihat di kesalahan bahwa jenisnya berbeda.   -  person chris    schedule 29.01.2014
comment
Selain jawaban di bawah ini... Lambda Anda di test2.cpp gagal karena mengembalikan int, bukan void.   -  person Rastaban    schedule 29.01.2014


Jawaban (2)


Masalahnya adalah fungsi anggota bukanlah fungsi normal, fungsi tersebut tidak dapat ditetapkan ke penunjuk fungsi karena tipe anggotanya adalah bagian dari tipenya. Selain itu, fungsi anggota harus memiliki objek untuk dipanggil, yang akan menjadi this di dalam kode fungsi.

Anda memiliki beberapa solusi:

  1. izinkan hanya fungsi yang merupakan anggota kelas Anda

    void (*MyClass::func)(int); // but you can use it only with members of the class
    
  2. gunakan std::function

    typedef std::function<void(int)> func;
    

Solusi 2 adalah yang paling sederhana karena std::function dirancang untuk bekerja dengan apa pun yang dapat dipanggil dengan tanda tangan yang sama seperti yang ada di parameter templat. Selain itu, ini satu-satunya solusi yang memungkinkan Anda menyimpan penutupan (objek dari lambda). Lihat C++11 callback bergaya? untuk detailnya.

class test {
private:
    // variable for function pointer
    std::function< void ( int )> func;
    // default output function
    void my_default(int x) {
        cout << "x =" << "\t" << x << endl << endl;
    }

public:
    void dummy(void) {
        // 1. Test - default output function
        cout << "my_default\n";
        func = std::bind(&test::my_default, this, std::placeholders::_1);
        // or 
        func = [&]( int i ){ my_default( i ); };
        func(5);

        // 2. Test - special output function 2
        cout << "my_func2\n";
        func =  [](int x)->int{ cout << "x =" << "  " << x << endl << endl; };
        func(5);
    }
};


// entry
int main() {
    cout << "Test Programm\n\n";

    test a;
    a.dummy();

    return 0;
}
person Klaim    schedule 28.01.2014
comment
Terima kasih atas penjelasannya. func = std::bind( &my_default, ini ); akan mengembalikan kesalahan (kompiler) tetapi seperti yang ditulis Brian Bi std::bind(&test::my_default, this, std::placeholders::_1); tidak akan mengembalikan kesalahan. - person Heinrich; 29.01.2014
comment
Ah iya saya selalu kesulitan mengingat cara menggunakan bind, jadi saya gunakan lambda saja. Juga, ada mem_fun(). - person Klaim; 29.01.2014
comment
Saya merekomendasikan rute std::function, meskipun opsi ketiga (tergantung pada sifat my_default) adalah menjadikan my_default statis. - person Rastaban; 29.01.2014
comment
@Rastaban Dia ingin menggunakan lambda, dan kami tidak tahu apakah itu menangkap lambda atau tidak. - person Klaim; 29.01.2014

Fungsi anggota tidak seperti fungsi biasa, karena harus ada turunan kelas yang tersedia agar dapat memanggilnya (yaitu objek yang akan menjadi *this). Anda tidak dapat membuat variabel penunjuk fungsi biasa menunjuk ke fungsi anggota.

Jika Anda ingin membuat penunjuk fungsi yang dapat dipanggil menggunakan instance kelas mana pun, Anda memerlukan penunjuk fungsi anggota. Anda akan menulis

void (test::*func)(int);

untuk mendeklarasikannya,

func = &test::my_default;

untuk menugaskannya, dan

(this->*func)(5);

untuk menyebutnya. Tentu saja, sekarang Anda tidak dapat membuat penunjuk fungsi anggota menunjuk ke lambda.

Sebaliknya, jika Anda ingin mengikat this sebagai instance dan membuat fungsi biasa dari fungsi anggota, Anda tidak bisa membuat penunjuk fungsi biasa ke sana. Sebaliknya Anda menginginkan objek std::function,

std::function<void(int)> func;

mengikat sebagai berikut:

func = std::bind(&test::my_default, this, std::placeholders::_1);

dan kemudian menelepon secara normal. std::function bekerja dengan lambda seperti halnya penunjuk fungsi.

person Brian Bi    schedule 28.01.2014
comment
Terima kasih!! Saya mungkin lupa apa perbedaan antara fungsi anggota dan fungsi biasa. - person Heinrich; 29.01.2014