Что лучше использовать встроенные функции или MACROS в C ++ для указателей на функции переменной длины - PullRequest
1 голос
/ 24 января 2012

У меня есть приложение, которое имеет множество функций, которые проходят через все элементы панели инструментов меню.

Код выглядит примерно так:

subMenuDefaultMenuShortcuts( ui->fileMenu );
subMenuDefaultMenuShortcuts(ui->editMenu);
subMenuDefaultMenuShortcuts(ui->windowMenu);
subMenuDefaultMenuShortcuts(ui->helpMenu);

subMenuUpdateLabels(ui->fileMenu,hierarchy);
subMenuUpdateLabels(ui->editMenu,hierarchy);
subMenuUpdateLabels(ui->windowMenu,hierarchy);
subMenuUpdateLabels(ui->helpMenu,hierarchy);

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

в идеале я хотел бы что-то вроде этого:

OnAllMenus(functionName,params ...)

, поэтому мой код будет выглядеть так:

OnAllMenus(subMenuUpdateLabels)
OnAllMenus(subMenuUpdateLabels,hierarchy)
OnAllMenus(someFunction,hierarchy,argument1,argument2)

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

Есть ли какой-нибудь лучший / более чистый способ сделать это без добавления слишком сложного неуправляемого кода.

Ответы [ 2 ]

1 голос
/ 24 января 2012
template<typename FuncPointer, typename ... Args>
void for_all_menus(FuncPointer func, Args ... args)
{
  f(ui->foo,std::forward<Args>(args)...);
  f(ui->bar,std::forward<Args>(args)...);
  // etc
}

// use
for_all_menus(&subMenuLabel, hierarchy);

Pmr ответ, но различные шаблоны, чтобы остановить глупых boost::bind s, которые будут разбросаны повсюду.

1 голос
/ 24 января 2012

Вы можете использовать boost::function и boost::bind.

template<typename Func>
void for_all_menus(Func f) {
  f(ui->foo);
  f(ui->bar);
  // etc
}

// use
for_all_menus(boost::bind(subMenuLabel, _1, hierarchy));

// with variadic templates
template<typename Func, typename Args...>
struct for_all_menus {
  Func f;
  void operator()(Args&&... args) {
    // umh, I always mess up the syntax
    // you might want to double check this
    f(ui->foo, std::forward<Args>(args)...);
  }
};
template<typename F>
for_all_menus<F> make_for_all_menus(F f) { return for_all_menus<F>{f}; }

// use
auto f = make_for_all_menus(subMenuLabel);
f(hierarchy);

Если вам нужно что-то более динамичное, просто замените шаблон функции на функцию, которая принимает boost::function.Конечно, вы также можете использовать эквиваленты C ++ 11 и лямбды.

Если вы хотите собрать список меню в одном месте и использовать этот список в разных местах, я бы порекомендовал Boost.Preprocessor.Но вы можете подумать дважды, прежде чем прибегнуть к этому.

...