[C++技能提升]类型归一
最近在设计AI调用架构时,想把各个AI功能的接口定义统一并用基类的多态管理起来(即各个AI功能都继承自同一个基类,并重写init、run、release这三个接口),遇到一个问题就是AI的输入数据类型多样化(除了基本数据类型int、float等外,还有图像、mesh、点云等)且参数个数不固定,想过用模板函数的方式声明这三个接口但是不支持virsual重写。
因此最终想到的方案是:
对于接口参数数量不固定的问题,采用std::vector容器包装起来,于是接口可以定义成:
#include<vector>
class BaseAIModule{
public:
virsual bool init(const std::vector<DataType>& params)=0;
virsual bool run(const std::vector<DataType>& params,std::vector<DataType>& outs)=0;
virsual bool release()=0;
protected:
std::string moduleName;
}
对于类型统一的问题(vector容器只能存放同一种类型的数据,c++17有其他容器可支持不同类型数据的存放),如果把DataType定义为每个参数的地址,则接口内部无法做类型校验(当然也可以再把类型名称也放入到另一个vector容器一起传入,但是这样不美观且操作繁琐)。因此我的解决方案是用类继承的方式管理,我的实现代码如下:
// aidata.h
#ifndef AI_DATA_H_
#define AI_DATA_H_
/* Useage:
double* pd=new double(3.45);
std::vector<std::shared_ptr<BaseAIData>> params={
AIDATA(int,1),AIDATA(float,2),AIDATA(double*,pd)};
std::cout<<"param 0:"<<GET_DATA(int,params[0])<<std::endl;
std::cout<<"param 1:"<<GET_DATA(int,params[1])<<std::endl;
std::cout<<"param 2:"<<GET_DATA(int,params[2])<<std::endl;
*/
#include<string>
#include<iostream>
// 包装数据
#define AIDATA(Type,Data) std::shared_ptr<BaseAIData>(new AIData<Type>(Data,#Type))
// 获取数据
#define GET_DATA(Type,ptrBaseAIData) ptrBaseAIData->get_data<Type>(#Type)
template<typename T> class AIData;
class BaseAIData{
public:
std::string get_type(){
return type;
}
bool check_type(const std::string& type){
if(type!=this->type){
std::cout<<"Error:check type fail."<<std::endl;
return false;
}
return true;
}
template<typename T>
T get_data(const std::string& type){
T data;
if(!check_type(type)){
return data;
}
AIData<T>* ptr=static_cast<AIData<T>*>(this);
return ptr->get_data();
}
protected:
std::string type;
};
template<typename T>
class AIData:public BaseAIData{
public:
AIData(const T& data,const std::string& type){
this->data=data;
this->type=type;
}
T get_data(){
return data;
}
private:
T data;
}
#endif
那么,最终的接口可以定义成:
#include<vector>
#include"BaseAIData.h"
// 基类
class BaseAIModule{
public:
virsual bool init(const std::vector<std::shared_ptr<BaseAIData>>& params)=0;
virsual bool run(const std::vector<std::shared_ptr<BaseAIData>>& params,std::vector<std::shared_ptr<BaseAIData>>& outs)=0;
virsual bool release()=0;
protected:
std::string moduleName;
}