ORIGINAL
Лямбда-функции очень удобны и уменьшают код.В моем случае мне понадобились лямбды для параллельного программирования.Но это требует захвата и функциональных указателей.Мое решение здесь.Но будьте осторожны с областью действия переменных, которые вы захватили.
template<typename Tret, typename T>
Tret lambda_ptr_exec(T* v) {
return (Tret) (*v)();
}
template<typename Tret = void, typename Tfp = Tret(*)(void*), typename T>
Tfp lambda_ptr(T& v) {
return (Tfp) lambda_ptr_exec<Tret, T>;
}
Пример
int a = 100;
auto b = [&]() { a += 1;};
void (*fp)(void*) = lambda_ptr(b);
fp(&b);
Пример с возвращаемым значением
int a = 100;
auto b = [&]() {return a;};
int (*fp)(void*) = lambda_ptr<int>(b);
fp(&b);
ОБНОВЛЕНИЕ
Улучшенная версия
Прошло некоторое время с тех пор, как был опубликован первый пост о лямбде C ++ с перехватами в качестве указателя на функцию.Поскольку это было полезно для меня и других людей, я внес некоторые улучшения.
Стандартная функция C Указатель API использует соглашение void fn (void * data).По умолчанию это соглашение используется, и лямбда должна быть объявлена с аргументом void *.
Улучшенная реализация
struct Lambda {
template<typename Tret, typename T>
static Tret lambda_ptr_exec(void* data) {
return (Tret) (*(T*)fn<T>())(data);
}
template<typename Tret = void, typename Tfp = Tret(*)(void*), typename T>
static Tfp ptr(T& t) {
fn<T>(&t);
return (Tfp) lambda_ptr_exec<Tret, T>;
}
template<typename T>
static void* fn(void* new_fn = nullptr) {
static void* fn;
if (new_fn != nullptr)
fn = new_fn;
return fn;
}
};
Exapmle
int a = 100;
auto b = [&](void*) {return ++a;};
Преобразование лямбды с захватамиУказатель C
void (*f1)(void*) = Lambda::ptr(b);
f1(nullptr);
printf("%d\n", a); // 101
Можно использовать и таким образом
auto f2 = Lambda::ptr(b);
f2(nullptr);
printf("%d\n", a); // 102
В случае использования возвращаемого значения
int (*f3)(void*) = Lambda::ptr<int>(b);
printf("%d\n", f3(nullptr)); // 103
И в случае использования данных
auto b2 = [&](void* data) {return *(int*)(data) + a;};
int (*f4)(void*) = Lambda::ptr<int>(b2);
int data = 5;
printf("%d\n", f4(&data)); // 108