经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++访问者模式模板函数无法重载的问题解决
来源:jb51  时间:2021/12/24 8:46:04  对本文有异议

背景

最近遇到一个比较棘手的场景,我们有一堆模块,他们有一个通用的基类,我们不防假设为 BaseClass,该类有一些通用的结构以及需要重载的方法。这些模块有一个堆同名但是不同类型

参数的方法,比如:

  1. int DerivedClass1::DoNlpTask(const DerivedReq1& req, DerivedResp* resp);

类似这样的。每个 DerivedClass 的DoNlpTask都是同名不同参数的,而且这些要给业务去具体实现。正常来说,很容易想到函数重载的方式,但是很不幸,模板函数无法重载
但是,我们想让框架层和业务层相对解耦,不想让业务的具体类型等污染框架调度模块的结构。

解决方案

在这里,我们利用访问者模式的思想,结合C++的模板来统一处理。先定义一个Visitor,该类定义好具体业务模块的通用操作步骤;实现的时候利用模板特化来实例化不同的业务模块及其DoNlpTask 函数。这样在框架层只需要调用Visitor 的统一模板接口即可,具体参看一下代码。

最终代码

  1. #include <iostream>
  2. #include <type_traits>
  3.  
  4. // 以下模拟请求协议 =====================
  5. class BaseReq {};
  6.  
  7. class DerivedReq : public BaseReq {};
  8.  
  9. class BaseResp {};
  10.  
  11. class DerivedResp : public BaseResp {};
  12.  
  13. DerivedReq g_derived_req;
  14.  
  15. // 以下模拟 NLP ============================
  16.  
  17. class BaseClass {
  18. public:
  19. // 单纯视为一个需要重载的函数
  20. virtual int get_field_id() = 0;
  21. virtual void WormUp () {}
  22. };
  23.  
  24. #define REGISTER_PROTOTYPE(req_type, resp_type) public: using ReqType = req_type; using RespType = resp_type;
  25.  
  26. class DerivedClass : public BaseClass {
  27. // 注册请求类型
  28. REGISTER_PROTOTYPE(DerivedReq, DerivedResp)
  29. public:
  30. int DoNlpTask(const DerivedReq&, DerivedResp* resp) {
  31. std::cout << "Derived DoNlpTask\n";
  32. }
  33.  
  34. int get_field_id() override { return 1; }
  35. };
  36.  
  37. // 以下模拟pb反射 =========================
  38. const BaseReq* GetReqType() { return &g_derived_req; }
  39.  
  40. // 以下是 visitor 的定义 ===========
  41. class Visitor {
  42. public:
  43. template <typename ClassType>
  44. int DoVisit(ClassType* base) {
  45. static_assert(std::is_base_of<BaseClass, DerivedClass>::value,
  46. "type failed");
  47. int idx = base->get_field_id();
  48. std::cout << "visitor get field_id " << idx << std::endl;
  49. const auto* req = GetMessageType<typename ClassType::ReqType>(GetReqType());
  50. typename ClassType::RespType resp;
  51. // 返回计算结果
  52. return base->DoNlpTask(*req, &resp);
  53. }
  54.  
  55. private:
  56. template <typename ReqType>
  57. const ReqType* GetMessageType(const BaseReq* req) {
  58. static_assert(std::is_base_of<BaseReq, ReqType>::value,
  59. "Message Type Error");
  60. return static_cast<const ReqType*>(req);
  61. }
  62. };
  63.  
  64. int main() {
  65. DerivedClass dc;
  66. Visitor vis;
  67. vis.DoVisit(&dc);
  68. return 0;
  69. }

到此这篇关于C++访问者模式模板函数无法重载的问题解决的文章就介绍到这了,更多相关C++模板函数无法重载内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号