溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何解決C++訪問者模式模板函數(shù)無法重載的問題

發(fā)布時(shí)間:2021-12-24 09:03:55 來源:億速云 閱讀:136 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“如何解決C++訪問者模式模板函數(shù)無法重載的問題”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“如何解決C++訪問者模式模板函數(shù)無法重載的問題”吧!

背景

最近遇到一個(gè)比較棘手的場景,我們有一堆模塊,他們有一個(gè)通用的基類,我們不防假設(shè)為 BaseClass,該類有一些通用的結(jié)構(gòu)以及需要重載的方法。這些模塊有一個(gè)堆同名但是不同類型

參數(shù)的方法,比如:

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

類似這樣的。每個(gè) DerivedClass 的DoNlpTask都是同名不同參數(shù)的,而且這些要給業(yè)務(wù)去具體實(shí)現(xiàn)。正常來說,很容易想到函數(shù)重載的方式,但是很不幸,模板函數(shù)無法重載
但是,我們想讓框架層和業(yè)務(wù)層相對(duì)解耦,不想讓業(yè)務(wù)的具體類型等污染框架調(diào)度模塊的結(jié)構(gòu)。

解決方案

在這里,我們利用訪問者模式的思想,結(jié)合C++的模板來統(tǒng)一處理。先定義一個(gè)Visitor,該類定義好具體業(yè)務(wù)模塊的通用操作步驟;實(shí)現(xiàn)的時(shí)候利用模板特化來實(shí)例化不同的業(yè)務(wù)模塊及其DoNlpTask 函數(shù)。這樣在框架層只需要調(diào)用Visitor 的統(tǒng)一模板接口即可,具體參看一下代碼。

最終代碼

#include <iostream>
#include <type_traits>

// 以下模擬請(qǐng)求協(xié)議 =====================
class BaseReq {};

class DerivedReq : public BaseReq {};

class BaseResp {};

class DerivedResp : public BaseResp {};

DerivedReq g_derived_req;

// 以下模擬 NLP ============================

class BaseClass {
 public:
  // 單純視為一個(gè)需要重載的函數(shù)
  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 {
  // 注冊(cè)請(qǐng)求類型
  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;
    // 返回計(jì)算結(jié)果
    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;
}

到此,相信大家對(duì)“如何解決C++訪問者模式模板函數(shù)無法重載的問題”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI