2011-02-07 5 views
5

У меня есть эта проблема, когда указатель функции C++ сохраняется вместе с набором аргументов для его вызова, чтобы его можно было вызвать позже. Вызывающий код не знает тип и аргументы функций. Сохранение и вызов указателей функций и аргументов чрезвычайно критичны в моем приложении. Интерфейс должен выглядеть следующим образом:Сохранение указателя функции + аргументы для последующего использования

void func(int a, char * b); 
call_this_later(func, 5, "abc"); 

Самое простое решение, чтобы положить всю эту информацию в функтора, требуя другого ЬурейеЕ за вызываемой функции. C++ 11 позволил бы мне сделать это с использованием вариационного шаблона, так что все в порядке.

Поскольку тип функтора неизвестен в точке вызова, представляется необходимым создать виртуальный базовый класс для этих функторов и вызвать функторы, используя вызовы виртуальных функций. Накладные расходы на виртуальные функции + распределение кучи слишком высоки (я нажимаю границы реализации этой идиомы с минимальными инструкциями по сборке). Поэтому мне нужно другое решение.

Любые идеи?

ответ

0

Вам понадобится настраиваемый распределитель для соответствия вашему шаблону распределения. В качестве альтернативы используйте полиморфизм времени компиляции, чтобы передать тип функтора на сайт вызова.

3

насчет решения с использованием boost::function/boost::bind:

void func(int a, char * b); 

boost::function<void()> my_proc = 
    boost::bind(&func, 5, "abc"); 

// then later... 

my_proc(); // calls func(5, "abc"); 
+1

Я считаю, что ':: boost :: function' и' :: std :: tr1 :: function' делают именно то, что @Hans не хочет делать. Я думаю, что они используют виртуальные функции и динамическое распределение. – Omnifarious

+0

@Omnifarious: зависит от функции/функтора, используемой для динамического выделения. для функций с небольшим количеством типов POD существует внутреннее хранилище, которое он будет использовать, однако, да, он действительно использует (очень глубокую) скрытую виртуальную таблицу для фактического выполнения вызова функции. – diverscuba23

2

Вы можете сделать это с помощью лямбда-выражения, которое захватывает типы.

template <typename Func, typename Arg1, typename Arg2> 
std::function<void(void)> call_this_later(Func f, Arg1 a1, Arg2 a2) { 
    return [=]() { f(a1, a2); }; // Capture arguments by value 
} 

несколько вещей, чтобы отметить:

  1. Я не думаю, что вы можете использовать идеальную переадресацию здесь, так как вы должны захватить аргументы
  2. Поскольку C++ не сборщик мусора, если аргументы являются указателями, которые они могут указывать на то, что не было потом. Например, если ваш аргумент равен const char*, тогда все в порядке, если вы используете его со строковым литералом, но если вы передадите someStdString.c_str(), и строка скоро умрет.
  3. Я привел пример с двумя аргументами, если ваш компилятор поддерживает вариативные шаблоны, вы можете использовать их, иначе просто создайте перегруз для каждого количества аргументов.
Смежные вопросы