目录
- 背景
- 解决方案
- 最终代码
背景
最近遇到一个比较棘手的场景,我们有一堆模块,他们有一个通用的基类,我们不防假设为 BaseClass,该类有一些通用的结构以及需要重载的方法。这些模块有一个堆同名但是不同类型
参数的方法,比如:
int DerivedClass1::DoNlpTask(const DerivedReq1& req, DerivedResp* resp);
类似这样的。每个 DerivedClass 的DoNlpTask都是同名不同参数的,而且这些要给业务去具体实现。正常来说,很容易想到函数重载的方式,但是很不幸,模板函数无法重载
但是,我们想让框架层和业务层相对解耦,不想让业务的具体类型等污染框架调度模块的结构。
解决方案
在这里,我们利用访问者模式的思想,结合C++的模板来统一处理。先定义一个Visitor,该类定义好具体业务模块的通用操作步骤;实现的时候利用模板特化来实例化不同的业务模块及其DoNlpTask 函数。这样在框架层只需要调用Visitor 的统一模板接口即可,具体参看一下代码。
最终代码
#include <iostream>
#include <type_traits>
// 以下模拟请求协议 =====================
class BaseReq {};
class DerivedReq : public BaseReq {};
class BaseResp {};
class DerivedResp : public BaseResp {};
DerivedReq g_derived_req;
// 以下模拟 NLP ============================
class BaseClass {
public:
// 单纯视为一个需要重载的函数
virtual int get_field_id() = 0;
virtual void WormUp () {}
};
#define REGISTER_PROTOTYPE(req_type, resp_type) \
public: \
using ReqType = req_type; \
using RespType = resp_type;
class DerivedClass : public BaseClass {
// 注册请求类型
REGISTER_PROTOTYPE(DerivedReq, DerivedResp)
public:
int DoNlpTask(const DerivedReq&, DerivedResp* resp) {
std::cout << "Derived DoNlpTask\n";
}
int get_field_id() override { return 1; }
};
// 以下模拟pb反射 =========================
const BaseReq* GetReqType() { return &g_derived_req; }
// 以下是 visitor 的定义 ===========
class Visitor {
public:
template <typename ClassType>
int DoVisit(ClassType* base) {
static_assert(std::is_base_of<BaseClass, DerivedClass>::value,
"type failed");
int idx = base->get_field_id();
std::cout << "visitor get field_id " << idx << std::endl;
const auto* req = GetMessageType<typename ClassType::ReqType>(GetReqType());
typename ClassType::RespType resp;
// 返回计算结果
return base->DoNlpTask(*req, &resp);
}
private:
template <typename ReqType>
const ReqType* GetMessageType(const BaseReq* req) {
static_assert(std::is_base_of<BaseReq, ReqType>::value,
"Message Type Error");
return static_cast<const ReqType*>(req);
}
};
int main() {
DerivedClass dc;
Visitor vis;
vis.DoVisit(&dc);
return 0;
}
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

评论(0)