我们只要用过一些成熟的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"));
|
|