我有一个应用程序,它有很多功能,遍历菜单工具栏的所有元素。
代码看起来像这样:
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)
我想使用宏,但不推荐使用它们。 使用带函数指针的内联函数的Howerver似乎导致一些难以理解的代码。 (我没有看到任何函数指针的例子,期望带有函数的可变数量的参数)。
如果没有添加一些过于复杂的无法解释的代码,是否有更好/更清洁的方法呢?
答案 0 :(得分:1)
您可以使用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等价物和lambdas。
如果您想将菜单列表放在一个位置并使用该列表 在不同的地方,我推荐使用Boost.Preprocessor。但你可能会 在诉诸它之前想要三思而行。
答案 1 :(得分:1)
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
。