我们只要用过一些成熟的lua对c++的绑定,例如SLB、luabind或者其他,就会想:为什么它们会这么神奇,可以在C++实现参数数目任意、参数类型任意的函数。现在我们来探讨它们的本质,这里只讨论它们的最初原型,当然现实的bind会非常复杂。
例如:实现调用lua函数的通用方法;
call("add",112, 2323.33); // 调用lua 的add方法,参数是一个整数和一个double
call("print","helloworld");// 调用lua 的 print 方法,参数是一个C-style 字符串"helloworld"
call("print",222222);// 调用lua 的 print 方法,参数是一个整数
将我们后面讨论的方法稍稍修改下,也可以实现上面的神奇调用。
核心思想
对每种不同的参数类型 ,分别调用不同的处理函数Do()
//原型要首先声明
template<typename T>
struct Trait
{
static void Do(T t);
};
//利用偏特化
template<>
struct Trait<int>
{
static void Do(int t)
{
std::cout<<" Type int "<<t ;
}
};
template<>
struct Trait<float>
{
static void Do(float t)
{
std::cout<<"Type float "<<t ;
}
};
template<>
struct Trait<double>
{
static void Do(double t)
{
std::cout<<" Type double "<<t ;
}
};
//char const *类型 无法从这里实例化,WHY
template<>
struct Trait<char*>
{
static void Do(char* t)
{
std::cout<<" Type char* "<<t ;
}
};
//奇怪的是 char *类型 无法从这里实例化 WHY
template<>
struct Trait<char const*>
{
static void Do(char const* t)
{
std::cout<<" Type char const* "<<t ;
}
};
template<>
struct Trait<std::string>
{
static void Do(std::string t)
{
std::cout<<" Type std::string "<<t ;
}
};
关键的地方
template<typename T1, typename T2>
void Call(T1 t1, T2 t2)//自动推导
{
// 在函数内部,T1、T2已经被推导出来了,因此后面可以直接T1、T2来实例化其他的模版
//衔接前后
Trait<T1>::Do(t1);
Trait<T2>::Do(t2);
};
template<typename T1,typename T2,typename T3 ,typename T4>
void Call(T1 t1,T2 t2,T3 t3 ,T4 t4)
{
Trait<T1>::Do(t1);
Trait<T2>::Do(t2);
Trait<T3>::Do(t3);
Trait<T4>::Do(t4);
};
实现的效果:
Call(11,1111);
Call("hello","world");
Call("HelloGuys");
Call(11, 22.2, 232.3f, std::string("fdsaf"));
联系客服