本篇內容主要講解“如何解決C++訪問者模式模板函數無法重載的問題”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何解決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++訪問者模式模板函數無法重載的問題”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。