Я хочу сохранить переменные лямбда-выражения (например, в блоке кода кулака). Проблема в том, что тогда я использую классы (например, второй блок кода), компилятор возвращает мне некоторые ошибки. Я не знаю, как это исправить.
Надеюсь, кто-то может мне помочь и объяснить, почему он не работает так. Благодарю.
Первый код:
// 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;
}
Второй код:
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;
}
Составитель:
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)
Проблема в том, что функции-члены не являются нормальными функциями, они не могут быть назначены указателю на функцию, потому что тип, в котором они являются членами, является частью их типа. Кроме того, функция члена должна иметь объект, чтобы быть вызван, который будет this
в коде функции.
У вас есть несколько решений:
разрешить только функции, которые являются членами вашего класса
void (*MyClass::func)(int); // but you can use it only with members of the class
использовать функцию std :: function
typedef std::function<void(int)> func;
Решение 2 является самым простым, поскольку функция std :: предназначена для работы со всем, что может быть вызвано с той же самой сигнатурой, что и в шаблонах parammetters. Кроме того, это единственное решение, которое позволяет хранить закрытие (объекты из лямбда). См. Обратные вызовы в стиле С++ 11? для деталей.
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;
}
mem_fun()
.
Функция-член не похожа на обычную функцию, поскольку должен быть экземпляр класса, доступного для его вызова (т.е. Объекта, который станет *this
). Вы не можете сделать обычную переменную переменной указателя функции-члена.
Если вы хотите создать указатель на функцию, который можно вызвать с помощью любого экземпляра класса, вам понадобится указатель на функцию-член. Ты бы написал
void (test::*func)(int);
заявить об этом,
func = &test::my_default;
назначить его и
(this->*func)(5);
называть его. Конечно, теперь вы не можете указать точку указателя функции-члена на лямбду.
Если, с другой стороны, вы хотите связать this
как экземпляр и создать обычную функцию из функции-члена, ну вы не можете на самом деле сделать обычный указатель на нее. Вместо этого вам понадобится объект std::function
,
std::function<void(int)> func;
свяжите следующим образом:
func = std::bind(&test::my_default, this, std::placeholders::_1);
и затем звоните нормально. std::function
работает с lambdas точно так же, как указатель функции.