C++访问者模式模板函数无法重载的问题解决

目录
  • 背景
  • 解决方案
  • 最终代码

背景

最近遇到一个比较棘手的场景,我们有一堆模块,他们有一个通用的基类,我们不防假设为 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;
}

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

(0)

相关推荐

  • C++模板重载

    目录 1.重载模板 2.问题  文章转自 公众号:Coder梁(ID:Coder_LT) 1.重载模板 函数模板可以使得同一个函数对不同类型使用,非常地方便.但有的时候类型不同,只是通过模板是没办法解决的, 可能逻辑上也会有所区别,这个时候只是使用模板是无法解决的. 为了满足这种需求,我们可以像是重载函数那样重载模板.和常规的函数一样,重载的模板的函数特征,也就是入参的数量和类型必须有所不同. 举个例子:比如我们之前定义了一个函数模板用来交换两个变量的值.如果我们要交换的不只是变量,而是两个数组

  • C++访问者模式模板函数无法重载的问题解决

    目录 背景 解决方案 最终代码 背景 最近遇到一个比较棘手的场景,我们有一堆模块,他们有一个通用的基类,我们不防假设为 BaseClass,该类有一些通用的结构以及需要重载的方法.这些模块有一个堆同名但是不同类型 参数的方法,比如: int DerivedClass1::DoNlpTask(const DerivedReq1& req, DerivedResp* resp); 类似这样的.每个 DerivedClass 的DoNlpTask都是同名不同参数的,而且这些要给业务去具体实现.正常来说

  • java访问者模式的静态动态及伪动态分派彻底理解

    目录 1 使用访问者模式实现KPI考核的场景 2 从静态分派到动态分派 2.1 静态分派 2.2 动态分派 3 访问者模式中的伪动态分派 4 访问者模式在JDK源码中的应用 5 访问者模式在Spring源码中的应用 本文节选自<设计模式就该这样学> 1 使用访问者模式实现KPI考核的场景 每到年底,管理层就要开始评定员工一年的工作绩效,员工分为工程师和经理:管理层有CEO和CTO.那么CTO关注工程师的代码量.经理的新产品数量:CEO关注工程师的KPI.经理的KPI及新产品数量. 由于CEO和

  • C#设计模式之Visitor访问者模式解决长隆欢乐世界问题实例

    本文实例讲述了C#设计模式之Visitor访问者模式解决长隆欢乐世界问题.分享给大家供大家参考,具体如下: 一.理论定义 访问者模式 提供了 一组 集合 对象 统一的 访问接口,适合对 一个集合中的对象,进行逻辑操作,使 数据结构  和 逻辑结构分离. 二.应用举例 需求描述:暑假来啦!三个小伙子组团,开车来 长隆欢乐世界玩. 每个人想玩的项目都不一样, 旅游者 1   想玩:十环过山车,龙卷风暴,梦幻旋马 旅游者 2   想玩:空中警察,欢乐摩天轮,超级水战 旅游者 3   想玩:四维影院,垂

  • C语言 设计模式之访问者模式

    C语言访问者模式 概要: 访问者模式,听上去复杂一些.但是,这种模式用简单的一句话说,就是不同的人对不同的事物有不同的感觉.比如说吧,豆腐可以做成麻辣豆腐,也可以做成臭豆腐.可是,不同的地方的人未必都喜欢这两种豆腐.四川的朋友可能更喜欢辣豆腐,江浙的人就可能对臭豆腐更喜欢一些.那么,这种情况应该怎么用设计模式表达呢? typedef struct _Tofu { int type; void (*eat) (struct _Visitor* pVisitor, struct _Tofu* pTo

  • JAVA设计模式之访问者模式原理与用法详解

    本文实例讲述了JAVA设计模式之访问者模式.分享给大家供大家参考,具体如下: 访问者模式: 一个作用于某对象结构中各元素的操作,使你可以在不改变各元素类数据结构的前提下增加作用于这些元素的新操作. 结构对象是访问者模式必备条件,且这个结构对象必须存在遍历自身各个对象的方法. 适用于:数据结构相对稳定,把数据结构和作用与其上的其它操作解耦,使得操作相对自由. 优点: 1.符合单一职责原则 2.扩展性良好:元素类可以通过接受不同的访问者来实现对不同操作的扩展. 缺点: 1.如果要增加新元素,则会让操

  • JAVA设计模式之访问者模式详解

    在阎宏博士的<JAVA与模式>一书中开头是这样描述访问者(Visitor)模式的: 访问者模式是对象的行为模式.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变. 分派的概念 变量被声明时的类型叫做变量的静态类型(Static Type),有些人又把静态类型叫做明显类型(Apparent Type):而变量所引用的对象的真实类型又叫做变量的实际类型(Actual Type).比如: 复制代码 代码如下: List lis

  • 轻松掌握python设计模式之访问者模式

    本文实例为大家分享了python访问者模式代码,供大家参考,具体内容如下 """访问者模式""" class Node(object): pass class A(Node): pass class B(Node): pass class C(A, B): pass class Visitor(object): def visit(self, node, *args, **kwargs): meth = None ""&quo

  • Java设计模式之java访问者模式详解

    目录 介绍 定义及使用场景 UML类图 角色 财务案例 个人心得体会 静态分派以及动态分派 静态分派 动态分派 访问者模式中的伪动态双分派 对访问者模式的一些思考 总结 优点 缺点 适用性 参考文章 总结 介绍 访问者模式,是行为型设计模式之一 访问者模式是一种将数据操作与数据结构分离的设计模式 访问者模式的基本思想: 软件系统中拥有一个由许多对象构成的.比较稳定的对象结构,这些对象的类都拥有一个 accept 方法用来接受访问者对象的访问 访问者是一个接口,它拥有一个 visit 方法,这个方

  • 浅谈PHP面向对象之访问者模式+组合模式

    因为原文中延续了组合模式的代码示例来讲访问者模式 所以这里就合并一起来复习了.但主要还是讲访问者模式.顾名思义这个模式会有一个访问者类(就像近期的热播剧"人民的名义"中的检查官,跑到到贪官家里调查取证,查实后就定罪),被访问者类调用访问者类的时候会将自身传递给它使用. 直接看代码: //被访问者基类 abstract class Unit { abstract function bombardStrength(); //获取单位的攻击力 //这个方法将调用访问者类,并将自身传递给它 f

  • 轻松掌握php设计模式之访问者模式

    访问者模式解决的问题 在我们的代码编写过程当中,经常需要对一些类似的对象添加一些的代码,我们以一个计算机对象打印组成部分为例来看下: /** * 抽象基类 */ abstract class Unit { /** *获取名称 */ abstract public function getName(); } /** * Cpu类 */ class Cpu extends Unit { public function getName() { return 'i am cpu'; } } /** *

随机推荐