今天小编给大家分享一下c++类函数作为模板参数实现的方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
需求背景
DB操作有四种基本操作:Insert、Update、Delete和Query,每种操作需要进行功能增强(eg:支持重试、权限校验等),最粗暴的实现就是改动原有接口实现,在实现中加入增强逻辑,这种方式对代码侵入性过高,而且无法控制该逻辑是否需要,如果不需要的话又得重新修改代码实现。
可以用装饰者设计模式对原有接口做一层包装,然后在包装层里注入增强实现逻辑,伪码表现形式:
Status Insert(Args args...); Status Update(Args args...); Status Delete(Args args...); Status Query(Args args...); Status Wapper(...){ // 增强逻辑实现 ... // 调用原有函数 Insert(Args args...) // 返回处理结果 ... }
实现方式
对于这种通用的增强逻辑及包装形式,很适合用模板作为统一实现,简化代码逻辑,并增强后期维护,对于上述场景,有如下两种模板实现方式:
struct + operator
class DbWapper : public DbOperation{ public: // 继承方法 Status Insert(Args args...) override; Status Update(Args args...) override; Status Delete(Args args...) override; Status Query(Args args...) override; private: DbOperation *m_dbOperation; template <typename Func, typename... Args> Status Wapper(Func func, Args &&...args) { // 调用原有的函数逻辑 Status status = func(std::forward<Args>(args)...); // 增强逻辑实现 ... return status; } } Status Insert(Args args...) { // 利用struct + operator实现函数包装 struct InsertFunc { DbOperation *dbOperation; Status operator()(Args args...) const { // 调用原有逻辑 return dbOperation->Insert(args...); } } insertFunc{m_dbOperation}; // 将函数包装作为function传入增强逻辑 return Wapper(insertFunc, args...); }
Pass Function Signature
观察上一种实现方案,发现struct和operator只是为了构造一种函数参数,便于模板调用原有逻辑,所以我们可以尝试消除struct,让模板只接受具体的函数签名,就可以极大简化实现逻辑,具体实现如下:
class DbWapper : public DbOperation{ public: // 继承方法 Status Insert(Args args...) override; Status Update(Args args...) override; Status Delete(Args args...) override; Status Query(Args args...) override; private: DbOperation *m_dbOperation; template <typename... Args0, typename... Args1> Status Wapper(Status (DbOperation::*method)(Args0...), Args1 &&...args) { // 调用原有的函数逻辑 Status status = (m_dbOperation->*method)(std::forward<Args1>(args)...); // 增强逻辑实现 ... return status; } } Status Insert(Args args...) { // 传入具体的函数签名 return Wapper((Status(DbOperation::*)(Insert函数签名))(&DbOperation::Insert), args...); }