这几天本来想将Lua_Tinker移植到Linux上去的,但是由于VC中的模板写法与gcc中的模板写法有些不同之处,比如下面一段代码:
struct pop_ { template<typename T> static T invoke(lua_State *L, int index) { return lua2type<T>::invoke(L, index); } template<> static char* invoke(lua_State *L, int index) { return (char*)lua_tostring(L, index); } template<> static const char* invoke(lua_State *L, int index) { return (const char*)lua_tostring(L, index); } };
在VS2003中就没有问题,但是在Linux中用g++编译就会出现问题,g++不支持这种写法。因为Lua_Tinker全是模板,而且有很多这种模板与全特化同在一个类或者结构中的模板,而至今(到笔者写稿时为止)也没有找到一种解决方案可以将上面所示代码正确移植到Linux,所以Lua_Tinker向Linux的移植到现在为止还并没有成功!虽然,这次移植并没有成功,但是我还是在这次移植中得到了许多关于模板的写法的经验。下面就介绍一下类模板中的函数模板在类内定义与类外定义的两种写法:
第一种:类内定义
// 类内定义写法 template<typename T> class CA { template<typename RET> static RET f() { RET t; return t; } };
第二种:类外定义
// 类外定义的写法 template<typename T> class CA { template<typename RET> static RET f(); }; template<typename T> template<typename RET> RET CA<T>::f() { RET t; return t; }
以上两中写法在VC中和g++中都可以顺利地编译!关于文章开头的第一段代码,如何写才能在g++中顺利编译呢?由于g++不支持类模板中函数模板全特化的template<>写法,但支持template<int>,template<char*>等等的全特化写法,所以将文章第一段代码写为如下形式即可在g++中编译通过:
struct pop_ { template<typename T> static T invoke(lua_State *L, int index) { return lua2type<T>::invoke(L, index); } template<char*> static char* invoke(lua_State *L, int index) { return (char*)lua_tostring(L, index); } template<const char*> static const char* invoke(lua_State *L, int index) { return (const char*)lua_tostring(L, index); } };
但是,由于g++不支持将void,float,double三种类型作为模板参数,所以template<void>,template<float>,template<double>在g++中编译会出错!