//traits.h
/*制定输入 - 输出类型规则*/
template <class T>
struct RtnType {
typedef T return_type;//默认返回类型和输入类型一致
};
template <class T>
struct RtnType<T*> {//特化,当输入的是指针类型,返回类型规定为指针原型
typedef T return_type;
};
template <class T>
struct RtnType<const T*> {//特化常量指针类型,当输入的是常量指针类型,返回类型规定为原型指针
typedef T* return_type;
};
// 你可以根据需要,特化不同的输入输出规则
/*特性萃取器*/
template <class unknown_class>
struct unknown_class_traits {
typedef typename unknown_class::return_type return_type;
};
/*特性萃取器 —— 针对指针*/
template <class T>
struct unknown_class_traits<T*> {
typedef T return_type;
};
/*特性萃取其 —— 针对常量指针*/
template <class T>
struct unknown_class_traits<const T*> {
typedef const T return_type;
};
#define RType typename unknown_class_traits<RtnType<T>>::return_type
/*决定使用哪一个类型*/
template <class T>
inline RType return_type(T) {
return RType();
}
/*用户统一接口*/
template <class T>
inline RType interface(T param)
{
const type_info& Rtid = typeid(RType);
const type_info& Tid = typeid(T);
const char* Rname = Rtid.name();
const char* Tname = Tid.name();
bool bRet = compare_type(param, RType());//
return implement(param, RType());//static dispatch here. 编译期静态分发
}
/*接口默认实现*/
template <class T>
inline RType implement(T param, RType typ)
{
cout << "General Version of implement" << endl;
return RType();
}
template <class T, T Val>
struct var_constant
{
const T value = Val;
using value_type = T;
using type = var_constant;
};
template <bool Val>
struct var_constant<bool, Val>//特化bool类型
{
const bool value = Val;
using value_type = bool;
using type = var_constant;
};
template<class T1, class T2>
struct is_same_type
{
static const bool value = false;
};
template<class T>
struct is_same_type<T, T>
{
static const bool value = true;
};
template<class T1, class T2>
inline bool compare_type(T1, T2)
{
var_constant<bool, is_same_type<T1, T2>::value> bConstant;
return bConstant.value;
};
//main.cpp
#include "traits.h"
class A
{
};
struct B
{
};
A implement(A, A)
{
cout << "use object value type version" << endl;
return A();
}
B implement(B*, B)
{
cout << "use object raw ptr type version" << endl;
return B();
}
int implement(int, int)
{
cout << "use raw type version." << endl;
return 0;
}
int implement(int*, int)
{
cout << "use raw ptr version." << endl;
return 0;
}
int* implement(const int*, int*)
{
cout << "use const raw ptr version." << endl;
return 0;
}
int main() {
B b;
A a;
int value = 1;
int *p = &value;
const int* cp = p;
A v1 = interface(a);
B v2 = interface(&b);
int v3 = interface(p);
int* v4 = interface(cp);
char ch = getchar();
return 0;
}
通过一些模板技巧,使得模块内部可以根据用户输入数据类型,返回不同的数据,实现接口的统一,并在接口内实现静态分发。
另一种基于模板的静态分发,可以采用CRTP,以下是基于CRTP技术实现编译期多态的例子,仅供参考:
template<class T>
class BaseObj
{
public:
inline void Interface()
{
return static_cast<T*>(this)->Implement();
}
inline void Implement()
{
}
~BaseObj()
{
static_cast<T*>(this)->Destory();
}
inline void Destory()
{
}
protected:
// T m_subObj;// error. 基类中不能用子类来创建成员变量,这也是c++基本要求
};
class Drive :public BaseObj<Drive>
{
public:
Drive()
{
m_handle = new int[4];
}
//void Implement()//解开注释,观察效果,
//{
// printf("Drive Implement.\r\n");
//}
~Drive()
{
printf("Drive Deconstructed.\r\n");
//Don't do any clear operation, put these into Destory call
}
void Destory()
{
printf("Drive Destoryed.\r\n");
delete[] m_handle;
m_handle = nullptr;//important 防止Destory被重复调用导致重复释放
}
private:
int* m_handle;
};
// 使用CRTP技术创建的不同子类对象,由于基类都是不一样的,因此不能统一放入容器中使用,可以用std::Any类型对它们进行一层包装,这样就可以放进容器了(参考:https://blog.csdn.net/yuanshenqiang/article/details/143984861)。
int main()
{
Drive* d1 = new Drive;
BaseObj<Drive>* dd1 = new Drive;
dd1->Interface();
d1->Interface();
delete dd1;
//d1->Destory();//手动调用Destory
delete d1;//由基类的析构函数发起Destory调用
return 0;
}
相比而言动态分发就是常规的虚函数——继承体系,基于该体系,可以实现各种设计模式。比如一个有趣的例子:c++的二次分发与访问者模式-CSDN博客