【发布时间】:2015-05-06 04:25:21
【问题描述】:
我正在使用其他人编写的框架。该框架使用了一些丑陋的宏。 首先,框架使用宏来声明和定义类,如下所示:
#define DECLARE_FUNC(_name, _params) \
class _name \
{ \
static int execute(); \
static int exec_func(_params* param); \
}
#define DEFINE_FUNC(_name, _params) \
int _name::execute() \
{ \
_params p = get_from_global(); \
return exec_func(&p) \
} \
int _name::exec_func(_param* param)
在使用这个框架时,我要做的是:
DECLARE_FUNC(foo, database)
DEFINE_FUNC(foo, database)
{
// write business logic here
}
在编写业务逻辑时,我必须从数据库中的不同表中查询信息,并对查询结果做几乎相同的事情。伪代码如下:
TypeA a = TABLE(t_TypeA)->Query();
if (a.is_valid()) {
// do something with a here
// some local variables are used here
}
TypeB b = TABLE(t_TypeB)->Query();
if (b.is_valid()) {
// do something with b here
// some local variables are used here
}
显然重复代码太多了,不好。所以我的同事使用宏来删除重复的代码。我认为多态 lambda 在这种情况下应该可以工作,但是 C++11 不支持多态 lambda。
我的问题:有没有其他方法可以删除没有宏的重复代码?
更新: 其实源代码中“_params”也是一个宏,可以扩展更多参数,我这里简化一下。如果扩展参数宏并使用多态 lambda,它看起来像:
int ClassA::exec_func(Database database,
Date date,
Time time)
{
// there are also some local variables, for example:
long second = get_second(date, time);
// polymorphic lambda version
auto handle_table = [&](auto table_type) {
// database, date, time and local variables will be used here
}
handle_table(TableA);
handle_table(TableB);
...
handle_table(TableX);
}
所以弗朗西斯的解决方案在这种情况下可能行不通。
【问题讨论】:
-
接受函数指针和数据库类型作为其模板参数的抽象模板基类会起作用吗?这样你的基类是抽象的,不能被实例化,但派生类可以是它们都共享一个相似接口的地方。每个派生类(数据库类型)独有的任何函数或方法都可以通过使用模板特化覆盖纯虚函数来完成。
-
老实说,我不确定您的问题是什么,您能否写一个草图如何使用多态 lambda 解决您的问题?另外,您希望避免哪些重复代码?最后,我会认真地问自己是否有充分的理由使用该框架,因为您展示的部分提出了一些非常复杂的设计,这些设计只能在预可变模板(甚至预模板)中得到证明时代。
-
@Ulrich 对我来说,这确实看起来像是一个可以选择模板的场景。但如果可能的话,弗朗西斯的解决方案会更好。一般来说,如果我有对类的部分数据执行相同操作的函数,我会尝试使用继承来解决它。
-
std::function不够吗? -
感谢您的建议。稍后我将添加更多代码以使其更清晰。 @Ulrich 我完全同意你的观点,框架很糟糕,设计更糟糕。是的,没有很好的理由使用它,但这是公司的选择,我必须忍受它。