Сохранение указателя функции + аргументы для последующего использования - PullRequest
7 голосов
/ 07 февраля 2011

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

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

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

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

Есть идеи?

Ответы [ 3 ]

4 голосов
/ 08 февраля 2011

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

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. Я привел примерс двумя аргументами, если ваш компилятор поддерживает шаблоны с переменным числом аргументов, вы можете использовать их, в противном случае просто создайте перегрузку для каждого числа аргументов.
3 голосов
/ 08 февраля 2011

Как насчет решения, использующего 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");
2 голосов
/ 07 февраля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...