Можно ли конвертировать “std::function<int(int)>” в “typedef int (*MyFunction) (int k);”

187
09 января 2018, 14:43

Доброго времени суток. Подскажите есть ли какой нибудь способ осуществить перевод из типа "std::function<int(int)>" в тип "int (*MyFunction) (int k);"

У меня есть функция

void someFnc(MyFunction collbackFn);

в которую я пытаюсь передать функцию создаваемую с помощью замыкания:

auto getFn(int ll)
{
return [=](int k)
    {
      std::cout<<(k+ll)<<"\n"; // тут какие то действия
      return k+ll;
    };   
}
someFnc(getFn(12));

Однако у меня не как не получается конвертировать тип функции который я получаю на выходе из замыкания, в требуемый. Я не могу отредактировать код функции в которую передаю замыкание void someFnc(MyFunction collbackFn);, так как она не мною была написана. И мне нужно замыкание либо что то в этом роде, для того что бы сгенерировать функцию с занесенным параметром внутри (зафиксированным), так как он (параметр) будет передаваться лишь единожды и не будет не где сохраняться.

Для большей конкретики, по этой ссылке ссылке (адрес: http://cpp.sh/4ngsq), в веб среде С++ я маленький пример накидал, которых иллюстрирует ту задачу которую я не как не могу решить.

Подскажите как можно было бы решить данный вопрос ?

Answer 1

Вариант со статическими переменными (можно заменить static на thread_local, но как это скажется на производительности мне неизвестно):

#include <iostream>
#include <string>
#include<functional>
template<class Fn>
struct static_capture_impl;
template<class R, class... Args>
struct static_capture_impl<R(Args...)>{
    using ret_value_t = R(*)(Args...);
    template<class Fn>
    ret_value_t  operator()(Fn fn) const{
       static auto state = std::move(fn);  
       return [](Args... args)->R{ 
          return state(args...);
       };
    }
};
// Это чтобы обрабатывались и указатели на функции
template<class R, class... Args>
struct static_capture_impl<R(*)(Args...)>: public static_capture_impl<R(Args...)> {};

template<class Ret, class Fn>
auto static_capture(Fn fn){
    return static_capture_impl<Ret>{}(std::move(fn));
}
/// example
using call_back_t = int(*)(int k);
int main() {
  int localVar = 5;
  call_back_t fn = static_capture<call_back_t>([localVar](int num) {  
    std::cout << localVar<<std::endl;
    std::cout << num <<std::endl;
    return num + localVar;
  });
  fn(15);
}

Если api позволяет передавать не только указатель на функцию, но и указатель на данные (void*) - можно конвертировать лямбду в void*, и передавать c-функцию, которая распаковывает void* обратно в лямбду (тут опять нужны шаблоны).

READ ALSO
вопрос а getline

вопрос а getline

я написал этот код но он не работаеткак исправить этот код

139
java app в eclipse

java app в eclipse

Изучаю тему Servlet/jsp , работаю в EclipseХочу в целях тренировки работы с сервлетами и базой данных написать простое веб приложение

202
отскакивание от прямых

отскакивание от прямых

В декартовом пространстве точка движется по прямой под определённым углом к другой прямой, надо определить направление движения после столкновения...

195