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++模板函數無法重載內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- C++強制類型轉換(static_cast、dynamic_cast、const_cast、reinterpret_cast)
- C++ 強制類型轉換詳解
- C++ RTTI與4種類型轉換的深入理解
- C++中4種強制類型轉換的區別詳析
- C++ 數據類型強制轉化的實現